Parsing ANTLR4中的贪心子规则

Parsing ANTLR4中的贪心子规则,parsing,antlr,antlr4,grammar,Parsing,Antlr,Antlr4,Grammar,我正在研究一种解析器语法,它应该允许在不包含符号的情况下使用尾随表达式。以下是证明该问题的简化版本: grammar Example; root: expression EOF; expression: binaryExpression; binaryExpression : binaryExpression 'and' binaryExpression | binaryExpression 'or' binaryExpression | quantifier

我正在研究一种解析器语法,它应该允许在不包含符号的情况下使用尾随表达式。以下是证明该问题的简化版本:

grammar Example;

root: expression EOF;

expression: binaryExpression;

binaryExpression
    : binaryExpression 'and' binaryExpression
    | binaryExpression 'or' binaryExpression
    | quantifier
    | '(' expression ')'
    | OPERAND
;

quantifier
    : 'no' ID 'in' ID 'satisfies' expression
;

OPERAND: 'true' | 'false';
ID: [a-z]+;
WS: (' ' | '\r' | '\t')+ -> channel(HIDDEN);
如果尝试解析以下表达式,您会注意到,尽管解析正确识别了输入,但它报告了歧义:

true or false and no x in y satisfies true or false

错误报告按预期工作(稍后将详细介绍):

如您所见,问题已经解决:

但它的代价是语法更加复杂,无法识别错误输入,如
(1


还有其他人对如何修复它有什么想法吗?

好的,在这里反复讨论了很多之后,我想我终于明白了,你想要的是关联性。试试:

grammar Example;

root: expression EOF;

expression
    : '(' expression ')'                            # parenExpr
    | <assoc=right>expression (AND | OR) quantifier # quantifierExpr
    | expression AND expression                     # andExpr
    | expression OR expression                      # orExpr
    | OPERAND                                       # operandExpr
;

quantifier
    :  'no' ID 'in' ID 'satisfies' expression
;

AND: 'and';
OR: 'or';
OPERAND: 'true' | 'false';
ID: [a-z]+;
WS: (' ' | '\r' | '\t')+ -> channel(HIDDEN);


这就是我的方法,使用Antlr4的内置算法来解决具有优先权的歧义(因为语法肯定是不明确的)。为了让优先算法发挥作用,将限定条件视为具有低优先权的一元运算符是很有用的,这就是为什么下面的
量词
是唯一的限定条件“运算符”,而不是完整表达式。可能在真正的语法中会有其他量词,很可能还有优先级更高的一元运算符,如
not

grammar Example;

root: expression EOF;

expression
    : expression 'and' expression
    | expression 'or' expression
    | quantifier expression
    | operand
    | '(' expression ')'
;

quantifier
    : 'no' ID 'in' ID 'satisfies'
;

operand: BOOLEAN | ID;

BOOLEAN: 'true' | 'false';
ID: [a-zA-Z]+;
WHITE_SPACE: (' ' | '\r' | '\n' | '\t')+ -> channel(HIDDEN);
这和你文章中的例子不太一样,因为你修改了问题的第一个版本中的一些小细节。但我认为这是指示性的


由于明显的原因,我无法使用
(1
(我假设输入对应于另一个版本,其中整数是操作数),但使用
(是的
它给了我你想要的错误报告。我不是一个真正的ANTLR4专家,所以我不知道如何预测错误恢复的细节。

两个问题:首先,你能把你失败的重构尝试包括在内吗?解决方案无疑涉及某种重构,所以最好知道为什么会这样你尝试了失败。(我不明白“它工作”和“无法识别大多数表达式”是如何共存的。)第二,你对运算符优先级的期望是什么?嗨@rici!我已经编辑了这个问题,以包括我失败的尝试。关于优先级,通常是:如我给出的语法所示,连词比析取具有更高的优先级。你能详细说明一下你的目标“不包含符号的后续表达式”吗(我并没有真正了解你想要实现的目标)?此外,我无法在您提供的任何输入组合中获得歧义错误。您使用的是什么版本的ANTLR?第二个示例错误消息是
表达式:quantifier | booleanExpression;
规则的结果,因此它尝试匹配一个量词,当它失败时,尝试识别一个布尔值并失败。(同时,我认为这两种语法都无法识别”(1)"因为它在您的语法中无效,并且两个示例都给出了相应的语法错误。嗨@Mike!感谢您的帮助,但它并没有解决问题。解析器仍然报告歧义树,请参阅:我不知怎么地没有领会您的意思。您的图像由两个不同的表达式组成,在我看来都是非歧义的(对他们的输入正确)parseTree。我想我需要一个更清晰的例子,清楚地指出你解释为歧义的内容。(你是从ANTLR得到歧义错误,还是觉得结果不明确?如果你认为结果不明确,我想我需要澄清,因为我没有看到它(可能只是“密集”)解析器可以识别,但它选择了一种可能的表示形式。我的目标是明确地告诉解析器,只有一种可能的表示形式是有效的。我共享的屏幕截图来自Intellij的ANTLR插件,显示在
有多个解释,y中没有x满足true或false
解析器仍然无法理解它们中只有一个是有效的(屏幕截图的右侧)。因此它总是一个AND(即
和y中的nox满足…
,但决不能
或y中的nox满足…
)?如果我开始跟随,似乎
实际上是你所说的尾随表达式的一部分。我是否“明白了”?(呃,仍然不认为我明白了。在两个图表的右侧(尾随表达式)是相同的,所以仍然没有看到差异。都给出了相同的子树
并且y中的nox满足true或false
(从我看到的情况)我将重试:)。对于解析器,输入
true和false或false中有两个可能的树,y中的nox满足true或false。第一个是
(真与假)或(假,y中的x满足真或假)
这正是我想要的。第二个是
((真与假)或假)和(y中的x满足真或假)
这是错误的。你可以忽略括号;这只是为了帮助我明确不同的解释。我需要告诉解析器,第一种方法是解释该表达式的唯一有效方法。在我的答案前后反复之后,我相信@MarcosPassos要找的是前面的布尔表达式“ID”中的
'no'ID'满足“
(即
量词
)与
量词
相关联,而不是与先前的内容相关联)。这并不能实现这一点。通过“贪婪”,他似乎希望量词对先前的内容“贪婪”(通常,我认为是“贪婪的”)如果我的理解是正确的,那么他需要
量词
具有正确的关联性(比如指数)@Mike:嗯,这不是我从问题中得到的。所以这很酷。他们有其他选择。希望其中一个是正在寻找的,他们最终会找到ei
line 1:1 token recognition error at: '1'
line 1:2 no viable alternative at input '('
grammar Example;

root: expression EOF;

expression
    : '(' expression ')'                            # parenExpr
    | <assoc=right>expression (AND | OR) quantifier # quantifierExpr
    | expression AND expression                     # andExpr
    | expression OR expression                      # orExpr
    | OPERAND                                       # operandExpr
;

quantifier
    :  'no' ID 'in' ID 'satisfies' expression
;

AND: 'and';
OR: 'or';
OPERAND: 'true' | 'false';
ID: [a-z]+;
WS: (' ' | '\r' | '\t')+ -> channel(HIDDEN);
true and false or false and no x in y satisfies true or false 
true and false or false or no x in y satisfies true or false
true and false or false and no x in y satisfies true or false
grammar Example;

root: expression EOF;

expression
    : expression 'and' expression
    | expression 'or' expression
    | quantifier expression
    | operand
    | '(' expression ')'
;

quantifier
    : 'no' ID 'in' ID 'satisfies'
;

operand: BOOLEAN | ID;

BOOLEAN: 'true' | 'false';
ID: [a-zA-Z]+;
WHITE_SPACE: (' ' | '\r' | '\n' | '\t')+ -> channel(HIDDEN);