我想用像Matlab冒号运算符这样的运算符写一个语法,其中"a:b"one_answers"a:b:c"意味着稍微不同的东西。我更希望操作符是非结合的,因为"a:b:c:d"等没有意义。
这是我的语法的精简版本,以显示我是如何做到的:
%union {
int ival;
}
%token tINT
%nonassoc ':'
%%
program: { }
| expression ';' { }
expression: tINT { }
| expression ':' expression { }
| expression ':' expression ':' expression { }
由于某些原因,bison忽略了第二个冒号规则,并给出如下消息:
test.y:16.13-56: warning: rule useless in parser due to conflicts [-Wother]
| expression ':' expression ':' expression { }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
为什么bison不明白我在这里想要什么,我怎样才能改变我的语法使它工作?
编辑:如果有帮助,"bison -v"的输出包含
State 7
4 expression: expression . ':' expression
4 | expression ':' expression .
5 | expression . ':' expression ':' expression
5 | expression ':' expression . ':' expression
':' error (nonassociative)
$default reduce using rule 4 (expression)
尽管我仍然不明白为什么野牛不允许这样做,也不明白如何解决这个问题。
您已经指定':'操作符是非关联的。去掉它,你就会得到预期的A:B:C冲突,可以解析为A:B:C, (A:B):C和A:(B:C)之一。
但是由于你想要它是非结合律的,这里有一种方法:
%token tINT
%%
program: { }
| colonexpression ';' { }
;
colonexpression: expression { }
| expression ':' expression ':' expression { }
| expression ':' expression { }
;
expression: tINT { }
;
%%
啊!经过一番折腾,我终于找到了一种有效的方法,并且仍然允许我以"正确"的方式使用优先级,尽管如果我想避免大量的shift/reduce警告,它需要我为可以出现在表达式中的所有终端分配优先级。它还需要一个虚拟令牌来给单冒号规则一个适当的优先级(略低于':',以避免可理解的shift-reduce冲突)。
我对必须为像tINT这样的终端分配优先级并不完全满意,因为我的实际语法有一堆这样的东西,但我想这将不得不做,如果没有人有更好的主意。
%union {
int ival;
}
%token tINT
%precedence nCOLON
%nonassoc ':'
%precedence tINT
%%
expression: tINT { }
| expression_colon expression %prec nCOLON { }
| expression_colon expression ':' expression { }
expression_colon: expression ':'
难道不能简单地使它具有适当的优先级,然后作为操作代码的一部分,如果有超过2个冒号,就抛出错误吗?也就是说,不要试图在语法中处理这个问题,而是将其作为语义约束,在C代码中强制执行。
我在想这样的东西——注意,这是纯粹的伪代码,因为我不知道你在构建什么样的解析树,但让我们假设你在构建一个抽象的语法树——
expression
: expression ':' expression
{
if (Head($1) == DoubleColon)
yyerror("Three-colon expressions are not allowed.");
else if (Head($1) == Colon)
$$ = DoubleColon(element_of($1, 1), element_of($1, 2), $3);
else
$$ = Colon($1, $3);
}
根据您处理括号的方式,这可能会变得更复杂一些。(例如,如果你在解析树中显式地对它们进行编码,你可以使用上述技术,但否则你将需要一种方法来区分(a:b):c
和a:b:c
。)