Antlr语义谓词未能找到可行的替代方案
对于.NETFramework4.8,我无法使用更简单的语义谓词来处理ANTLR4.6.6 下面的语法无法找到可行的输入选项Antlr语义谓词未能找到可行的替代方案,antlr,antlr4,antlr4cs,Antlr,Antlr4,Antlr4cs,对于.NETFramework4.8,我无法使用更简单的语义谓词来处理ANTLR4.6.6 下面的语法无法找到可行的输入选项 "received:last week" 更新: 这是我问题的简化。只有在“last week”前面加上“received”的情况下,才可能有语法将“received:last week”解析为“received”“last week”,但如果我将“subject:last week”解析为“subject”“last”“week”。当我运行此代码
"received:last week"
更新:
这是我问题的简化。只有在“last week”前面加上“received”的情况下,才可能有语法将“received:last week”解析为“received”“last week”,但如果我将“subject:last week”解析为“subject”“last”“week”。当我运行此代码时:
publicstaticvoidmain(字符串[]args){
String source=“已收到:上周”;
testLexer lexer=新的testLexer(CharStreams.fromString(source));
testParser=newtestparser(newcommontokenstream(lexer));
System.out.println(parser.parse().toString树(parser));
}
错误行1:0在输入“已接收”时没有可行的备选方案被打印到STDERR。当我将{false}?
更改为{true}?
时,输入被正确解析(如预期的那样)
如果由于{false}?
谓词,您希望输入被解析为received':'text
,那么您误解了ANTLR的lexer是如何工作的。lexer独立于解析器生成标记。解析器试图匹配文本
标记并不重要,您的输入总是以相同的方式标记
lexer的工作原理如下:
received
: RECEIVED ':' last_week
;
subject
: SUBJECT ':' text
;
last_week
: LAST WEEK
;
text
: TEXT
| LAST
| WEEK
;
RECEIVED : 'received';
SUBJECT : 'subject';
LAST : 'last';
WEEK : 'week';
TEXT : ~[ :]+;
尽可能多地使用字符
如果有两个或多个lexer规则匹配相同的字符,则让第一个定义的规则“win”
根据这些规则,很明显,“received:last week”
标记为received
,:“
和last week
标记
编辑
只有在“last week”前面加上“received”的情况下,但如果我将“subject:last week”解析为“subject”“last”“week”,那么语法是否可以将“received:last week”解析为“received”“last week”
通过使用,您可以使lexer具有一定的上下文敏感性。然后必须创建单独的lexer语法和parser语法,如下所示:
received
: RECEIVED ':' last_week
;
subject
: SUBJECT ':' text
;
last_week
: LAST WEEK
;
text
: TEXT
| LAST
| WEEK
;
RECEIVED : 'received';
SUBJECT : 'subject';
LAST : 'last';
WEEK : 'week';
TEXT : ~[ :]+;
TestLexer.g4
您可以在解析器语法中使用上述lexer:
TestParser.g4
现在,“已收到:上周”
将标记为:
'received' `received`
COLON `:`
LASTWEEK `last week`
EOF `<EOF>`
'subject' `subject`
COLON `:`
TEXT `last`
TEXT `week`
EOF `<EOF>`
编辑二
您还可以将上周创建的移动到解析器中,如下所示:
received
: RECEIVED ':' last_week
;
subject
: SUBJECT ':' text
;
last_week
: LAST WEEK
;
text
: TEXT
| LAST
| WEEK
;
RECEIVED : 'received';
SUBJECT : 'subject';
LAST : 'last';
WEEK : 'week';
TEXT : ~[ :]+;
谢谢这是我问题的简化。只有在“last week”前面加上“received”的情况下,才可能有语法将“received:last week”解析为“received”“last week”,但如果我的“subject:last week”被解析为“subject”“last”“week”,则可能有语法将其解析为“received”“last week”。你所说的lexer总是匹配最长的字符串,这意味着这是不可能实现的。我尝试在lexer lever上使用语义谓词,事实上我能够匹配上面简单示例中的那些,但是我没有足够的上下文来检查前面的标记“received”。这是一个很好的答案!非常感谢你!不客气@ekalchev。我还为稍微不同的解决方案添加了第二次编辑。
received
: RECEIVED ':' last_week
;
subject
: SUBJECT ':' text
;
last_week
: LAST WEEK
;
text
: TEXT
| LAST
| WEEK
;
RECEIVED : 'received';
SUBJECT : 'subject';
LAST : 'last';
WEEK : 'week';
TEXT : ~[ :]+;