yacc(野牛)简化

时间:2012-04-23 19:10:09

标签: yacc abstract-syntax-tree

让我说我的.y语法的一部分是这样的:

stmt : expr { $$ = $1; }
      | stmt expr { $$ = insert_stmt_list($1, $2); }

其中我可以有一个给出表达式的语句,或者我可以有几个表达式来生成一个语句列表。 关于后者我通过insert_stmt ...函数存储它,但是第一个我将它发送到堆栈的顶部。

我的问题是:我如何处理$$ = $ 1? 我的意思是,insert_stmt_list将所有内容都放在一个结构中,我知道它就在那里,我可以打印它们的值等等,但是在地狱中,$$ = S1会去哪里?怎么看? : - )

谢谢!

2 个答案:

答案 0 :(得分:1)

Re:如何阅读?

你有一个左递归语法,首先必须识别expr。这减少到stmtmake_new_stmt_list生成的语义值通过stmt1变为$$ = $1;的语义值。

这只是意味着“从右侧(恰好是唯一的一个)获取第一个符号的语义值,并将其作为左侧的语义值传播”。

然后,如果看到另一个expr,则解析继续进行另一个生成:

stmt : ...
     | stmt expr { $$ = insert_stmt_list($1, $2); }

此处,来自右侧$1的{​​{1}}是在先前缩减中分配给stmt的语义值,其产生$$

您已设计了系统,以便stmt可用作expr。此外,stmt生成的值适合作为expr的任一参数:表达式是列表。

所以:

  1. 如果你的输入只有一个表达式E,那么出现的insert_stmt_list就是那个表达式。

  2. 如果您有两个表达式E1和E2,则stmt的emeges是以下结果:

    stmt
  3. 如果您有三个表达式,那么整体insert_stmt_list(E1, E2) 就是这些调用的结果:

    stmt
  4. 等等。这是否有意义取决于此“插入”操作的语义。

答案 1 :(得分:0)

写这样的东西更加惯用:

stmt : expr { $$ = make_new_stmt_list($1); }
      | stmt expr { $$ = insert_stmt_list($1, $2); }

无论如何,您需要将表达式数据结构包装在语句列表数据结构中。