编译器-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;
}
浙公网安备 33010602011771号