![](/img/trans.png)
[英]ANTLR4 parser errors in code when Intellij plugin constructs it correctly
[英]Unexpected Antlr4 parser errors
我在 Antlr4 中發現了一個奇怪的行為(我嘗試了 4.10 和 4.10.1 版本,結果相同)。
當我嘗試使用語法時
grammar Paths;
cfg: NL? (entry (NL | EOF))* EOF;
entry: path ':' value;
path: SEGMENT ('.' SEGMENT)*;
value: USTRING;
SEGMENT: [a-zA-Z0-9]+;
USTRING: [a-zA-Z0-9]+;
NL: [\n\r]+;
WS: [ \t]+ -> skip;
在字符串"key1:value1\nkey2.sub:value2\nkey3.sub1.sub2:value3"
上,我看到錯誤消息:
line 1:5 mismatched input 'value1' expecting {':', '.'}
line 2:9 mismatched input 'value2' expecting {':', '.'}
line 3:15 mismatched input 'value3' expecting {':', '.'}
如果我用value: SEGMENT
替換value
definition ,一切都會按預期進行。
第一個定義有什么問題?
兩種情況下 tree 的 output 是一樣的:
(cfg (entry (path key1) : (value value1)) \n (entry (path key2 . sub) : (value value2)) \n (entry (path key3 . sub1 . sub2) : (value value3)) <EOF> <EOF>)
我試圖簡化語法:
grammar Paths;
cfg: NL? (entry (NL | EOF))* EOF;
entry: path ':' value;
path: SEGMENT;
value: USTRING;
SEGMENT: [a-zA-Z0-9]+;
USTRING: [a-zA-Z0-9]+;
NL: [\n\r]+;
WS: [ \t]+ -> skip;
在這種情況下,我有錯誤(解析的字符串是"key1:value1\nkey2:value2\nkey3:value3"
):
line 1:5 mismatched input 'value1' expecting USTRING
line 2:5 mismatched input 'value2' expecting USTRING
line 3:5 mismatched input 'value3' expecting USTRING
如果我在value
定義中用SEGMENT
替換USTRING
,一切都很好。 Output 是
(cfg (entry (path key1) : (value value1)) \n (entry (path key2) : (value value2)) \n (entry (path key3) : (value value3)) <EOF> <EOF>)
這是因為 ANTLR 的 Lexer 處理輸入的字符 stream 以產生令牌 stream,解析器處理令牌 stream。ANTLR 中的遞歸下降解析正在處理令牌 stream,並且對 Lexer 如何查看輸入沒有影響。
Lexer 規則SEGMENT
和USTRING
是相同的,因此,這兩個規則將完全匹配相同的輸入字符運行。 當發生這種情況時,ANTLR 將匹配第一個規則,因此它們都將是“SEGMENTS”標記。
如果您已經完成了標准設置(並創建了grun
別名,您可以使用 `-tokens 選項運行它以獲取令牌 stream 的轉儲。這通常是驗證您的 Lexer 規則是否正在創建令牌的好主意您期望的 stream。
發生這種情況是因為 Antlr 分配給值類型 '''SEGMENT'''。 Lexer 忽略語法,如果有可以分配給不同類型的標記,lexer 將它們分配給一個隨機類型。
這段代碼幫助了我:
val lexer = PathsLexer(CharStreams.fromString("key1:value1\nkey2.sub:value2\nkey3.sub1.sub2:value3"))
val tokens = CommonTokenStream(lexer)
tokens.fill()
println(tokens.getTokens.asScala.map { token =>
s"$token: ${token.getType} -> ${lexer.getVocabulary.getDisplayName(token.getType)}"
}.mkString("\n"))
可能我需要了解更多關於 Antlr 模式的知識。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.