flex/bison 中的表达式出现次数

Expression occurrences in flex/bison

假设我有一个这样的 Bison 表达式:

multiply:    T_FIGURE                     { $$ = ; }
        |    multiply T_ASTERISK multiply { $$ =  * ; }
;

它应该 return 一些数字相乘的结果,或者如果只提供一个数字则返回输入。如果我想将提供的数字限制为最多 3 个,我将重写表达式如下:

multiply:   T_FIGURE                                          { $$ = ; }
      |     T_FIGURE T_MULTIPLY T_FIGURE                      { $$ =  * ; }
      |     T_FIGURE T_MULTIPLY T_FIGURE T_MULTIPLY T_FIGURE  { $$ =  *  * ; }
;

我的问题:有没有办法重写这个表达式,这样我就不必手动指定出现次数,而是使用某种参数能够轻松地将上限更改为例如 30出现次数?

一句话,"No"。这不是野牛的特征(也不是我所知道的任何 yacc 衍生物)。

解决此类问题的最简单方法是使用代码生成器。要么使用像 m4 这样可用的宏处理器,要么用任何你觉得舒服的脚本语言编写你自己的脚本table。

您还可以通过对语义操作中的参数进行计数来动态解决问题(这意味着修改语义类型以同时包含值和计数。)如果超出计数,则可能会抛出语法错误。 (同样,在你的语义动作中。)这种方法的主要优点是避免破坏解析器的状态 table。如果您的限制很大并且相互影响,您可能会发现您正在生成一个非常大的状态机。

作为一个非常简单的例子(只有一个运算符):

%{
   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 = ; }
multiply: expr
        | multiply '*' expr { if (.count >= LIMIT) {
                                yyerror("Too many products");
                                YYABORT;
                              }
                              else {
                                $$.count = .count + 1;
                                $$.value = .value * .value;
                              }
                            }