c++ - 将标记从词法分析器传递到解析器

标签 c++ parsing lexer

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

最佳答案

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

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

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

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

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

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

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

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

我建议阅读 Lex 和 Yacc,不是因为你应该使用它们,而是为了获得更深入的理解。或者,当然,阅读 Dragon 书或诸如“使用 C 编写编译器”之类的东西

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

希望我能帮上一点忙。

关于c++ - 将标记从词法分析器传递到解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23583872/

相关文章:

java - 在 Java 中使用 JSoup 解析 CSS

java - ANTLR:Unicode 字符扫描

ANTLR如何使用以相同的开头的词法分析器规则?

c++ - OpenGL 抗锯齿不起作用

c++ - 动态链接和 Python SWIG (C++) 在 C++ 中工作在 python 中失败

parsing - 递归下降解析器的示例

java - 如何解析具有直接值的数组,两次 json 编码

c++ - 如何在 Clang AST 中的 SourceLocation 之后找到字符的 SourceLocation?

c++ - 键/值数组的双调排序

c++ - 分词器效率问题