1 回答

TA貢獻(xiàn)1911條經(jīng)驗(yàn) 獲得超7個(gè)贊
拉斐爾寫(xiě)道:
antlr是否通過(guò)選項(xiàng){output = AST;}自動(dòng)為我們構(gòu)建AST?或者我必須自己制作樹(shù)?如果是,那么如何吐出AST上的節(jié)點(diǎn)?
不,解析器不知道你想要什么作為root和每個(gè)解析器規(guī)則的葉子,所以你必須做的不僅僅是放入options { output=AST; }
你的語(yǔ)法。
例如,"true && (false || true && (true || false))"
使用從語(yǔ)法生成的解析器解析源時(shí):
grammar ASTDemo;options { output=AST; }parse : orExp ;orExp : andExp ('||' andExp)* ;andExp : atom ('&&' atom)* ;atom : 'true' | 'false' | '(' orExp ')' ;// ignore white space charactersSpace : (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;} ;
生成以下解析樹(shù):
(即只是一個(gè)扁平的,一維的令牌列表)
你想要告訴ANTLR你的語(yǔ)法中的哪些標(biāo)記成為根,離開(kāi)或者只是從樹(shù)中刪除。
創(chuàng)建AST可以通過(guò)兩種方式完成:
使用如下所示的重寫(xiě)規(guī)則:
foo : A B C D -> ^(D A B);
,哪里foo
是與令牌匹配的解析器規(guī)則A B C D
。所以事后的一切->
都是實(shí)際的重寫(xiě)規(guī)則。如您所見(jiàn),令牌C
未在重寫(xiě)規(guī)則中使用,這意味著它在AST中被省略。直接放在后面的令牌^(
將成為樹(shù)的根;使用樹(shù)操作符
^
,!
在解析器規(guī)則中的一個(gè)標(biāo)記后,^
將令牌作為根,并!
從樹(shù)中刪除一個(gè)標(biāo)記。等效于foo : A B C D -> ^(D A B);
將foo : A B C! D^;
雙方foo : A B C D -> ^(D A B);
并foo : A B C! D^;
會(huì)產(chǎn)生以下的AST:
現(xiàn)在,您可以按如下方式重寫(xiě)語(yǔ)法:
grammar ASTDemo;options { output=AST; }parse : orExp ;orExp : andExp ('||'^ andExp)* // Make `||` root ;andExp : atom ('&&'^ atom)* // Make `&&` root ;atom : 'true' | 'false' | '(' orExp ')' -> orExp // Just a single token, no need to do `^(...)`, // we're removing the parenthesis. Note that // `'('! orExp ')'!` will do exactly the same. ;// ignore white space charactersSpace : (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;} ;
這將從源創(chuàng)建以下AST"true && (false || true && (true || false))"
:
相關(guān)的ANTLR wiki鏈接:
樹(shù)的建設(shè)
樹(shù)解析
樹(shù)木施工設(shè)施
拉斐爾寫(xiě)道:
我目前認(rèn)為AST上的節(jié)點(diǎn)將用于制作SSA,然后進(jìn)行數(shù)據(jù)流分析以制作靜態(tài)分析器。我在正確的道路上嗎?
從來(lái)沒(méi)有做過(guò)這樣的事情,但I(xiàn)MO首先想要的是來(lái)自源頭的AST,所以是的,我猜你正走在正確的道路上!:)
編輯
以下是如何使用生成的詞法分析器和解析器:
import org.antlr.runtime.*;import org.antlr.runtime.tree.*;import org.antlr.stringtemplate.*;public class Main { public static void main(String[] args) throws Exception { String src = "true && (false || true && (true || false))"; ASTDemoLexer lexer = new ASTDemoLexer(new ANTLRStringStream(src)); ASTDemoParser parser = new ASTDemoParser(new CommonTokenStream(lexer)); CommonTree tree = (CommonTree)parser.parse().getTree(); DOTTreeGenerator gen = new DOTTreeGenerator(); StringTemplate st = gen.toDOT(tree); System.out.println(st); }}
- 1 回答
- 0 關(guān)注
- 374 瀏覽
添加回答
舉報(bào)