如果我在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设施可以帮助我解决这个问题,还是应该改变我的解析风格以避免这种尴尬的情况?
答案 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。