【问题标题】:How to use Yacc to translate a language to C++?如何使用 Yacc 将语言翻译成 C++?
【发布时间】:2013-02-17 21:11:34
【问题描述】:

这是一个更笼统的问题,因为我真的不知道如何开始。基本上,我必须使用 Yacc 来解释/翻译一种叫做 CALC 的虚构语言,它可以对变量执行算术运算,然后将它们打印出来。我已经完成了解释工作,但我项目的第二部分是编写一个 C++ 文件,其中包含原始文件中的所有指令,已翻译。

我的问题是,我该怎么做?我是在语法规则的代码中写入文件,还是在 main 中写入?我一直在尝试在语法规则代码中执行此操作,但我发现数据正在向后写入文件(也就是说,如果我声明了四个变量,程序会打印出原始文件中声明的最后一个先编程,以此类推)。

【问题讨论】:

  • 这个真的不清楚。如果你已经解决了 Yacc 部分,为什么还要问 Yacc?
  • 还是和 Yacc 相关的。我已经解释了该语言,但我必须使用 Yacc 编写一个与给定程序执行相同操作的 C++ 文件。
  • @user1174511 如果您已经实现了解释,那么您已经拥有某种形式的包含代码的抽象数据结构(例如,AST 或 ASG)。您可以遍历这个结构并将其“序列化”为 C++。

标签: c++ yacc translate


【解决方案1】:

嗯,Yacc 确实进行了自下而上的解析。

您大致有两种选择:

  1. 当输入导致减少并且附加代码被执行时,您可以像现在一样输出结果,但是您将需要一直重新排序。

  2. 您可以在规则中构建abstract syntax tree,然后按顺序遍历它。这是通常的做法。

【讨论】:

    【解决方案2】:

    我将分两个阶段执行此操作:使用 yacc 创建解析树,然后遍历树以输出需要输出的任何内容。

    【讨论】:

      【解决方案3】:

      数据正在向后写入文件

      这听起来像是您选择了与您想要的不同的构造。 Yacc 允许左递归和右递归,这让您(例如)按照您看到每个项目的顺序(左递归)或相反的顺序解析列表。这是您现在可能正在执行的正确递归的示例:

      list : ITEM
           | ITEM list
      

      请注意,当此子语法在输入中看到一个 ITEM 时,它不知道仅基于此使用这两个产生式中的哪一个 - 它们都以一个 ITEM 开头。因此,解析器向前看一个令牌。如果下一个令牌不是 ITEM,则它知道使用第一个产生式。但是如果下一个令牌是一个项目,那么它必须处理第二个产生式。但是该产生式中包含非终结符list,这意味着解析器实际上并没有减少,而是将第一个ITEM推入堆栈并寻找另一个list

      这样做的结果是,如果你给这个子语法一个 ITEM 标记的列表,它会一直将它们压入堆栈,直到它最终看到一个没有被另一个 ITEM 跟随的 ITEM。那时,最终的 ITEM 将被第一个产生式减少(从而变成list,所有其他 ITEM 将被第二个产生式一个一个减少。在左递归上。

      list : ITEM         /* matches first ITEM in list */
           | list ITEM    /* matches all other ITEMs in list */
      

      这一次,当解析器看到一个 ITEM 时,只有一个 list 产生式以 ITEM 开头,所以它会立即减少第一个产生式,将该 ITEM 变成一个 list。现在,如果输入流中有另一个 ITEM,它将尝试匹配 list 后跟一个 ITEM,并且与第二个产生式完全匹配。

      这些是解析简单列表的常用习语。请注意,如果您的列表是“零个或多个”而不是“一个或多个”,那么您只需使用一个空产生式而不是包含单个项目的一个产生式。使用左递归(您通常想要的),拥有一个与第一项匹配的单独产生式为您提供了一个方便的地方来放置一个操作,例如,初始化一个数组,该数组将保存(可能)跟随的所有 ITEM。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-27
        • 2018-06-09
        • 1970-01-01
        • 1970-01-01
        • 2014-11-04
        • 2011-01-04
        相关资源
        最近更新 更多