使用bison / yacc对逗号列表中的每个项重复操作

时间:2014-12-13 19:52:04

标签: grammar bison interpreter yacc

这是涉及翻译的大型家庭作业的一小部分。

基本上,我有一个操作,当完成某些事情时:

integer A, B, C

我想通过创建3个变量的过程实际运行。

目前在yacc文件中:

declare:
      INT VAR { $$ = createvar(INT_T, $2); }
    | FLT VAR { $$ = createvar(FLT_T, $2); }
    ;

其中createvar()是创建变量的中间代码生成的一部分。问题是我想允许VAR成为逗号分隔的列表,而且我真的迷失了该怎么做。我已经尝试在yacc文件中创建一个var_list,我想我可以找到一些不起眼的方法。但是,我希望尽可能多地重用代码,我认为这可能是一种递归方式。

var_list:
      VAR { $$ = $1; }
    | var_list ',' VAR { $$ = ????; }
    ;

有人可以推荐一些方法为列表中的每个值调用createvar()吗?

2 个答案:

答案 0 :(得分:1)

让我们从头开始,在自下而上的解析器的情况下是底部。

var_list将成为某种列表,它将采用某种append()方法。它需要在首次出现的地方创建,即生产

var_list ::= VAR

所以那里的行动就像是

{
    $$ = new VariableList();
    $$->append(create_var($1));
}

现在您已经启动了列表,它将附加到其他生产

| var_list ',' VAR

所以那里的动作就像

{
    $1->append(create_var($3));
    $$ = $1;
}

然后你在这里处理清单:

declaration ::= INT var_list
{
    // process elements of the var_list $2 and assign them the type INT
}

同样对于FLT案例。

答案 1 :(得分:0)

简单的方法是在var_list规则中创建名称列表:

var_list:
      VAR { $$ = create_singleton_list($1); }
    | var_list ',' VAR { $$ = append_to_list($1, $3); }

并在declare规则中运行它:

declare:
      INT var_list { $$ = create_vars_from_list(INT_T, $2); }
    | FLT var_list { $$ = create_vars_from_list(FLT_T, $2); }

当然,您需要担心列表的内存管理,以确保它们能够正确清理。

另一个偶尔有用的技巧是使用一个继承属性,bison只有有限的支持 - 你可以使用适当定位的嵌入式操作将它们显式放在解析器堆栈上,然后使用{{1 }}:

$0

要想做到这一点非常棘手,并且需要明确的演员表(危险)并且要小心谨慎。或者,您可以使用btyacc,它直接支持此功能:

declare:
      INT { $<type>$ = INT_T; } var_list
    | FLT { $<type>$ = FLT_T; } var_list

var_list:
      VAR { createvar($<type>0, $1); }
    | var_list ',' VAR { createvar($<type>0, $3); }