日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

都灵JVM编程语言:使用ANTLR构建高级词法分析器

發布時間:2023/12/3 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 都灵JVM编程语言:使用ANTLR构建高级词法分析器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正如我在上一篇文章中所寫的那樣,我最近開始研究一種名為Turin的新編程語言。 可以在GitHub上找到適用于languag初始版本的編譯器。 我目前正在改進語言,并正在開發Maven和IntelliJ插件。 在這里和下一篇文章中,我將介紹編譯器和相關工具的不同組件。

編譯器的結構

編譯器需要做幾件事:

  • 獲取源代碼并生成抽象語法樹(AST)
  • 通過不同階段轉換AST以簡化處理。 我們基本上希望從非常接近語法的表示形式過渡到更易于處理的表示形式。 例如,我們可以對語言進行“去糖化”,將幾種(顯然)不同的結構表示為同一結構的變體。 一個例子? Java編譯器將字符串連接轉換為對StringBuffer.append的調用
  • 執行語義檢查。 例如,我們要檢查所有表達式是否都使用可接受的類型(我們不想對字符求和,對嗎?)
  • 產生字節碼
  • 第一步需要構建兩個組件:詞法分析器和解析器。 詞法分析器對文本進行操作并生成標記序列,而解析器將標記組合到用于創建AST的構造(類型聲明,語句,表達式等)中。 為了編寫詞法分析器和解析器,我使用了ANTLR。

    在本文的其余部分,我們將研究詞法分析器。 解析器和編譯器的其他組件將在以后的文章中討論。

    為什么要使用ANTLR?

    ANTLR是用于編寫詞法分析器和解析器的非常成熟的工具。 它可以生成多種語言的代碼,并具有良好的性能。 它維護良好,我確信它具有處理可能遇到的所有極端情況所需的所有功能。 除此之外,ANTLR 4可以編寫簡單的語法,因為它可以為您解決左遞歸定義。 因此,您不必編寫許多中間節點類型即可為表達式指定優先級規則。 我們將在分析器中對此進行更多介紹。

    Xtext使用了ANTLR(我已經使用了很多),并且在為.NET平臺 (一種用于.NET的EMF)構建模型驅動的開發框架時 ,我使用了ANTLR。 因此,我知道并信任ANTLR,因此沒有理由尋找其他選擇。

    當前的詞法分析器語法

    這是詞法分析器語法的當前版本。

    lexer grammar TurinLexer;@header {}@lexer::members {public static final int WHITESPACE = 1;public static final int COMMENTS = 2; }// It is suggested to define the token types reused in different mode. // See mode in-interpolation below tokens { VALUE_ID, TYPE_ID, INT, LPAREN, RPAREN, COMMA, RELOP, AND_KW, OR_KW, NOT_KW }// Of course keywords has to be defined before the rules for identifiers NAMESPACE_KW : 'namespace'; PROGRAM_KW : 'program'; PROPERTY_KW : 'property'; TYPE_KW : 'type'; VAL_KW : 'val'; HAS_KW : 'has'; ABSTRACT_KW : 'abstract'; SHARED_KW : 'shared'; IMPORT_KW : 'import'; AS_KW : 'as'; VOID_KW : 'Void'; RETURN_KW : 'return'; FALSE_KW : 'false'; TRUE_KW : 'true'; IF_KW : 'if'; ELIF_KW : 'elif'; ELSE_KW : 'else';// For definitions reused in mode in-interpolation we define and refer to fragments AND_KW : F_AND; OR_KW : F_OR; NOT_KW : F_NOT;LPAREN : '('; RPAREN : ')'; LBRACKET : '{'; RBRACKET : '}'; LSQUARE : '['; RSQUARE : ']'; COMMA : ','; POINT : '.'; COLON : ':'; // We use just one token type to reduce the number of states (and not crash Antlr...) // https://github.com/antlr/antlr4/issues/840 EQUAL : '==' -> type(RELOP); DIFFERENT : '!=' -> type(RELOP); LESSEQ : '<=' -> type(RELOP); LESS : '<' -> type(RELOP); MOREEQ : '>=' -> type(RELOP); MORE : '>' -> type(RELOP); // ASSIGNMENT has to comes after EQUAL ASSIGNMENT : '='; // Mathematical operators cannot be merged in one token type because // they have different precedences ASTERISK : '*'; SLASH : '/'; PLUS : '+'; MINUS : '-';PRIMITIVE_TYPE : F_PRIMITIVE_TYPE; BASIC_TYPE : F_BASIC_TYPE;VALUE_ID : F_VALUE_ID; // Only for types TYPE_ID : F_TYPE_ID; INT : F_INT;// Let's switch to another mode here STRING_START : '"' -> pushMode(IN_STRING);WS : (' ' | '\t')+ -> channel(WHITESPACE); NL : '\r'? '\n';COMMENT : '/*' .*? '*/' -> channel(COMMENTS);LINE_COMMENT : '//' ~[\r\n]* -> channel(COMMENTS);mode IN_STRING;STRING_STOP : '"' -> popMode; STRING_CONTENT : (~["\\#]|ESCAPE_SEQUENCE|SHARP)+; INTERPOLATION_START : '#{' -> pushMode(IN_INTERPOLATION);mode IN_INTERPOLATION;INTERPOLATION_END : '}' -> popMode; I_PRIMITIVE_TYPE : F_PRIMITIVE_TYPE -> type(PRIMITIVE_TYPE); I_BASIC_TYPE : F_BASIC_TYPE -> type(BASIC_TYPE); I_FALSE_KW : 'false' -> type(FALSE_KW); I_TRUE_KW : 'true' -> type(TRUE_KW); I_AND_KW : F_AND -> type(AND_KW); I_OR_KW : F_OR -> type(OR_KW); I_NOT_KW : F_NOT -> type(NOT_KW); I_IF_KW : 'if' -> type(IF_KW); I_ELSE_KW : 'else' -> type(ELSE_KW); I_VALUE_ID : F_VALUE_ID -> type(VALUE_ID); I_TYPE_ID : F_TYPE_ID -> type(TYPE_ID); I_INT : F_INT -> type(INT); I_COMMA : ',' -> type(COMMA); I_LPAREN : '(' -> type(LPAREN); I_RPAREN : ')' -> type(RPAREN); I_LSQUARE : '[' -> type(LSQUARE); I_RSQUARE : ']' -> type(RSQUARE);I_ASTERISK : '*' -> type(ASTERISK); I_SLASH : '/' -> type(SLASH); I_PLUS : '+' -> type(PLUS); I_MINUS : '-' -> type(MINUS);I_POINT : '.' -> type(POINT); I_EQUAL : '==' -> type(RELOP); I_DIFFERENT : '!=' -> type(RELOP); I_LESSEQ : '<=' -> type(RELOP); I_LESS : '<' -> type(RELOP); I_MOREEQ : '>=' -> type(RELOP); I_MORE : '>' -> type(RELOP); I_STRING_START : '"' -> type(STRING_START), pushMode(IN_STRING); I_WS : (' ' | '\t')+ -> type(WS), channel(WHITESPACE);fragment F_AND : 'and'; fragment F_OR : 'or'; fragment F_NOT : 'not'; fragment F_VALUE_ID : ('_')*'a'..'z' ('A'..'Z' | 'a'..'z' | '0'..'9' | '_')*; // Only for types fragment F_TYPE_ID : ('_')*'A'..'Z' ('A'..'Z' | 'a'..'z' | '0'..'9' | '_')*; fragment F_INT : '0'|(('1'..'9')('0'..'9')*); fragment F_PRIMITIVE_TYPE : 'Byte'|'Int'|'Long'|'Boolean'|'Char'|'Float'|'Double'|'Short'; fragment F_BASIC_TYPE : 'UInt';fragment ESCAPE_SEQUENCE : '\\r'|'\\n'|'\\t'|'\\"'|'\\\\'; fragment SHARP : '#'{ _input.LA(1)!='{' }?;

    我已經做了一些選擇:

    • 有兩種不同類型的ID: VALUE_ID和TYPE_ID。 由于可以輕松地區分值和類型,因此語法上的歧義性較小。 在Java中,當遇到(foo)時,我們不知道它是表達式(對括號之間foo表示的值的引用)還是類型foo的強制轉換。 我們需要看下面的內容才能理解它。 我認為這很愚蠢,因為實際上每個人都只對類型使用大寫的標識符,但是由于這不是由語言強制執行的,因此編譯器無法從中受益
    • 換行符與都靈相關,因此我們有針對它們的標記,我們基本上希望語句以換行符終止,但我們在逗號后接受可選的換行符
    • 空格(但換行符)和注釋是在它們自己的通道中捕獲的,因此我們可以在解析器語法中忽略它們,但可以在需要時檢索它們。 例如,我們需要它們來突出顯示語法,并且通常需要IntelliJ插件,因為它需要為源文件中的每個單個字符定義標記,而沒有空格
    • 最棘手的部分是在Ruby中解析字符串插值,例如“我的名字是#{user.name}”。 我們使用模式:遇到字符串開始(“)時,我們切換到詞法分析器模式IN_STRING。 在IN_STRING模式下,如果遇到插值(#{)的開始,我們將移至詞法分析器模式IN_INTERPOLATION。 在IN_INTERPOLATION模式下,我們需要接受表達式中使用的大多數標記(可悲的是,這意味著我們的詞法分析器語法有很多重復)。
    • 我不得不將關系運算符折疊為一種令牌類型,以使生成的詞法分析器的狀態數不會太大。 這意味著我將不得不查看RELOP令牌的文本,以確定需要執行哪個操作。 沒什么可怕的,但是您必須知道如何解決此類問題。

    測試詞法分析器

    我寫了很多針對詞法分析器的測試。 特別是,我測試了最復雜的部分:有關字符串插值的部分。

    一些測試的示例:

    @Testpublic void parseStringWithEmptyInterpolation() throws IOException {String code = "\"Hel#{}lo!\"";verify(code, TurinLexer.STRING_START, TurinLexer.STRING_CONTENT, TurinLexer.INTERPOLATION_START, TurinLexer.INTERPOLATION_END, TurinLexer.STRING_CONTENT, TurinLexer.STRING_STOP);}@Testpublic void parseStringWithInterpolationContainingID() throws IOException {String code = "\"Hel#{foo}lo!\"";verify(code, TurinLexer.STRING_START, TurinLexer.STRING_CONTENT, TurinLexer.INTERPOLATION_START,TurinLexer.VALUE_ID,TurinLexer.INTERPOLATION_END, TurinLexer.STRING_CONTENT, TurinLexer.STRING_STOP);}@Testpublic void parseStringWithSharpSymbol() throws IOException {String code = "\"Hel#lo!\"";verify(code, TurinLexer.STRING_START, TurinLexer.STRING_CONTENT, TurinLexer.STRING_STOP);}@Testpublic void parseMethodDefinitionWithExpressionBody() throws IOException {String code = "Void toString() = \"foo\"";verify(code, TurinLexer.VOID_KW, TurinLexer.VALUE_ID, TurinLexer.LPAREN, TurinLexer.RPAREN, TurinLexer.ASSIGNMENT, TurinLexer.STRING_START, TurinLexer.STRING_CONTENT, TurinLexer.STRING_STOP);}

    如您所見,我只是在字符串上測試令牌,并驗證它是否生成了正確的令牌列表。 簡單而直接。

    結論

    我在ANTLR上使用該語言的經驗并不完美:存在問題和局限性。 必須在單個令牌類型中折疊多個運算符并不好。 必須為不同的詞法分析器模式重復幾個標記定義是不好的。 但是,ANTLR被證明是在實踐中可用的工具:它可以完成它需要做的所有事情,并且對于每個問題都有一個可接受的解決方案。 解決方案可能不是理想的,也許不是理想的解決方案,但是有一個解決方案。 因此,我可以使用它并繼續進行編譯器中更有趣的部分。

    翻譯自: https://www.javacodegeeks.com/2015/09/turin-programming-language-for-the-jvm-building-advanced-lexers-with-antlr.html

    總結

    以上是生活随笔為你收集整理的都灵JVM编程语言:使用ANTLR构建高级词法分析器的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 国产精品永久在线 | 日本少妇激情舌吻 | 天天操一操 | 操操操网 | 日韩久久精品电影 | 麻豆疯狂做受xxxx高潮视频 | 91高清视频免费观看 | 国产成人不卡 | 日韩精品无码一区二区三区 | 杨幂一区二区三区免费看视频 | jizzjizz日本免费视频 | 色婷婷一区二区三区四区 | 国产精品久久麻豆 | 青青草福利 | 国产精品黑丝 | 妹子干综合 | 亚洲av色一区二区三区精品 | 五月六月丁香 | 国产丰满果冻videossex | 国产精品情侣自拍 | 成人涩涩网站 | 欧洲性生活视频 | 无码国产精品一区二区高潮 | 午夜免费一级片 | 久操综合 | 三区在线观看 | 中文字幕人妻一区二区在线视频 | 久久久三级 | 亚洲精品高清无码视频 | 自拍视频国产 | 在线观看中文字幕码 | 丰满少妇影院 | 韩日黄色 | 在线99视频| 欧美爽爽| 在线成人中文字幕 | 99热这里只有精品7 青青草社区 | 亚洲成人自拍视频 | 亚洲成人精品一区二区三区 | 91精品国产高潮对白 | jlzzjlzz欧美大全 | 亚洲AV无码片久久精品 | 第一页在线视频 | 欧美激情校园春色 | 男人的天堂黄色 | 国产成人精品一区二区三区福利 | 国产色综合视频 | 亚洲第二色 | 国产精品美女久久久久av超清 | 黄色成人av网站 | 99热在线这里只有精品 | 久久亚洲av成人无码国产电影 | 美女露胸露尿口 | 久草视频在线观 | 一区二区三区亚洲精品 | 九九天堂网| 中文字幕亚洲第一 | 亚洲女人av| 伊人久久大香线蕉成人综合网 | 国产精品天天操 | 波多野结衣免费视频观看 | 成人免费精品视频 | 粉嫩aⅴ一区二区三区 | 国产成人av在线播放 | 久久xx| 91精品人妻一区二区三区果冻 | 女生扒开尿口 | 催眠美妇肉奴系统 | 两根大肉大捧一进一出好爽视频 | 午夜黄色在线 | 福利国产视频 | 一级片欧美 | 国产偷人妻精品一区 | 午夜影院在线观看视频 | www.亚洲欧美| 韩国美女毛片 | 日本爱爱免费视频 | aa黄色大片 | 亚洲毛片一区二区三区 | 刘亦菲毛片一区二区三区 | 久久精品无码一区二区三区 | 久久国产一区 | 一级片欧美| 岛国av网站| 久久高清一区 | 最新av在线网址 | 在线爱情大片免费观看大全 | 亚洲av成人无码一二三在线观看 | 日韩欧美www| 性欧美18—19sex性高清 | 超碰520| 欧美巨大荫蒂茸毛毛人妖 | 久久久久久欧美精品se一二三四 | 少妇被躁爽到高潮无码人狍大战 | ,亚洲人成毛片在线播放 | 爆操白虎 | 2021国产在线视频 | 亚洲青青操 | 第一区免费在线观看 |