2017-09-16 70 views
0

我試圖使用Antlr來製作一個非常簡單的解析器,它基本上標記了一系列. - 限制標識符。如何使antlr4完全令牌化終端節點

我做一個簡單的語法:

r : STRUCTURE_SELECTOR ; 
STRUCTURE_SELECTOR: '.' (ID STRUCTURE_SELECTOR?)? ; 
ID : [_a-z0-9$]* ;    
WS : [ \t\r\n]+ -> skip ; 

當產生解析器,我最終與表示字符串,而不是能夠找到進一步STRUCTURE_SELECTOR秒的單個終端節點。我希望看到一個序列(可能表示爲當前節點的子節點)。我怎樣才能做到這一點?

作爲一個例子:

  • .將產生其文本是一個終端節點.
  • .foobar將產生兩個節點,與文本.父並用文本子foobar
  • .foobar.baz將產生四個節點,文字爲.的父母,文字爲foobar的子女,文字爲.的二級子女,以及帶文字的三級子女baz

回答

0

以大寫字母開頭的規則是Lexer規則。

用下面的輸入文件t.text

. 
.foobar 
.foobar.baz 

你的語法(在文件Question.g4)產生下面的令牌

$ grun Question r -tokens -diagnostics t.text 
[@0,0:0='.',<STRUCTURE_SELECTOR>,1:0] 
[@1,2:8='.foobar',<STRUCTURE_SELECTOR>,2:0] 
[@2,10:20='.foobar.baz',<STRUCTURE_SELECTOR>,3:0] 
[@3,22:21='<EOF>',<EOF>,4:0] 

詞法分析器(解析器)是貪婪。它試圖儘可能多的讀取輸入字符(令牌)。詞法分析器規則STRUCTURE_SELECTOR: '.' (ID STRUCTURE_SELECTOR?)?可以讀取點,ID以及點和ID(由於重複標記?),直到NL。這就是爲什麼每條線都以單個標記結束的原因。

當編譯的語法,誤差

warning(146): Question.g4:5:0: non-fragment lexer rule ID can match the empty string 

自帶因爲ID的重複標記是*(這意味着0次或更多次),而不是+(一次或多次)。

現在試試這個語法:

grammar Question; 

r 
@init {System.out.println("Question last update 2135");} 
    : (structure_selector NL)+ EOF 
    ; 

structure_selector 
    : '.' 
    | '.' ID structure_selector* 
    ; 

ID : [_a-z0-9$]+ ; 
NL : [\r\n]+ ;   
WS : [ \t]+ -> skip ; 

$ grun Question r -tokens -diagnostics t.text 
[@0,0:0='.',<'.'>,1:0] 
[@1,1:1='\n',<NL>,1:1] 
[@2,2:2='.',<'.'>,2:0] 
[@3,3:8='foobar',<ID>,2:1] 
[@4,9:9='\n',<NL>,2:7] 
[@5,10:10='.',<'.'>,3:0] 
[@6,11:16='foobar',<ID>,3:1] 
[@7,17:17='.',<'.'>,3:7] 
[@8,18:20='baz',<ID>,3:8] 
[@9,21:21='\n',<NL>,3:11] 
[@10,22:21='<EOF>',<EOF>,4:0] 
Question last update 2135 
line 3:7 reportAttemptingFullContext d=1 (structure_selector), input='.' 
line 3:7 reportContextSensitivity d=1 (structure_selector), input='.' 

$ grun Question r -gui t.text顯示分層樹形結構中,期待。