摘要:詞法分析器本身就是一個狀態(tài)機,生成這個狀態(tài)機有很多種方法,而我打算采取手寫的方式。狀態(tài)機不斷從源代碼即一個字符串中讀入一個一個字符,讀到不同的字符將使狀態(tài)機的狀態(tài)從一個狀態(tài)變化到另外一個狀態(tài)。
詞法分析器 Tokenizer 本身就是一個狀態(tài)機,生成這個狀態(tài)機有很多種方法,而我打算采取手寫的方式。因為 tao 語言的詞法還是相對比較簡單的,手寫不成問題。
先新建一個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 的類型對應。特別的,Normal 類型表示狀態(tài)可以轉(zhuǎn)化成任何一種單詞類型的狀態(tài)。我還是貼一張圖來描述著7種狀態(tài)吧。
如圖所示,Normal 狀態(tài)作為狀態(tài)機的初始狀態(tài),也是各個其他狀態(tài)的中轉(zhuǎn)狀態(tài)。狀態(tài)機不斷從源代碼(即一個字符串)中讀入一個一個字符,讀到不同的字符將使狀態(tài)機的狀態(tài)從一個狀態(tài)變化到另外一個狀態(tài)。
例如,在 Normal 狀態(tài)下讀到了“#”將使狀態(tài)變?yōu)?Annotation ,反過來如果繼續(xù)讀到一個“ "即換行符號,則會從 Annotation 狀態(tài)回到 Normal 狀態(tài)。當然,對于 Identifier、 Sign、Space 的狀態(tài)變化更為復雜一點,但僅憑當前讀入的那一個字符就可以變化到正確的狀態(tài)(圖中沒有表現(xiàn))。
此外,當源代碼讀完了,如果狀態(tài)機處于Normal狀態(tài),此時應該生成一個EndSymbol。但如果此時不處于 Normal 狀態(tài),那就有問題了,必須拋出一個異常。(這種情況是程序員把源代碼本身寫錯了,例如最后一個字符串少右邊的"之類的。)
至此,我就可以知道 LexicalAnalysis 類應該有那些函數(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 這段。當這個異常被拋出,說明源代碼寫錯了。這不是編譯器的錯,而是程序員的錯,編譯器只管把這個錯報出來,讓程序員去改代碼。
當然對于程序員而言,這是個語法錯誤。但是既然我是在寫編譯器,我可能要把這些錯誤分得更細一點。因為這個錯誤是在單詞化(Tokenization)階段拋出的,因此我們將其稱之為詞法錯誤吧,以便區(qū)分。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/64212.html
摘要:是的,這個系列將呈現(xiàn)一個完整的編譯器從無到有的過程。但在寫這個編譯器的過程中,我可不會偷工減料,該有的一定會寫上的。該語言的虛擬機將運行于之上,同時編譯器將使用實現(xiàn)。我早有寫編譯器的想法之前沒寫過,故希望一邊寫編譯器一邊完成這個系列。 是的,這個系列將呈現(xiàn)一個完整的編譯器從無到有的過程。當然,為了保證該系列內(nèi)容的簡潔(也為了降低難度),僅僅保證編譯器的最低要求,即僅能用。但在寫這個編譯...
摘要:上一章提到我要手寫詞法分析器這個狀態(tài)機,嗯,那就讓我們開始吧。實際上,在狀態(tài)機不斷接受字符的過程中,會先調(diào)用將其緩存,并在適當?shù)臅r機調(diào)用生成。一個典型的狀態(tài)機,處于不同狀態(tài),對于接受的參數(shù)進行不同的操作。 上一章提到我要手寫詞法分析器這個狀態(tài)機,嗯,那就讓我們開始吧。 public class LexicalAnalysis { private...
摘要:在之前的章節(jié)第章從零開始寫個編譯器吧開始寫詞法分析器中我有說,我將函數(shù)設計成主動調(diào)用的形式,而則是被動調(diào)用的形式。接下來本系列將進入編寫語法分析器的階段,不過在此之前,我將抽出一點時間介紹一下語言本身。 上周周末旅游去了,就沒更新了,雖然回到海拔0m的地區(qū),不過目前似乎還在缺氧,所以本次就少更點吧。 這章將結(jié)束詞法分析的部分。 在之前的章節(jié)(第7章從零開始寫個編譯器吧 - 開始寫詞...
摘要:讀到一個非數(shù)字非英文字母非下劃線字符。此時立即跳轉(zhuǎn)回狀態(tài)。以一個雙引號開始,并以一個雙引號結(jié)束。另外,在讀和時源代碼不許結(jié)束,即讀到符號,若結(jié)束,則判定為詞法錯誤。對于而言,也有一些其他的詞法錯誤判定,如,不能換行。 對于非 Normal 狀態(tài),我只需要關心兩個過程: 何時從 Normal 跳轉(zhuǎn)到該狀態(tài); 何時從該狀態(tài)跳回 Normal 狀態(tài)。 在上一章中,我已經(jīng)寫好了從 Nor...
摘要:要為語言設計詞法分析器,首先得知道語言是一種什么樣的語言。,不過首先我們得把詞法分析器能生成的單詞類型定義好了。 要為 tao 語言設計詞法分析器,首先得知道 tao 語言是一種什么樣的語言。不過呢,我腦海里還沒有 tao 語言具體形象。我還是先貼一段 tao 語言的代碼,大概展示下這是怎么回事吧。 def say_hello_world(who) print hello ...
閱讀 2825·2021-11-11 17:21
閱讀 693·2021-09-23 11:22
閱讀 3637·2019-08-30 15:55
閱讀 1696·2019-08-29 17:15
閱讀 625·2019-08-29 16:38
閱讀 1001·2019-08-26 11:54
閱讀 2620·2019-08-26 11:53
閱讀 2814·2019-08-26 10:31