编译器-FIRST集合

 

语法分析器的两个重要函数 FIRST和FOLLOW

FIRST的定义

FIRST(α),可从α推导得到的串的首符号的集合

1.如果X是一个终结符,那么FIRST(X) = X

2.如果X是一个非终结符,且X -> Y1Y2...Yk 是一个产生式,

 1)如果Y1..Yj-1=>ε 那么 FIRST(Yj) 添加到 FIRST(X)

 2)如果Y1...Yk=>ε,那么ε添加到FIRST(X)

3.如果X->ε是一个产生式,那么ε添加到FIRST(X)

代码实现

1.符号类

import java.util.Objects;

/**
 * 符号
 */
public class Symbol {

    protected String name;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Symbol symbol = (Symbol) o;
        return Objects.equals(name, symbol.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}

2.终结符

public class Terminal extends Symbol {

    public static Terminal of(String name) {
        Terminal result = new Terminal();
        result.name = name;
        return result;
    }
}

 

3.非终结符

/**
 * 非终结符
 */
public class Nonterminal extends Symbol {

    public static Nonterminal of(String name) {
        Nonterminal result = new Nonterminal();
        result.name = name;
        return result;
    }
}

  

 4.产生式

 

import java.util.List;
import java.util.Objects;

/**
 * 产生式
 */
public class Production {

    /** 产生式头 */
    private Nonterminal head;
    /** 产生式体 */
    private List<Symbol> body;

    public Nonterminal getHead() {
        return head;
    }

    public List<Symbol> getBody() {
        return body;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Production that = (Production) o;
        return Objects.equals(head, that.head) && Objects.equals(body, that.body);
    }

    @Override
    public int hashCode() {
        return Objects.hash(head, body);
    }
}

  

5.文法

package com.kashin.grammar.model;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 文法
 */
public class Grammar {

    /** 开始符号 */
    private Nonterminal start;
    /** 产生式 */
    private List<Production> productions;

}

  

 6.FIRST函数

/**
     * P140 FIRST(X)集合
     * @param token
     * @return
     */
    public Set<Terminal> first(Symbol token) {

        Set<Terminal> result = new HashSet<>();

        // X 是一个终结符号
        // 1) if X is a terminal, then FIRST(X) = {X}
        if (token instanceof Terminal) {
            result.add((Terminal) token);
            return result;
        }

        List<Production> productionList = getProduction((Nonterminal) token);
        for (Production production : productionList) {

            // 如果 X->ε是一个产生式,那么将ε加入到FIRST(X)
            if (production.getBody().size() == 1 && production.getBody().get(0).equals(Terminal.of("ε"))) {
                result.add(Terminal.of("ε"));
            } else {
                Set<Terminal> firstSet = first(production.getBody());
                result.addAll(firstSet);
            }
        }

        return result;
    }

  

/**
     * P140 FIRST(X)集合
     * @param tokens
     * @return
     */
    public Set<Terminal> first(List<Symbol> tokens) {

        // 是否全部包含ε
        boolean allContainsEpsilon = true;
        Set<Terminal> result = new HashSet<>();
        for (Symbol token : tokens) {

            Set<Terminal> firstSet = first(token);
            for (Terminal terminal : firstSet) {
                if (terminal.equals(Terminal.of("ε"))) {
                    continue;
                }
                result.add(terminal);
            }

            if (!firstSet.contains(Terminal.of("ε"))) {
                allContainsEpsilon = false;
                break;
            }
        }

        // 如果对于所有的j=1,2,...,k,ε在FIRST(Yj)中,那么将ε加入到FIRST(X)
        if (allContainsEpsilon) {
            result.add(Terminal.of("ε"));
        }

        return result;
    }

  

posted @ 2023-10-21 09:29  kashin05  阅读(56)  评论(0)    收藏  举报