2

如果我像这样在 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 设施可以帮助我处理这个问题,或者我应该改变我的解析风格以避免这种尴尬的情况?

4

1 回答 1

3

有一个bison功能,但正如手册所说,请谨慎使用:

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

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

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

只要仅以bar此处所示的方式使用,总是$0指.exprbarfoo

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

有关中间规则操作的更多信息和示例,请参阅手册

于 2012-11-23T18:23:53.080 回答