以下用于解析逻辑表达式的简单语法会导致减少/减少冲突:
%token AND OR
%token NUMBER VARIABLE
%%
logical_expr
: logical_expr AND logical_term
| logical_expr OR logical_term
| logical_term
;
logical_term
: VARIABLE
| comparison
| '(' logical_expr ')'
;
comparison
: expr '<' expr
| expr '>' expr
;
expr
: expr '+' term
| expr '-' term
| term
;
term
: NUMBER
| VARIABLE
| '(' expr ')'
;
%%
来自野牛的状态报告:
state 2
4 logical_term: VARIABLE .
13 term: VARIABLE .
')' reduce using rule 4 (logical_term)
')' [reduce using rule 13 (term)]
'<' reduce using rule 13 (term)
'>' reduce using rule 13 (term)
'+' reduce using rule 13 (term)
'-' reduce using rule 13 (term)
$default reduce using rule 4 (logical_term)
我猜测问题是它无法弄清楚如何解析“(a)+ 1&lt; 2”。如何消除这种语法的歧义?有可能吗?
答案 0 :(得分:4)
语法的基本问题是,当您看到( VARIABLE
并且下一个标记是)
时,解析器无法判断这是否应该是带括号的expr
或{{ 1}} - 它取决于logical_expr
之后的下一个标记。如果下一个标记是)
。 +
,-
或<
则为expr,如果为>
或AND
(或EOF),则为OR
。
通常的解决方案是不要尝试在语法中进行类型检查。虽然它可能,但它需要额外的前瞻,可能需要多级语法或这样的复杂性。
在您的情况下,如果您将logical_expr
规则更改为
logical_term
冲突消失了,但是你的解析器会接受非类型正确的东西,例如
logical_term
: comparison
| expr
;
或a > 3 AND 2
。您需要对生成的解析树(或者您正在创建的任何数据结构)进行类型检查以确保正确性,尽管您可能仍然需要(至少您已经需要进行类型检查2 + 2 OR 7
以确保该变量是数字或布尔值,具体取决于上下文。)