Parsing ANTLR4上下文敏感规则:语义谓词失败时意外的分析/重新同步
我正在研究一种上下文敏感的语法。以下是它的描述:Parsing ANTLR4上下文敏感规则:语义谓词失败时意外的分析/重新同步,parsing,antlr4,Parsing,Antlr4,我正在研究一种上下文敏感的语法。以下是它的描述: 它描述了一组表达式 每个表达式包含一个或多个由逻辑运算符分隔的部分 每个部分由可选字段标识符、一些比较运算符(也是可选的)和值列表组成 值也由逻辑运算符分隔 默认值是一个字符序列。有时(取决于上下文),可以扩展每个值的一组可能字符。它甚至可以使用比较运算符(根据第三条规则,用于将字段标识符从值列表中分离)将其视为值的字符 以下是语法的简化版本: grammar TestGrammar; @members { boolean isValu
- 它描述了一组表达式李>
- 每个表达式包含一个或多个由逻辑运算符分隔的部分李>
- 每个部分由可选字段标识符、一些比较运算符(也是可选的)和值列表组成李>
- 值也由逻辑运算符分隔李>
- 默认值是一个字符序列。有时(取决于上下文),可以扩展每个值的一组可能字符。它甚至可以使用比较运算符(根据第三条规则,用于将字段标识符从值列表中分离)将其视为值的字符
grammar TestGrammar;
@members {
boolean isValue = false;
}
exprSet: (expr NL?)+;
expr: expr log_op expr
| part
| '(' expr ')'
;
part: (fieldId comp_op)? values;
fieldId: STRNG;
values: values log_op values
| value
| '(' values ')'
;
value: strng;
strng: ( STRNG
| {isValue}? comp_op
)+;
log_op: '&' '&';
comp_op: '=';
NL: '\r'? '\n';
WS: ' ' -> channel(HIDDEN);
STRNG: CHR+;
CHR: [A-Za-z];
我在strng规则中使用语义谓词。它应该根据isValue变量扩展可能的令牌集
当语义谓词的计算结果为false时,就会出现问题。我希望2个STRNG令牌(它们之间带有“=”令牌)将被视为part节点。相反,它将每个STRNG标记解析为值,并在重新同步时抛出“=”标记
以下是不正确的输入字符串和生成的表达式树:
a && b=c
要查看正确的表达式树,从strng规则中删除一个带有语义谓词的替代项就足够了(这使得它是静态的,因此不适合我的解决方案):
下面是生成的表达式树:
顺便说一句,当语义谓词的计算结果为true时-结果与预期一致:strng规则匹配扩展的标记集:
strng: ( STRNG
| {!isValue}? comp_op
)+;
请解释为什么会发生这种情况,并帮助找出正确的解决方案。谢谢 从
值中删除一个选项如何?否则,文本a&&b
可能是
expr
->expr
log\u op
expr
或
expr
->部分
->值
日志操作
值
。
似乎Antlr通过使用第二个选项解决了这个问题
values
: //values log_op values
value
| '(' values ')'
;
我相信你的expr
规则写错了顺序。尝试将二进制表达式移动为最后一个替代项,而不是第一个 好的,我意识到目前的方法不适合我的任务
我选择了另一种基于覆盖Lexer的nextToken()和emit()方法的方法,如中所述
它让我几乎完全控制了代币流。我有以下优点:
- 将所需类型分配给令牌李>
- 推迟向解析器发送尚未定义类型的令牌(通过在隐藏通道上发送假令牌)李>
- 分割和合并代币的可能性李>
- 可以将推迟的代币组织到队列中
有了所有这些可能性,我能够解决解析器中的所有歧义
另外,感谢所有试图帮助我的人,我很感激 谢谢你的回答!不幸的是,这没有帮助。主要原因是:以这种方式不可能表示值列表,每个部分将只有一个值,可能包含在括号内。不管怎样,我试过了,但没有成功。。。它仍然将“b=c”表示为两个部分,并在语义谓词的计算结果为false时抛出“=”标记……不幸的是,它没有帮助。结果与第一个屏幕截图上的结果相同。似乎当语义谓词失败时,它会抛出FailedPredicateException异常,强制执行错误恢复过程,该过程将通过调用堆栈向下到达根(exprSet)节点。没有叶子的第二分枝。似乎解析器在恢复过程中启动了故障安全策略(如《最终ANTLR参考》一书中“错误恢复故障安全”子章节所述)。无论如何,还不清楚为什么在恢复过程中找不到正确的替代方案。我还需要进一步研究。特别是关于恢复:ANTLR 4在任何情况下都不会执行任何回溯。如果预测在第一次尝试时未能返回正确的备选方案,那么它将无法完全返回正确的备选方案。
values
: //values log_op values
value
| '(' values ')'
;