表现出现在flex / bison中

时间:2017-09-22 11:44:47

标签: regex parsing syntax bison flex-lexer

假设我有一个像这样的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?

1 个答案:

答案 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;
                              }
                            }