野牛如何获取令牌值(不是语义值)

时间:2014-10-29 23:58:58

标签: bison flex-lexer bisonc++

是否可以恢复令牌的价值?

我的规则类似于:

unaryOperation:
      NOT       { $$ = new UnaryOP(NOT); }
    | PLUS      { $$ = new UnaryOP(PLUS); }
    | MINUS     { $$ = new UnaryOP(MINUS); }
    ;

NOT,PLUS和MINUS是令牌,我也在我的程序中使用生成的定义。有可能恢复这些数据而不是在同一行重复自己吗?

我对语义值不感兴趣,所以我写这个不正确:

unaryOperation:
      NOT       { $$ = new UnaryOP($1); }
    | PLUS      { $$ = new UnaryOP($1); }
    | MINUS     { $$ = new UnaryOP($1); }
    ;

谢谢

1 个答案:

答案 0 :(得分:0)

bison不需要知道哪个令牌被识别,因为该信息实际上是堆栈状态的一部分。但是,如果启用了调试,则bison表包含每个缩减的右侧的编码版本,这允许内置跟踪功能生成人类可读的跟踪。

理论上你也可以使用这些信息,但它不会是你想要的,因为bison将flex令牌数转换成连续的序列(以允许更紧凑的解析表)并且不提供任何翻译方法他们回来了。所以这将是乏味的。

更好的解决方案是使用您当前忽略的语义值(假设它具有整数变体)。分配语义值的成本是微不足道的,因为野牛真的需要将每个令牌的语义值初始化为某种东西。

因此,合理的弹性/野牛解决方案可能是:

柔性

%union {
   int intval;
   /* ... other semantic values */
}

%%

 /* All the other rules come first */

 /* Default rule which just passes any character through to bison
  * (see note)
  */
.  { return (yylval.intval = yytext[0]); }

野牛

 /* This declaration is only necessary because these tokens
  * have a semantic value
  */
%token <intval> '-' '+' '!'

%%

unaryOperation
    : '!'     { $$ = new UnaryOP($1); }
    | '+'     { $$ = new UnaryOP($1); }
    | '-'     { $$ = new UnaryOP($1); }
    ;

注意:我删除了令牌名称NOTPLUSMINUS,因为我更喜欢使用单字符令牌代表自己的风格。这里的区别在于,flex规则设置语义值(到相同的数字)。如果操作符是多字符的,那么你也可以这样做:

柔性

'!='   { return (yylval.intval = NOTEQUAL); }