假设我有一个像这样的Bison表达式:
multiply: T_FIGURE { $$ = $1; }
| multiply T_ASTERISK multiply { $$ = $1 * $3; }
;
如果只提供一个数字,它应该返回一些数字相乘的结果或返回输入。如果我想限制提供的数字最多为3,我会重写这样的表达式:
multiply: T_FIGURE { $$ = $1; }
| T_FIGURE T_MULTIPLY T_FIGURE { $$ = $1 * $3; }
| T_FIGURE T_MULTIPLY T_FIGURE T_MULTIPLY T_FIGURE { $$ = $1 * $3 * $5; }
;
我的问题:有没有办法重写这个表达式,这样我就不必手动指定出现的情况,而是使用某种参数来轻松地将上限改为,例如30 OCCURENCES?
答案 0 :(得分:1)
总之,“不”。这不是野牛的特征(也不是我所知道的任何yacc衍生物)。
解决此类问题的最简单方法是使用代码生成器。使用像m4
这样的可用宏处理器,或者用您认为合适的脚本语言编写自己的脚本。
您还可以通过计算语义操作中的参数来动态解决问题(这意味着修改语义类型以包含值和计数。)如果超过计数,则可能会抛出语法错误。 (再次,在你的语义动作中。)这种方法的主要优点是避免炸毁解析器的状态表。如果你的限制很大并且相互影响,你可能会发现你正在生产一个非常大的状态机。
作为一个非常简单的例子(只有一个运算符):
%{
typedef struct ExprNode {
int count;
double value;
} ExprNode;
%}
%union {
ExprNode expr;
double value;
}
%token <value> T_FIGURE
%type <expr> expr multiply
%%
expr: T_FIGURE { $$.count = 0; $$.value = $1; }
multiply: expr
| multiply '*' expr { if ($1.count >= LIMIT) {
yyerror("Too many products");
YYABORT;
}
else {
$$.count = $1.count + 1;
$$.value = $1.value * $3.value;
}
}