從零開始寫個編譯器吧 - tao 語言的文法定義(下)
目前為止我們創建的文件列表:
- com.taozeyu.taolan.analysisn|- FirstSetConstructorn|- LexicalAnalysisn|- LexicalAnalysisExceptionn|- NonTerminalSymboln|- SignParsern|- SyntacticDefine[新]n|- TerminalSymboln|- Tokenn
上一章中我們提到了 4 個方法:
node
token
or
sign
它們可以用來描述非終結符和展開式的形式,那麼它們又是如何工作的呢?
SyntacticDefine.java 文件中定義了一些 static 方法。
static NonTerminalSymbol getNonTerminalSymbol(Exp exp) {n return expContainer.get(exp);n }n private static NonTerminalSymbol node(Exp exp) {n return new NonTerminalSymbol(exp);n }n private static NonTerminalSymbol node() {n return new NonTerminalSymbol(null);n }n private static TerminalSymbol token(Type type, String value) {n return new TerminalSymbol(type, value);n }n private static TerminalSymbol token(Type type) {n return new TerminalSymbol(type, null);n }n
可以看出,這些方法只是稍微封裝了一下,具體還要繼續追蹤 TerminalSymbol.java 和 NotTerminalySymbol.java。
先看看 TerminalSymbol.java 的相關代碼:
public final Type type;npublic final String value;nfinal boolean careValue;nTerminalSymbol(Type type, String value) {n this.type = type;n this.value = value;n this.careValue = careValueTypeSet.contains(type);n}n
原來只是直接保存成變數罷了。
再看 NotTerminalySymbol.java 的相關代碼:
final Exp exp;nCharacter sign = null;nfinal ArrayList<Object[]> expansionList = new ArrayList<>();n
定義了這些成員變數,其中 expansionList 代表展開式,它由一組 Object[] 組成。
NonTerminalSymbol(Exp exp) {n this.exp = exp;n }n NonTerminalSymbol or(Object...args) {n expansionList.add(args);n return this;n }n NonTerminalSymbol sign(char sign) {n this.sign = sign;n return this;n }n
NotTerminalySymbol 也是把這些定義的東西保存起來,只不過每個方法返回 this,因此允許我連續調用這些方法。
特別的,注意如下代碼:
final ArrayList<TerminalSymbol> banList = new ArrayList<>();n NonTerminalSymbol ban(TerminalSymbol...args) {n for(TerminalSymbol node:args) {n banList.add(node);n }n return this;n }n
這個方法可以紀錄被 ban 掉的一組非終結符,紀錄這些東西有什麼用,將在隨後的章節介紹。
推薦閱讀:
※c/c++能做什麼?
※從零開始寫個編譯器吧 - tao 語言的文法定義(上)
※好好用滑鼠
※程序列印字元畫?
※【修真院「純潔」系列之五】醉酒和加班