成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

從零開始寫個(gè)編譯器吧 - 詞法分析器是一個(gè)狀態(tài)機(jī)

calx / 2729人閱讀

摘要:詞法分析器本身就是一個(gè)狀態(tài)機(jī),生成這個(gè)狀態(tài)機(jī)有很多種方法,而我打算采取手寫的方式。狀態(tài)機(jī)不斷從源代碼即一個(gè)字符串中讀入一個(gè)一個(gè)字符,讀到不同的字符將使?fàn)顟B(tài)機(jī)的狀態(tài)從一個(gè)狀態(tài)變化到另外一個(gè)狀態(tài)。

詞法分析器 Tokenizer 本身就是一個(gè)狀態(tài)機(jī),生成這個(gè)狀態(tài)機(jī)有很多種方法,而我打算采取手寫的方式。因?yàn)?tao 語言的詞法還是相對比較簡單的,手寫不成問題。
先新建一個(gè)LexicalAnalysis.java 于 src/com/taozeyu/taolan/analysis之中。

package com.taozeyu.taolan.analysis;

public class LexicalAnalysis {
    private static enum State {
        Normal,
        Identifier, Sign, Annotation,
        String, RegEx, Space;
    }
}

看看其中定義的 State 枚舉類型,其中有6種類型與 Token 的類型對應(yīng)。特別的,Normal 類型表示狀態(tài)可以轉(zhuǎn)化成任何一種單詞類型的狀態(tài)。我還是貼一張圖來描述著7種狀態(tài)吧。

如圖所示,Normal 狀態(tài)作為狀態(tài)機(jī)的初始狀態(tài),也是各個(gè)其他狀態(tài)的中轉(zhuǎn)狀態(tài)。狀態(tài)機(jī)不斷從源代碼(即一個(gè)字符串)中讀入一個(gè)一個(gè)字符,讀到不同的字符將使?fàn)顟B(tài)機(jī)的狀態(tài)從一個(gè)狀態(tài)變化到另外一個(gè)狀態(tài)。

例如,在 Normal 狀態(tài)下讀到了“#”將使?fàn)顟B(tài)變?yōu)?Annotation ,反過來如果繼續(xù)讀到一個(gè)“ "即換行符號,則會從 Annotation 狀態(tài)回到 Normal 狀態(tài)。當(dāng)然,對于 Identifier、 Sign、Space 的狀態(tài)變化更為復(fù)雜一點(diǎn),但僅憑當(dāng)前讀入的那一個(gè)字符就可以變化到正確的狀態(tài)(圖中沒有表現(xiàn))。

此外,當(dāng)源代碼讀完了,如果狀態(tài)機(jī)處于Normal狀態(tài),此時(shí)應(yīng)該生成一個(gè)EndSymbol。但如果此時(shí)不處于 Normal 狀態(tài),那就有問題了,必須拋出一個(gè)異常。(這種情況是程序員把源代碼本身寫錯(cuò)了,例如最后一個(gè)字符串少右邊的"之類的。)
至此,我就可以知道 LexicalAnalysis 類應(yīng)該有那些函數(shù)可供(Parser)調(diào)用啦。

package com.taozeyu.taolan.analysis;

public class LexicalAnalysis {
    private static enum State {
        Normal,
        Identifier, Sign, Annotation,
        String, RegEx, Space;
    }

    public LexicalAnalysis(Reader reader) {
        //TODO
    }

    Token read() throws IOException, LexicalAnalysisException {
        //TODO
    }
}

至此,語法分析器 Parser 可以不斷調(diào)用 read() 函數(shù)來獲得 Token 對象,直到讀到 EndSymbol 或拋出異常為止。注意 read() 函數(shù)的聲明中 throws LexicalAnalysisException 這段。當(dāng)這個(gè)異常被拋出,說明源代碼寫錯(cuò)了。這不是編譯器的錯(cuò),而是程序員的錯(cuò),編譯器只管把這個(gè)錯(cuò)報(bào)出來,讓程序員去改代碼。

當(dāng)然對于程序員而言,這是個(gè)語法錯(cuò)誤。但是既然我是在寫編譯器,我可能要把這些錯(cuò)誤分得更細(xì)一點(diǎn)。因?yàn)檫@個(gè)錯(cuò)誤是在單詞化(Tokenization)階段拋出的,因此我們將其稱之為詞法錯(cuò)誤吧,以便區(qū)分。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/64212.html

相關(guān)文章

  • 從零開始寫個(gè)譯器系列

    摘要:是的,這個(gè)系列將呈現(xiàn)一個(gè)完整的編譯器從無到有的過程。但在寫這個(gè)編譯器的過程中,我可不會偷工減料,該有的一定會寫上的。該語言的虛擬機(jī)將運(yùn)行于之上,同時(shí)編譯器將使用實(shí)現(xiàn)。我早有寫編譯器的想法之前沒寫過,故希望一邊寫編譯器一邊完成這個(gè)系列。 是的,這個(gè)系列將呈現(xiàn)一個(gè)完整的編譯器從無到有的過程。當(dāng)然,為了保證該系列內(nèi)容的簡潔(也為了降低難度),僅僅保證編譯器的最低要求,即僅能用。但在寫這個(gè)編譯...

    genedna 評論0 收藏0
  • 從零開始寫個(gè)譯器 - 開始詞法析器(1)

    摘要:上一章提到我要手寫詞法分析器這個(gè)狀態(tài)機(jī),嗯,那就讓我們開始吧。實(shí)際上,在狀態(tài)機(jī)不斷接受字符的過程中,會先調(diào)用將其緩存,并在適當(dāng)?shù)臅r(shí)機(jī)調(diào)用生成。一個(gè)典型的狀態(tài)機(jī),處于不同狀態(tài),對于接受的參數(shù)進(jìn)行不同的操作。 上一章提到我要手寫詞法分析器這個(gè)狀態(tài)機(jī),嗯,那就讓我們開始吧。 public class LexicalAnalysis { private...

    littleGrow 評論0 收藏0
  • 從零開始寫個(gè)譯器 - 開始詞法析器(3)

    摘要:在之前的章節(jié)第章從零開始寫個(gè)編譯器吧開始寫詞法分析器中我有說,我將函數(shù)設(shè)計(jì)成主動調(diào)用的形式,而則是被動調(diào)用的形式。接下來本系列將進(jìn)入編寫語法分析器的階段,不過在此之前,我將抽出一點(diǎn)時(shí)間介紹一下語言本身。 上周周末旅游去了,就沒更新了,雖然回到海拔0m的地區(qū),不過目前似乎還在缺氧,所以本次就少更點(diǎn)吧。 這章將結(jié)束詞法分析的部分。 在之前的章節(jié)(第7章從零開始寫個(gè)編譯器吧 - 開始寫詞...

    Barrior 評論0 收藏0
  • 從零開始寫個(gè)譯器 - 開始詞法析器(2)

    摘要:讀到一個(gè)非數(shù)字非英文字母非下劃線字符。此時(shí)立即跳轉(zhuǎn)回狀態(tài)。以一個(gè)雙引號開始,并以一個(gè)雙引號結(jié)束。另外,在讀和時(shí)源代碼不許結(jié)束,即讀到符號,若結(jié)束,則判定為詞法錯(cuò)誤。對于而言,也有一些其他的詞法錯(cuò)誤判定,如,不能換行。 對于非 Normal 狀態(tài),我只需要關(guān)心兩個(gè)過程: 何時(shí)從 Normal 跳轉(zhuǎn)到該狀態(tài); 何時(shí)從該狀態(tài)跳回 Normal 狀態(tài)。 在上一章中,我已經(jīng)寫好了從 Nor...

    MarvinZhang 評論0 收藏0
  • 從零開始寫個(gè)譯器 - tao語言的詞法析器(Tokenizer)的類型定義

    摘要:要為語言設(shè)計(jì)詞法分析器,首先得知道語言是一種什么樣的語言。,不過首先我們得把詞法分析器能生成的單詞類型定義好了。 要為 tao 語言設(shè)計(jì)詞法分析器,首先得知道 tao 語言是一種什么樣的語言。不過呢,我腦海里還沒有 tao 語言具體形象。我還是先貼一段 tao 語言的代碼,大概展示下這是怎么回事吧。 def say_hello_world(who) print hello ...

    qpal 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<