目前为止我们创建的文件列表:
|- 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 掉的一组非终结符,纪录这些东西有什么用,将在随后的章节介绍。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。