標籤:

從零開始寫個編譯器吧 - tao 語言的文法定義(下)

目前為止我們創建的文件列表:

- com.taozeyu.taolan.analysisn|- FirstSetConstructorn|- LexicalAnalysisn|- LexicalAnalysisExceptionn|- NonTerminalSymboln|- SignParsern|- SyntacticDefine[新]n|- TerminalSymboln|- Tokenn

上一章中我們提到了 4 個方法:

  1. node

  2. token

  3. or

  4. 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 語言的文法定義(上)
好好用滑鼠
程序列印字元畫?
【修真院「純潔」系列之五】醉酒和加班

TAG:编译器 | 程序 |