【问题标题】:Passing tokens from lexer to parser将令牌从词法分析器传递到解析器
【发布时间】:2014-05-10 16:53:32
【问题描述】:

我正在用 C++ 编写一个手工制作的词法分析器和一个解析器。我编写词法分析器的方式是,如果它找到例如 ;,它会打印 "SEMICOLON",如果它找到 while,它会打印 "KEYWORD" ,如果找到hello,它会打印 "IDENTIFIER" 等。但是现在我需要将这些标记传递给解析器。例如,如何使用列表来做到这一点?而且发现需要存储token类型和token值

【问题讨论】:

  • 你能证明你的努力吗?
  • 我写了整个词法分析器,它的输出很好.....我只需要知道如何将标记传递给解析器
  • 通常你想设计一些东西,以便解析器从词法分析器数据。例如,这可以通过在 lexer 对象上调用 get_next_token() 方法来实现。
  • @j_random_hacker get_next_token(Token * tok),是这样的吗?我的意思是这个函数会填充传入的Token对象的所有字段,包括token的类型(也可以说token的种类,token的值,比如标识符的字符串)。
  • @ollydbg23:当然,这对我来说是一种实用的方法。

标签: c++ parsing lexer


【解决方案1】:

您显然没有使用经典方法,即解析器调用扫描仪来获取下一个标记。通常使用拉解析器。这意味着,解析器通过调用相应的函数从扫描器(Lexer)中提取标记。最常见的扫描仪/解析器生成器 Lex/Yacc 或 Flex/Bison 使用这种方法。因此,解析器调用 getNextToken 之类的东西,然后扫描器从输入流中读取字节,直到找到一个令牌。在检测到令牌(或错误)之前它不会返回。

还有推送解析器。在这里,输入流由解析器或其他东西(例如套接字)读取,然后填充到扫描器中,直到可以识别令牌,然后返回。这有点复杂,因为扫描仪需要维护状态。最新的 Bison 版本支持此方法。

两者的共同点是使用类或结构(POD)“令牌”。此类通常包含令牌类型和一个或多个属性,例如值。还有许多,通常是重载的 setter 和 getter。这通常是解析器和扫描器之间的主要接口。

据我了解您的方法,您首先运行扫描仪,使用整个输入并收集所有令牌。也是可以的。然后,您将所有标记(如上所述)存储在 std::vector(或其他 stl::container)中。然后解析器将访问该向量。

对于这种通信,您可以使用中介者模式,也可以将容器嵌入“上下文”类中,并在扫描器和解析器之间进行交换。

您还可以向扫描仪类 (getToken) 添加一个成员函数,该函数返回令牌容器的一个元素。为此,您需要维护状态。扫描仪的迭代器基本上会调用底层容器的迭代器,这也是一个不错的建议。有了它,您可以轻松地迭代您的令牌并实施(可能)必要的操作,例如读取前瞻符号或“取消”某些东西。

以上应该基本上回答了你的问题。

而且,对于简单的语法,这将起作用。但对于更复杂的语法,我会推荐经典方法。可能有必要进行上下文相关扫描。例如。相同的关键字可能会产生不同的标记。这是你的方法无法处理的。

我建议阅读 Lex 和 Yacc,不是因为你应该使用它,而是为了更深入地了解它。或者,当然,阅读 Dragon 的书或类似“Crafting a Compiler with C”之类的东西

您可能还想查看 2 个编译器示例 here

希望我能帮上点忙。

【讨论】:

  • 您能否通过简单的示例来编辑您的答案。这样我就可以更好地了解解析器何时从词法分析器询问令牌?
  • 另外,您能否为 Lex 和 Yacc 提供最佳资源
  • 我无法将整个源代码放入答案中。太多了 。 . .请按照分析器中的链接获取工作示例代码。 Lex/Yacc/Flex/Bison 文档可以在这里找到:dinosaur.compilertools.net
  • 感谢您的帮助。
【解决方案2】:

以这种方式使用std::map

std::map<string, string> my_map = {
    { ";", "SEMICOLON" },
    { "while", "KEYWORD" },
    ...
 };

【讨论】:

    猜你喜欢
    • 2011-02-03
    • 2021-06-29
    • 1970-01-01
    • 1970-01-01
    • 2013-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-07
    相关资源
    最近更新 更多