摘要:現在,讓我們來動手寫編譯器的第一個個文件吧。如其名字所示,這個類實例化的對象用于表示詞法分析器的產物。我希望詞法分析器從源代碼中提取出語素,并根據上下文推測出單詞類型,從而構造出對象。只需要構造出類型即可,進一步細分將在的構造函數中進行。
現在,讓我們來動手寫編譯器的第一個個java文件吧。本章要寫的類,是Token類。如其名字所示,這個類實例化的對象用于表示詞法分析器 Tokenizer 的產物。同時,也作為下一階段的語法分析器 Parser 的原料。
讓我們開始吧!先新建一個Token.java 于 src/com/taozeyu/taolan/analysis之中。
package com.taozeyu.taolan.analysis; public class Token { public static enum Type { Keyword, Number, Identifier, Sign, Annotation, String, RegEx, Space, NewLine, EndSymbol; } final Type type; final String value; Token(Type type, String value) { //TODO } }
如之前章節討論的一樣,Token對象應該包含類型和語素兩個屬性。注意這個 Type 枚舉類型,其內容就是我在上一章所說的 tao 語言應該具備的10種單詞類型。
我希望詞法分析器從源代碼中提取出語素,并根據上下文推測出單詞類型,從而構造出Token對象。但實際上,請注意Type這個枚舉類的三個類型:
Keyword, Number, Identifier
這三個類型不同之處?實際上這三個類型的形式極其類似(甚至 Keyword 和 Identifier 的形式是完全相同的),并且可以僅通過語素準確判定其類型。因此,我希望對詞法分析器 Tokenizer 隱藏著三種類型的區別,將這三種類型統稱 Identifier,以簡化編碼。
Token(Type type, String value) { if(type == Type.Identifier) { char firstChar = value.charAt(0); if(firstChar >= "0" & firstChar < "9") { type = Type.Number; } else if(keywordsSet.contains(value)){ type = Type.Keyword; } } this.type = type; this.value = value; }
于是,Token 對 Tokenizer 隱藏了 Number、Keyword 類型。Tokenizer 只需要構造出 Identifier 類型即可,進一步細分將在 Token 的構造函數中進行。
特別的,構造函數中引用了一個 keywordsSet 變量。實際上這個變量應該包含所有 tao 語言的關鍵字。此處稍稍定義一下。
private static final HashSetkeywordsSet = new HashSet<>(); static { keywordsSet.add("if"); keywordsSet.add("when"); keywordsSet.add("elsif"); keywordsSet.add("else"); keywordsSet.add("while"); keywordsSet.add("begin"); keywordsSet.add("until"); keywordsSet.add("for"); keywordsSet.add("do"); keywordsSet.add("try"); keywordsSet.add("catch"); keywordsSet.add("finally"); keywordsSet.add("end"); keywordsSet.add("def"); keywordsSet.add("var"); keywordsSet.add("this"); keywordsSet.add("null"); keywordsSet.add("throw"); keywordsSet.add("break"); keywordsSet.add("continue"); keywordsSet.add("return"); keywordsSet.add("operator"); }
好吧,tao 語言我能想出的可能有的關鍵字都在這里了。如果有遺漏或者多余,其實以后再回過頭來改也沒問題。
特別的,對于 Annotation、String、RegEx ,它們在源代碼中存在的形式和具體的語素并不完全等同。
#我是注釋(回車)
"我是一個字符串"
^s+d+$
對于 Tokenizer 而言,它傾向于讀出如上一整行信息。但是僅僅只加下劃線的文字是Token的語素。因此,我還需要再構造函數中對構造參數value進行進一步提取,以得到正確的語素。
另外,EndSymbol 的語素必須為空,不管 Tokenizer 傳入什么參數都必須如此。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64213.html
摘要:是的,這個系列將呈現一個完整的編譯器從無到有的過程。但在寫這個編譯器的過程中,我可不會偷工減料,該有的一定會寫上的。該語言的虛擬機將運行于之上,同時編譯器將使用實現。我早有寫編譯器的想法之前沒寫過,故希望一邊寫編譯器一邊完成這個系列。 是的,這個系列將呈現一個完整的編譯器從無到有的過程。當然,為了保證該系列內容的簡潔(也為了降低難度),僅僅保證編譯器的最低要求,即僅能用。但在寫這個編譯...
摘要:對于而言,終結符與的是對應的。這些內容,我將其稱之為終結符的值。對于一個非終結符的產生式對于非終結符,其對象的字段則會表現成如下形式。對于里面的數組,其元素可能為終結符對象非終結符對象或表達式枚舉對象。 首先是 TerminalSymbol.java 即終結符。 package com.taozeyu.taolan.analysis; import java.util.HashSet...
摘要:即創建一個文件,并寫下如下內容。然后以此緩存一個字符串,然后,通過調用來將這個字符串分割成一個一個運算符,并生成。語言中根據運算符長度分開儲存的。具體來說,如果運算符對應的字符串最短的是,最長的是。 上一章留下的那個大大的 TODO 表明,似乎還有什么東西沒寫完。沒錯,所以這一章我們來寫 Sign 狀態下的代碼。 所謂 Sign 狀態,即是用來處理和生成 Sign 類型的 Token...
摘要:這樣的程序或稱工具有很多現成的可供選擇包括在平臺上可用的,但既然我這個系列叫做從零開始寫個編譯器吧,那顯然如果我用現成的工具,那是犯規行為。 Parser(語法分析器)的編寫相對于 Tokenizer (詞法分析器)要復雜得多,因此,在編寫之前可能也會鋪墊得更多一些。當然,本系列旨在寫出一個編譯器,所以理論方面只會簡單介紹 tao 語言所涉及的部分。 之前的幾章中,我純手寫了tao 語...
摘要:在之前的章節第章從零開始寫個編譯器吧開始寫詞法分析器中我有說,我將函數設計成主動調用的形式,而則是被動調用的形式。接下來本系列將進入編寫語法分析器的階段,不過在此之前,我將抽出一點時間介紹一下語言本身。 上周周末旅游去了,就沒更新了,雖然回到海拔0m的地區,不過目前似乎還在缺氧,所以本次就少更點吧。 這章將結束詞法分析的部分。 在之前的章節(第7章從零開始寫個編譯器吧 - 開始寫詞...
閱讀 3216·2021-11-23 09:51
閱讀 3558·2021-11-09 09:46
閱讀 3655·2021-11-09 09:45
閱讀 2938·2019-08-29 17:31
閱讀 1860·2019-08-26 13:39
閱讀 2715·2019-08-26 12:12
閱讀 3614·2019-08-26 12:08
閱讀 2235·2019-08-26 11:31