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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

一个简单的语言的语法(二):ANTLR的重写规则

發(fā)布時(shí)間:2025/5/22 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一个简单的语言的语法(二):ANTLR的重写规则 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
們使用ANTLR來(lái)描述了Jerry語(yǔ)言的基本語(yǔ)法,并通過(guò)ANTLRWorks來(lái)實(shí)驗(yàn)該語(yǔ)法對(duì)樣本代碼生成的解析樹(shù)。但如同上一篇最后所述,這樣得到的解析樹(shù)中有太多對(duì)后續(xù)處理來(lái)說(shuō)無(wú)用的冗余信息。我們需要消除這些冗余信息,得到抽象語(yǔ)法樹(shù)(AST)。
本篇將以之前做的語(yǔ)法為基礎(chǔ),通過(guò)添加樹(shù)重寫(xiě)規(guī)則來(lái)將ANTLR默認(rèn)生成的解析樹(shù)簡(jiǎn)化整理為抽象語(yǔ)法樹(shù)。

本文涉及的源碼和運(yùn)行時(shí)庫(kù)打包在附件里了,懶得復(fù)制粘貼的話就直接下載附件的版本,用ANTLRWorks來(lái)查看和編輯語(yǔ)法文件吧~

修改后的語(yǔ)法文件如下:
Jerry.g(ANTLR 3.1語(yǔ)法文件,以Java為生成目標(biāo)語(yǔ)言)
Java代碼 ?
  • grammar?Jerry;??
  • ??
  • options?{??
  • ????language?=?Java;??
  • ????output?=?AST;??
  • ????ASTLabelType?=?CommonTree;??
  • }??
  • ??
  • tokens?{??
  • ????//?imaginary?tokens??
  • ????VAR_DECL;??
  • ????SIMPLE_TYPE;??
  • ????ARRAY_TYPE;??
  • ????ARRAY_LITERAL;??
  • ????SIMPLE_VAR_ACCESS;??
  • ????ARRAY_VAR_ACCESS;??
  • ????UNARY_MINUS;??
  • ????BLOCK;??
  • ????EXPR_STMT;??
  • }??
  • ??
  • //?parser?rules??
  • ??
  • program?:???statementList?EOF!??
  • ????????{??
  • ????????????System.out.println(??
  • ????????????????null?==?$statementList.tree????
  • ????????????????"null"?:??
  • ????????????????$statementList.tree.toStringTree());??
  • ????????}??
  • ????;??
  • ??
  • statementList??
  • ????:???statement*??
  • ????;??
  • ??
  • statement??
  • ????:???expressionStatement??
  • ????|???variableDeclaration??
  • ????|???blockStatement??
  • ????|???ifStatement??
  • ????|???whileStatement??
  • ????|???breakStatement??
  • ????|???readStatement??
  • ????|???writeStatement??
  • ????;??
  • ??
  • expressionStatement??
  • ????:???expression?SEMICOLON??
  • ????????????->?^(?EXPR_STMT?expression?)??
  • ????;??
  • ??
  • variableDeclaration??
  • ????:???typeSpecifier??
  • ????????????(?Identifier??
  • ????????????????(???->?^(?VAR_DECL?^(?SIMPLE_TYPE?typeSpecifier?)?Identifier?)??
  • ????????????????|?(?LBRACK?Integer?RBRACK?)+??
  • ????????????????????->?^(?VAR_DECL?^(?ARRAY_TYPE?typeSpecifier?Integer+?)?Identifier?)??
  • ????????????????|?EQ?expression??
  • ????????????????????->?^(?VAR_DECL?^(?SIMPLE_TYPE?typeSpecifier?)?Identifier?expression?)??
  • ????????????????|?(?LBRACK?Integer?RBRACK?)+?EQ?arrayLiteral??
  • ????????????????????->?^(?VAR_DECL?^(?ARRAY_TYPE?typeSpecifier?Integer+?)?Identifier?arrayLiteral?)??
  • ????????????????)??
  • ????????????)??
  • ????????????(?COMMA?id=Identifier??
  • ????????????????(???->?$variableDeclaration?^(?VAR_DECL?^(?SIMPLE_TYPE?typeSpecifier?)?$id?)??
  • ????????????????|?(?LBRACK?dim1+=Integer?RBRACK?)+??
  • ????????????????????->?$variableDeclaration?^(?VAR_DECL?^(?ARRAY_TYPE?typeSpecifier?$dim1+?)?$id?)??
  • ????????????????|?EQ?exp=expression??
  • ????????????????????->?$variableDeclaration?^(?VAR_DECL?^(?SIMPLE_TYPE?typeSpecifier?)?$id?$exp?)??
  • ????????????????|?(?LBRACK?dim2+=Integer?RBRACK?)+?EQ?al=arrayLiteral??
  • ????????????????????->?$variableDeclaration?^(?VAR_DECL?^(?ARRAY_TYPE?typeSpecifier?$dim2+?)?$id?$al?)??
  • ????????????????)??
  • ????????????????{?if?(null?!=?$dim1)?$dim1.clear();?if?(null?!=?$dim2)?$dim2.clear();?}??
  • ????????????)*??
  • ????????SEMICOLON??
  • ????;??
  • ??
  • typeSpecifier??
  • ????:???INT?|?REAL??
  • ????;??
  • ??
  • arrayLiteral??
  • ????:???LBRACE??
  • ????????????arrayLiteralElement?(?COMMA?arrayLiteralElement?)*??
  • ????????RBRACE??
  • ????????????->?^(?ARRAY_LITERAL?arrayLiteralElement+?)??
  • ????;??
  • ??
  • arrayLiteralElement??
  • ????:???expression??
  • ????|???arrayLiteral??
  • ????;??
  • ??
  • blockStatement??
  • ????:???LBRACE?statementList?RBRACE??
  • ????????????->?^(?BLOCK?statementList?)??
  • ????;??
  • ??
  • ifStatement??
  • ????:???IF^?LPAREN!?expression?RPAREN!?statement?(?ELSE!?statement?)???
  • ????;??
  • ??
  • whileStatement??
  • ????:???WHILE^?LPAREN!?expression?RPAREN!?statement??
  • ????;??
  • ??
  • breakStatement??
  • ????:???BREAK?SEMICOLON!??
  • ????;??
  • ??
  • readStatement??
  • ????:???READ^?variableAccess?SEMICOLON!??
  • ????;??
  • ??
  • writeStatement??
  • ????:???WRITE^?expression?SEMICOLON!??
  • ????;??
  • ??
  • variableAccess??
  • ????:???Identifier??
  • ????????(???->?^(?SIMPLE_VAR_ACCESS?Identifier?)??
  • ????????|?(?LBRACK?Integer?RBRACK?)+??
  • ????????????->?^(?ARRAY_VAR_ACCESS?Identifier?Integer+?)??
  • ????????)??
  • ????;??
  • ??
  • expression??
  • ????:???assignmentExpression??
  • ????|???logicalOrExpression??
  • ????;??
  • ??
  • assignmentExpression??
  • ????:???variableAccess?EQ^?expression??
  • ????;??
  • ??
  • logicalOrExpression??
  • ????:???logicalAndExpression?(?OROR^?logicalAndExpression?)*??
  • ????;??
  • ??
  • logicalAndExpression??
  • ????:???relationalExpression?(?ANDAND^?relationalExpression?)*??
  • ????;??
  • ??
  • relationalExpression??
  • ????:???additiveExpression?(?relationalOperator^?additiveExpression?)???
  • ????|???BANG^?relationalExpression??
  • ????;??
  • ??
  • additiveExpression??
  • ????:???multiplicativeExpression?(?additiveOperator^?multiplicativeExpression?)*??
  • ????;??
  • ????
  • multiplicativeExpression??
  • ????:???primaryExpression?(?multiplicativeOperator^?primaryExpression?)*??
  • ????;??
  • ??
  • primaryExpression??
  • ????:???variableAccess??
  • ????|???Integer??
  • ????|???RealNumber??
  • ????|???LPAREN!?expression?RPAREN!??
  • ????|???MINUS?primaryExpression??
  • ????????????->?^(?UNARY_MINUS?primaryExpression?)??
  • ????;??
  • ??
  • relationalOperator?????
  • ????:???LT?|?GT?|?EQEQ?|?LE?|?GE?|?NE??
  • ????;??
  • ??
  • additiveOperator??
  • ????:???PLUS?|?MINUS??
  • ????;??
  • ??
  • multiplicativeOperator??
  • ????:???MUL?|?DIV??
  • ????;??
  • ??
  • //?lexer?rules??
  • ??
  • LPAREN??:???'('??
  • ????;??
  • ??
  • RPAREN??:???')'??
  • ????;??
  • ??
  • LBRACK??:???'['??
  • ????;??
  • ??
  • RBRACK??:???']'??
  • ????;??
  • ??
  • LBRACE??:???'{'??
  • ????;??
  • ??
  • RBRACE??:???'}'??
  • ????;??
  • ??
  • COMMA???:???','??
  • ????;??
  • ??
  • SEMICOLON??
  • ????:???';'??
  • ????;??
  • ??
  • PLUS????:???'+'??
  • ????;??
  • ??
  • MINUS???:???'-'??
  • ????;??
  • ??
  • MUL?:???'*'??
  • ????;??
  • ??
  • DIV?:???'/'??
  • ????;??
  • ??
  • EQEQ????:???'=='??
  • ????;??
  • ??
  • NE??:???'!='??
  • ????;??
  • ??
  • LT??:???'<'??
  • ????;??
  • ??
  • LE??:???'<='??
  • ????;??
  • ??
  • GT??:???'>'??
  • ????;??
  • ??
  • GE??:???'>='??
  • ????;??
  • ??
  • BANG????:???'!'??
  • ????;??
  • ??
  • ANDAND??:???'&&'??
  • ????;??
  • ??
  • OROR????:???'||'??
  • ????;??
  • ??
  • EQ??:???'='??
  • ????;??
  • ??
  • IF??:???'if'??
  • ????;??
  • ??
  • ELSE????:???'else'??
  • ????;??
  • ??
  • WHILE???:???'while'??
  • ????;??
  • ??
  • BREAK???:???'break'??
  • ????;??
  • ??
  • READ????:???'read'??
  • ????;??
  • ??
  • WRITE???:???'write'??
  • ????;??
  • ??
  • INT?:???'int'??
  • ????;??
  • ??
  • REAL????:???'real'??
  • ????;??
  • ??
  • Identifier??
  • ????:???LetterOrUnderscore?(?LetterOrUnderscore?|?Digit?)*??
  • ????;??
  • ??
  • Integer?:???Digit+??
  • ????;??
  • ??
  • RealNumber??
  • ????:???Digit+?'.'?Digit+??
  • ????;??
  • ??
  • fragment??
  • Digit???:???'0'..'9'??
  • ????;??
  • ??
  • fragment??
  • LetterOrUnderscore??
  • ????:???Letter?|?'_'??
  • ????;??
  • ??
  • fragment??
  • Letter??:???(?'a'..'z'?|?'A'..'Z'?)??
  • ????;??
  • ??
  • WS??:???(?'?'?|?'\t'?|?'\r'?|?'\n'?)+?{?$channel?=?HIDDEN;?}?????
  • ????;??
  • ??
  • Comment??
  • ????:???'/*'?(?options?{?greedy?=?false;?}?:?.?)*?'*/'?{?$channel?=?HIDDEN;?}??
  • ????;??
  • ??
  • LineComment??
  • ????:???'//'?~('\n'|'\r')*?'\r'??'\n'?{?$channel?=?HIDDEN;?}??
  • ????;??


  • 稍微說(shuō)明一下修改點(diǎn)。應(yīng)該觀察到lexer rules部分是完全沒(méi)有改變的,修改的主要是一些選項(xiàng)和parser rules。

    首先,在文件的開(kāi)頭添加了一組選項(xiàng):
    Java代碼 ?
  • options?{??
  • ????language?=?Java;??
  • ????output?=?AST;??
  • ????ASTLabelType?=?CommonTree;??
  • }??

  • ANTLR會(huì)知道應(yīng)該使用生成AST的模式,以CommonTree作為AST的節(jié)點(diǎn)類型,并以Java作為生成的解析器源碼的語(yǔ)言。上一篇是在 ANTLRWorks里編輯和實(shí)驗(yàn)語(yǔ)法的,這次我們需要生成實(shí)際能運(yùn)行的解析器,所以需要指定這些選項(xiàng)(默認(rèn)就是生成Java源碼,不過(guò)后續(xù)文章中我應(yīng)該 會(huì)換用CSharp2目標(biāo)。這個(gè)以后再說(shuō))。

    接下來(lái),可以看到除了原本在lexer rules里定義的實(shí)際存在的token類型之外,這次我們?cè)谡Z(yǔ)法文件的開(kāi)頭還增加了一組虛擬的token類型。這些token類型是為了讓生成出來(lái)的抽象語(yǔ)法樹(shù)易于解析而添加的。
    例如,觀察VAR_DECL這個(gè)token類型。在原本的語(yǔ)法中,沒(méi)有任何關(guān)鍵字能清楚的標(biāo)識(shí)出當(dāng)前處理的內(nèi)容是一個(gè)變量聲明。為了方便后續(xù)分析,我們可以“制造”出一個(gè)虛構(gòu)的token作為一個(gè)變量聲明語(yǔ)句的根元素,然后以變量的類型、標(biāo)識(shí)符和初始值為子元素。

    然后就是最重要的部分,樹(shù)重寫(xiě)規(guī)則了。有兩種形式來(lái)表述樹(shù)重寫(xiě)規(guī)則:一是直接在原本的語(yǔ)法規(guī)則上添加樹(shù)生成用的運(yùn)算符(^和!),二是在原本的語(yǔ)法規(guī)則后添加一個(gè)箭頭("->"),并在箭頭后顯式指定需要生成的節(jié)點(diǎn)的結(jié)構(gòu)。
    看兩個(gè)例子:
    while語(yǔ)句。原本的語(yǔ)法是:
    Java代碼 ?
  • whileStatement?:?'while'?'('?expression?')'?statement?;??

  • 這里我們想讓生成出來(lái)的子樹(shù)以'while'為根節(jié)點(diǎn),以expression和statement為子節(jié)點(diǎn)。
    可以直接在該語(yǔ)法上添加樹(shù)生成運(yùn)算符:在某個(gè)元素后加上帽子符號(hào)('^')來(lái)表示它是生成的子樹(shù)的根節(jié)點(diǎn),在某個(gè)元素后加上嘆號(hào)('!')來(lái)表示生成的子樹(shù)中應(yīng)該忽略該元素。于是修改得到的語(yǔ)法是:
    Java代碼 ?
  • whileStatement?:?'while'^?'('!?expression?')'!?statement?;??

  • 也可以顯式指定樹(shù)重寫(xiě)規(guī)則。一棵子樹(shù)用這種方式來(lái)表示:
    Java代碼 ?
  • ^(?root?element1?element2?...?)??

  • 這里我們要的就是:
    Java代碼 ?
  • whileStatement?:?'while'?'('?expression?')'?statement??
  • ????->?^(?'while'?expression?statement?)??
  • ??;??

  • 這種形式我們能一目了然看到最終生成的子樹(shù)的結(jié)構(gòu)。
    兩種形式是等價(jià)的,可以根據(jù)具體情況來(lái)選擇能簡(jiǎn)單而清晰的表示出樹(shù)改寫(xiě)規(guī)則的版本。

    對(duì)表達(dá)式相關(guān)的語(yǔ)法規(guī)則,我們幾乎都是用添加運(yùn)算符的形式來(lái)表示樹(shù)改寫(xiě)規(guī)則,因?yàn)閷?duì)左結(jié)合的雙目運(yùn)算符,這樣是最簡(jiǎn)潔的。
    ANTLR生成的解析器使用LL(*)算法;與一般的LL解析器一樣,ANTLR不支持左遞歸的語(yǔ)法規(guī)則。這使得書(shū)寫(xiě)左結(jié)合的雙目運(yùn)算符時(shí),一般得寫(xiě)成這樣的形式:
    Java代碼 ?
  • exprWithHigherPrecedence??
  • ??:?exprWithLowerPrecedence?(?op?exprWithLowerPrecedence?)*??
  • ??;??

  • 而不能以左遞歸來(lái)指定左結(jié)合。(但右結(jié)合還是可以用右遞歸來(lái)指定的。)
    那么在表示樹(shù)改寫(xiě)規(guī)則的時(shí)候,使用運(yùn)算符來(lái)修飾語(yǔ)法就是這樣:
    Java代碼 ?
  • exprWithHigherPrecedence??
  • ??:?exprWithLowerPrecedence?(?op^?exprWithLowerPrecedence?)*??
  • ??;??

  • 只是在op的后面添加了一個(gè)帽子符號(hào)('^'),表明在沒(méi)有匹配到op運(yùn)算符時(shí)就直接返回exprWithLowerPrecedence規(guī)則所 生成的樹(shù);而如果匹配到了op運(yùn)算符,則每匹配到一次就生成一個(gè)新的以op為根節(jié)點(diǎn)的、前后兩個(gè)較低優(yōu)先級(jí)的表達(dá)式節(jié)點(diǎn)為子節(jié)點(diǎn)的樹(shù)。
    這個(gè)樹(shù)改寫(xiě)規(guī)則如果要顯式指定,就得寫(xiě)成:
    Java代碼 ?
  • exprWithHigherPrecedence??
  • ??:?exprWithLowerPrecedence??
  • ??????(?op?exp=exprWithLowerPrecedence??
  • ??????????->?^(?op?$exprWithHigherPrecedence?$exp?)??
  • ??????)*??
  • ??;??

  • 后者相比之下麻煩多了,所以一般都會(huì)使用前者。

    可惜C風(fēng)格的變量聲明語(yǔ)句的語(yǔ)法很麻煩,結(jié)果variableDeclaration在修改后膨脹了好多 T T
    最不爽的地方就是C風(fēng)格的數(shù)組變量聲明是把數(shù)組的維度寫(xiě)在變量名后面的。這就使得語(yǔ)句開(kāi)頭的類型(例如int、char等)可能只是變量的實(shí)際類型的一部分,而另一部分要在變量名的之前(例如表示指針的星號(hào)('*'))或之后(例如表示數(shù)組的方括號(hào)('[' ']'))。
    就不能把整個(gè)類型寫(xiě)在一起么……T T 于是衍生出來(lái)的Java和C#明顯都吸取了這個(gè)教訓(xùn)。

    在語(yǔ)法的program規(guī)則中,我們添加了一條嵌入語(yǔ)法動(dòng)作,讓生成的解析器在匹配完program規(guī)則后將其對(duì)應(yīng)的抽象語(yǔ)法樹(shù)以字符串的形式輸出出來(lái)。

    如果是在ANTLRWorks里編輯該語(yǔ)法文件,可以在菜單里選擇Generate -> Generate Code來(lái)生成出解析器的源碼。這里例子中我們會(huì)得到JerryLexer.java和JerryParser.java。
    要運(yùn)行這個(gè)解析器,還需要寫(xiě)一個(gè)簡(jiǎn)單的啟動(dòng)程序來(lái)調(diào)用生成出來(lái)的JerryLexer和JerryParser。源碼如下:
    TestJerry.java
    Java代碼 ?
  • import?org.antlr.runtime.*;??
  • ??
  • public?class?TestJerry?{??
  • ????public?static?void?main(String[]?args)?throws?Exception?{??
  • ????????//?Create?an?input?character?stream?from?standard?in??
  • ????????ANTLRInputStream?input?=?new?ANTLRInputStream(System.in);??
  • ????????//?Create?an?JerryLexer?that?feeds?from?that?stream??
  • ????????JerryLexer?lexer?=?new?JerryLexer(input);??
  • ????????//?Create?a?stream?of?tokens?fed?by?the?lexer??
  • ????????CommonTokenStream?tokens?=?new?CommonTokenStream(lexer);??
  • ????????//?Create?a?parser?that?feeds?off?the?token?stream??
  • ????????JerryParser?parser?=?new?JerryParser(tokens);??
  • ????????//?Begin?parsing?at?rule?prog??
  • ????????parser.program();??
  • ????}??
  • }??

  • 它指定從標(biāo)準(zhǔn)輸入流得到要解析的Jerry代碼,然后通過(guò)JerryLexer將代碼解析成token流,再將token流交給JerryParser進(jìn)行句法分析。

    將JerryLexer.java、JerryParser.java和TestJerry.java放在跟ANTLRWorks同一目錄下,然后編譯它們:
    引用javac -Xlint:unchecked -cp antlrworks-1.2.2.jar JerryLexer.java JerryParser.java TestJerry.java
    (因?yàn)锳NTLRWorks里含有ANTLR的運(yùn)行時(shí)庫(kù),而我正好又是用ANTLRWorks來(lái)編輯語(yǔ)法文件的,所以直接用ANTLRWorks 的JAR包放在classpath里來(lái)得到需要的ANTLR運(yùn)行時(shí)類。實(shí)際開(kāi)發(fā)的話可以從ANTLR官網(wǎng)獲得只含有ANTLR運(yùn)行時(shí)庫(kù)的JAR包并在編譯 和運(yùn)行的時(shí)候?qū)⑵涮砑拥絚lasspath里。)

    上一篇的最后有這樣的一段Jerry例子:
    C代碼 ?
  • //?line?comment??
  • //?declare?variables?with/without?initializers??
  • int?i?=?1,?j;??
  • int?x?=?i?+?2?*?3?-?4?/?(?6?-?-?7?);??
  • int?array[2][3]?=?{??
  • ??{?0,?1,?2?},??
  • ??{?3,?4,?6?}??
  • };??
  • ??
  • /*?
  • ??block?comment?
  • */??
  • ??
  • while?(i?<?10)?i?=?i?+?1;??
  • while?(!x?>?0?&&?i?<?10)?{??
  • ??x?=?x?-?1;??
  • ??if?(i?<?5)?break;??
  • ??else?read?i;??
  • }??
  • ??
  • write?x?-?j;??

  • (語(yǔ)法是符合要求的,至于代碼的意義就別追究了,只是用來(lái)演示各種語(yǔ)法結(jié)構(gòu)隨便寫(xiě)的)

    用本篇的ANTLR語(yǔ)法文件生成的解析器,我們可以解析這個(gè)例子,得到對(duì)應(yīng)的抽象語(yǔ)法樹(shù)的字符串表示。表示方法是:
    Java代碼 ?
  • (root?element1?element2?...)??

  • 跟LISP的S-expression非常類似。

    于是執(zhí)行測(cè)試程序。將要解析的代碼保存到JerrySample.txt中,然后執(zhí)行下面的命令:
    引用java -cp ".;antlrworks-1.2.2.jar" TestJerry < JerrySample.txt
    得到輸出:
    Java代碼 ?
  • (VAR_DECL?(SIMPLE_TYPE?int)?i?1)?(VAR_DECL?(SIMPLE_TYPE?int)?j)?(VAR_DECL?(SIMPLE_TYPE?int)?x?(-?(+?(SIMPLE_VAR_ACCESS?i)?(*?2?3))?(/?4?(-?6?(UNARY_MINUS?7)))))?(VAR_DECL?(ARRAY_TYPE?int?2?3)?array?(ARRAY_LITERAL?(ARRAY_LITERAL?0?1?2)?(ARRAY_LITERAL?3?4?6)))?(while?(<?(SIMPLE_VAR_ACCESS?i)?10)?(=?(SIMPLE_VAR_ACCESS?i)?(+?(SIMPLE_VAR_ACCESS?i)?1)))?(while?(&&?(!?(>?(SIMPLE_VAR_ACCESS?x)?0))?(<?(SIMPLE_VAR_ACCESS?i)?10))?(BLOCK?(=?(SIMPLE_VAR_ACCESS?x)?(-?(SIMPLE_VAR_ACCESS?x)?1))?(if?(<?(SIMPLE_VAR_ACCESS?i)?5)?break?(read?(SIMPLE_VAR_ACCESS?i)))))?(write?(-?(SIMPLE_VAR_ACCESS?x)?(SIMPLE_VAR_ACCESS?j)))??

  • 這樣太亂了看不清楚。將其格式稍微整理一下得到:
    Java代碼 ?
  • (VAR_DECL??
  • ??(SIMPLE_TYPE?int)??
  • ??i??
  • ??1??
  • )??
  • (VAR_DECL??
  • ??(SIMPLE_TYPE?int)??
  • ??j??
  • )??
  • (VAR_DECL??
  • ??(SIMPLE_TYPE?int)??
  • ??x??
  • ??(-??
  • ????(+?(SIMPLE_VAR_ACCESS?i)?(*?2?3))??
  • ????(/?4?(-?6?(UNARY_MINUS?7)))??
  • ??)??
  • )??
  • (VAR_DECL??
  • ??(ARRAY_TYPE??
  • ????int??
  • ????2??
  • ????3??
  • ??)??
  • ??array??
  • ??(ARRAY_LITERAL??
  • ????(ARRAY_LITERAL?0?1?2)??
  • ????(ARRAY_LITERAL?3?4?6)??
  • ??)??
  • )??
  • ??
  • (while??
  • ??(<?(SIMPLE_VAR_ACCESS?i)?10)??
  • ??(=?(SIMPLE_VAR_ACCESS?i)?(+?(SIMPLE_VAR_ACCESS?i)?1))??
  • )??
  • (while??
  • ??(&&??
  • ????(!?(>?(SIMPLE_VAR_ACCESS?x)?0))??
  • ????(<?(SIMPLE_VAR_ACCESS?i)?10)??
  • ??)??
  • ??(BLOCK??
  • ????(=?(SIMPLE_VAR_ACCESS?x)?(-?(SIMPLE_VAR_ACCESS?x)?1))??
  • ????(if??
  • ??????(<?(SIMPLE_VAR_ACCESS?i)?5)??
  • ??????break??
  • ??????(read?(SIMPLE_VAR_ACCESS?i))??
  • ????)??
  • ??)??
  • )??
  • (write??
  • ??(-?(SIMPLE_VAR_ACCESS?x)?(SIMPLE_VAR_ACCESS?j)))??

  • 可以跟原本的代碼對(duì)比一下,看看是否保持了原本的結(jié)構(gòu)。

    得到這棵抽象語(yǔ)法樹(shù)之后,接下來(lái)就可以對(duì)樹(shù)來(lái)做匹配和分析了。由于樹(shù)本身已經(jīng)有了結(jié)構(gòu),下面就可以用更干凈的描述方式來(lái)表述我們要對(duì)樹(shù)做的處理。

    轉(zhuǎn)載于:https://www.cnblogs.com/shihao/archive/2012/06/02/2532218.html

    總結(jié)

    以上是生活随笔為你收集整理的一个简单的语言的语法(二):ANTLR的重写规则的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 欧美freesex黑人又粗又大 | 在线观看av的网址 | 影音先锋中文字幕人妻 | 日韩男女啪啪 | 黄色视屏软件 | 国产精品黑人一区二区三区 | 潮喷失禁大喷水无码 | 亚洲成人不卡 | 国产男人的天堂 | 色综合久久久 | 99re99| 校霸被c到爽夹震蛋上课高潮 | 少妇久久精品 | 亚洲乱码国产一区三区 | 国产在线无 | 少妇性bbb搡bbb爽爽爽欧美 | 国精产品乱码一区一区三区四区 | 亚洲男人天堂av | 日本精品免费在线观看 | www久久久久久久 | 成人免费视频a | 日韩经典av | 久久午夜无码鲁丝片午夜精品 | 91精品在线看 | 毛片视频网 | 暖暖视频日本 | 日本污视频在线观看 | 国产精品一区二区三区四区 | 超碰在线网址 | 人妻av无码一区二区三区 | 永久免费在线观看视频 | 欧美人与禽猛交乱配 | 精品国产乱码久久久久久郑州公司 | 精品动漫一区 | 中文字幕高清一区 | 黑森林福利视频导航 | 美女黄色一级片 | 在线免费观看高清视频 | 少妇做爰免费理伦电影 | 7x7x7x人成影视 | av在线播放观看 | 国产成人影视 | 成年人免费看 | 久久98| 美女扒开内看个够网站 | h片在线免费看 | 99热官网 | 综合在线播放 | 亚洲一区二区黄片 | 九九视频免费看 | h片免费在线观看 | 亚洲av午夜精品一区二区三区 | 国产一区二区三区四区五区 | 国产精品白嫩极品美女视频 | 久久久久久黄 | 啪啪综合 | 美女隐私免费看 | aaaaa黄色片 天堂网在线观看 | 毛片网 | 少妇精品一区二区三区 | 亚洲欧美视频在线 | av导航福利 | 二级毛片在线观看 | 亚洲国产日韩av | 亚洲欧美综合自拍 | 激情五月婷婷在线 | 菲律宾av | 日韩在线电影一区 | 9cao| 日韩乱论| 午夜视频一区二区三区 | 亚洲伊人成人网 | 国产一区二区99 | 乳色吐息在线观看 | 91视频影院 | 日韩欧美色图 | 青青草综合| 欧美毛片网站 | 果冻av在线 | 视频二区欧美 | 三级自拍视频 | 天天操天天爽天天干 | 男女激情视频网站 | 操欧美女 | 国产成人三级在线观看视频 | 91久久亚洲| 国产又粗又硬又黄的视频 | 免费国产黄色网址 | av免费观看不卡 | gav久久| 啪啪导航 | 久久免费高清视频 | 欧美日韩精品在线播放 | 色偷偷免费 | 97精品一区二区视频在线观看 | 黄av在线播放 | 久久人体| 小视频在线看 | 加勒比毛片 |