如何解析依赖父母信息的子节点?

时间:2012-11-23 16:32:19

标签: parsing compiler-construction bison yacc

如果我在Yacc / Bison中写这样的语法文件:

Module
    :ModuleName "=" Functions
      { $$ = Builder::concat($1, $2, ","); }

Functions
    :Functions Function
      { $$ = Builder::concat($1, $2, ","); }
    | Function
      { $$ = $1; }

Function
    : DEF ID ARGS BODY
      {
          /** Lacks module name to do name mangling for the function **/
          /** How can I obtain the "parent" node's module name here ?? **/
          module_name = ; //????

          $$ = Builder::def_function(module_name, $ID, $ARGS, $BODY); 
      }

此解析器应解析如下代码:

main_module:
    def funA (a,b,c) { ... }

在我的AST中,名称" funA"应重命名为main_module.funA。但是当解析器处理Function节点时,我无法获取模块的信息!

是否有任何Yacc / Bison设施可以帮助我解决这个问题,还是应该改变我的解析风格以避免这种尴尬的情况?

1 个答案:

答案 0 :(得分:3)

bison功能,但正如manual所述,请谨慎使用:

  

$N允许N为零或负数,以便在之前对与当前规则匹配的标记和分组进行引用。这是一种非常危险的做法,要可靠地使用它,您必须确定应用规则的上下文。在这种情况下,您可以可靠地使用它:

 foo:      expr bar '+' expr  { ... }
         | expr bar '-' expr  { ... }
         ;

 bar:      /* empty */
         { previous_expr = $0; }
         ;
  

只要bar仅以此处显示的方式使用,$0始终引用expr定义bar之前的foo

更清楚的是,您可以使用中间规则操作(在Module中)将模块名称推送到名称堆栈(这必须是解析上下文的一部分)。然后,您将在规则结束时弹出堆栈。

有关中规则操作的详细信息和示例,请参阅manual