目前为止我们创建的文件列表:
|- com.taozeyu.taolan.analysis |- FirstSetConstructor |- LexicalAnalysis |- LexicalAnalysisException |- NonTerminalSymbol |- SignParser |- SyntacticDefine[新] |- TerminalSymbol |- Token
上一章中我们提到了 4 个方法:
node
token
or
sign
它们可以用来描述非终结符和展开式的形式,那么它们又是如何工作的呢?
SyntacticDefine.java 文件中定义了一些 static 方法。 static NonTerminalSymbol getNonTerminalSymbol(Exp exp) { return expContainer.get(exp); } private static NonTerminalSymbol node(Exp exp) { return new NonTerminalSymbol(exp); } private static NonTerminalSymbol node() { return new NonTerminalSymbol(null); } private static TerminalSymbol token(Type type, String value) { return new TerminalSymbol(type, value); } private static TerminalSymbol token(Type type) { return new TerminalSymbol(type, null); }
可以看出,这些方法只是稍微封装了一下,具体还要继续追踪 TerminalSymbol.java 和 NotTerminalySymbol.java。
先看看 TerminalSymbol.java 的相关代码:
public final Type type; public final String value; final boolean careValue; TerminalSymbol(Type type, String value) { this.type = type; this.value = value; this.careValue = careValueTypeSet.contains(type); }
原来只是直接保存成变量罢了。
再看 NotTerminalySymbol.java 的相关代码:
final Exp exp; Character sign = null; final ArrayList<Object[]> expansionList = new ArrayList<>();
定义了这些成员变量,其中 expansionList 代表展开式,它由一组 Object[] 组成。
NonTerminalSymbol(Exp exp) { this.exp = exp; } NonTerminalSymbol or(Object...args) { expansionList.add(args); return this; } NonTerminalSymbol sign(char sign) { this.sign = sign; return this; }
NotTerminalySymbol 也是把这些定义的东西保存起来,只不过每个方法返回 this,因此允许我连续调用这些方法。
特别的,注意如下代码:
final ArrayList<TerminalSymbol> banList = new ArrayList<>(); NonTerminalSymbol ban(TerminalSymbol...args) { for(TerminalSymbol node:args) { banList.add(node); } return this; }
这个方法可以纪录被 ban 掉的一组非终结符,纪录这些东西有什么用,将在随后的章节介绍。