從零開始寫個編譯器吧 - 程序流控制

目前爲止咱們建立的文件列表:java

|- com.taozeyu.taolan.analysis
    |- FirstSetConstructor
    |- LexicalAnalysis
    |- LexicalAnalysisException
    |- NonTerminalSymbol
    |- SignParser
    |- SyntacticDefine
    |- TerminalSymbol
    |- Token

咱們來看看 SyntacticDefine.java 文件(142~159 行):node

node(Exp.StartChunk).or(Exp.Chunk),
    node(Exp.Chunk).or(
            Exp.SpaceOrEnter,
            node().or(Exp.Line, Exp.Space,
                      node().or(token(Type.NewLine), Exp.SpaceOrEnter)
                            .or(token(Type.EndSymbol))).sign('?')
    ).sign('*'),
    node(Exp.Line).or(Exp.Command)
                  .or(Exp.Operate)
                  .or(Exp.DefineVariable)
                  .or(Exp.DefineFunction)
                  .or(Exp.IfElseChunk)
                  .or(Exp.WhileChunk)
                  .or(Exp.DoUntilChunk)
                  .or(Exp.ForEachChunk)
                  .or(Exp.TryCatch)

咱們定義了三個命名了的非終結符:StartChunk、Chunk、Line。函數

其中 StartChunk 是咱們展開式的全部起點,每個 tao 語言的源代碼文件都從 StartChunk 開始展開。這裏我簡單的將其展開爲 Chunk。code

而 Chunk 表示一個語法塊,它由許多行(Line)構成。可是在文法定義中,我必須爲其每行的首位定義許多必要的雜項。從展開式中,能夠看出,除了 Line 這個非終結符,還有其餘一些非終結符:SpaceOrEnter、Space、NewLine、EndSymbol。token

這些非終結符的含義,能夠在 SyntacticDefine.java 文件的對應位置找到(可使用 ctrl+F 搜索),只要找到它們對應的展開式,相信不難理機它們的含義。特別的 EndSymbol,便是 Tokenizer 表明源代碼解析結束的終止符。it

Chunk 是語言文法定義中最重要的非終結符。io

再看看 Line,這個非終結符能夠簡單的理解爲「一行代碼」。天然,Chunk 就是由不少行代碼組成的。特定的一行代碼能夠寫不少東西,可能用於定義一個變量,也多是一行賦值語句,也多是在調用一個方法。總之,它能夠是不少不少種東西。從以前這段代碼中,能夠看到,它有不少種展開式。變量

你們能夠經過 GitHub 自行查看 Line 展開後對應的非終結符具體還能再如何展開,但受限於篇幅,我只會對其中一部分進行講解。搜索

node(Exp.Operate).or(Exp.L0Expression, Exp.When)

Operate 是 Line 可能展開的形式之一,在 tao 語言中,以下代碼就是一行典型的 Operate:語法

count = size * 2 + 1

從表達式來看,它是由一個 0 級表達式(L0Expression)和一個 When 類型的非終結符組成。

其中 L0Expression 表明一個表達式,它多是一行賦值語句,也多是一個函數調用,它是咱們文法定義中一個比較複雜,但卻處處都會出現的東西,我會在以後的章節進行簡單介紹。

隨後,緊接而來的是 When 非終結符。咱們來看看 When 的定義是怎麼樣的:

node(Exp.When).or(node().or(Exp.SplitSpaceSign).sign('?'),
              node().or(token(Type.Keyword, "when"), Exp.SplitSpaceSign, Exp.L0Expression).sign('?'))

它主要由一個 when 關鍵字緊接令一個 0 級表達式組成。但特別注意結尾的 .sign('?') 數量詞代表,整個非終結符 When 都是可選的。也就是說,Operate 後面不寫 when 也沒有關係。

一行寫了 when 的 tao 語言代碼多是以下形式:

count = size * 2 + 1 when size > 1

這是一種簡寫形式,在 tao 語言中等價於以下寫法:

if size > 1
    count = size * 2 + 1
end

接下來,咱們來看看 DefineVariable 非終結符:

node(Exp.DefineVariable).or(token(Type.Keyword, "var"), Exp.Space, Exp.DefineVariableElement,
                            node().or(Exp.Space, token(Type.Sign, ","),
                            Exp.SpaceOrEnter, Exp.DefineVariableElement).sign('*'))

注意到 DefineVariableElement 彷佛還能夠繼續展開:

node(Exp.DefineVariableElement).or(token(Type.Identifier), Exp.Space,
                                   node().or(token(Type.Sign, "="), Exp.Space, Exp.L0Expression).sign('?'))

這代表 tao 語言中定義局部變量的形式以下:

var cat = take_cat(), dog = Dog.alloc().init()

固然,從 DefineVariableElement 的展開式中的 .sign('?') 量詞能夠知道,去掉等號以及等號後面的表達式,也是合法的局部變量定義:

var cat, dog

甚至,一次只定義一個變量,固然也是能夠的:

var cat

在接下來,就是 IfElseChunk 了:

node(Exp.IfElseChunk).or(
                    token(Type.Keyword, "if"), Exp.Space,
                    Exp.L0Expression, Exp.SpaceOrEnter,
                    Exp.Chunk,
                    node().or(token(Type.Keyword, "elsif"), Exp.Space,
                              Exp.L0Expression, Exp.SpaceOrEnter,
                              Exp.Chunk).sign('*'),
                    node().or(token(Type.Keyword, "else"), Exp.SpaceOrEnter,
                              Exp.Chunk).sign('?'),
                    Exp.SpaceOrEnter,
                    token(Type.Keyword, "end"))

注意到,這裏展開出現了四種關鍵字:if、elsif、else、end。

tao 語言中,一個典型的 if-else-chunk 是以下這樣子的:

if check_condition(100)
    a = 1 + 1
elsif a > 2
    a += 3
else
    a = 0
end

固然,elsif 能夠重複出現0~N 次:

if check_condition(100)
    a = 1 + 1
elsif a > 2
    a += 3
elsif a > 3
    a += 4
elsif a > 4
    a += 7
else
    a = 0
end

而 else 是可選的,能夠沒有:

if check_condition(100)
    a = 1 + 1
elsif a > 2
    a += 3
end

也能夠只剩下 if 和 end:

if check_condition(100)
    a = 1 + 1
end

從文法定義的角度來看,if-else-chunk 這種形式的變化,我經過數量詞 sign('*') 和 sign('?') 來控制。

相關文章
相關標籤/搜索