我正在用C ++编写一个手工制作的词法分析器和解析器。我以这样的方式写了词法分析器,如果它找到例如;
它打印" SEMICOLON" ,如果它找到while
则打印< strong>&#34; KEYWORD&#34; ,如果找到hello
,则会打印&#34; IDENTIFIER&#34; 等等。但是现在我需要将这些标记传递给解析器。如何使用列表完成此操作?我发现我需要存储令牌类型和令牌值
答案 0 :(得分:0)
您显然没有使用经典方法,即解析器调用扫描程序来获取下一个令牌。通常使用拉解析器。意思是,解析器通过调用相应的函数从扫描器(Lexer)中提取令牌。最常见的扫描器/解析器生成器Lex / Yacc或Flex / Bison使用此方法。因此,解析器调用诸如getNextToken之类的东西,然后扫描器从输入流中读取字节,直到找到令牌为止。在检测到令牌(或错误)之前,它不会返回。
也有推送解析器。在此,解析器或其他对象(例如套接字)读取输入流,然后将其填充到扫描器中,直到可以识别令牌为止,然后将其返回。这有点复杂,因为扫描仪需要保持状态。最新的Bison版本支持此方法。
两者的共同点是使用类或结构(POD)“令牌”。此类通常包含令牌类型和一个或多个属性(如值)。还有许多(通常是超载的)setter和getter。这通常是解析器和扫描器之间的主要接口。
据我了解,您的方法是先运行扫描仪,使用整个输入并收集所有令牌。也可以。然后,您将所有令牌(如上所述)存储在std :: vector(或其他stl :: container)中。然后,解析器将访问该向量。
对于这种通信,您可以使用调解器模式,也可以将容器嵌入“上下文”类中,并在扫描器和解析器之间交换它。
您还可以将成员函数添加到扫描器类(getToken),该类返回令牌容器的一个元素。为此,您需要保持状态。基本上将调用基础容器的迭代器的扫描仪迭代器也是一个不错的建议。这样,您可以轻松地遍历令牌并实现(也许)执行必要的操作,例如读取前瞻符号或“疏通”某些内容。
以上基本上应该回答您的问题。
并且,为了简单的语法,这将起作用。但是对于更复杂的语法,我会推荐经典方法。可能需要进行上下文相关的扫描。例如。相同的关键字可能会产生不同的令牌。您的方法无法解决。
我建议您阅读有关Lex和Yacc的文章,不是因为您应该使用它,而是要加深了解。或者,当然,请阅读Dragon书籍或诸如“使用C编写编译器”之类的内容
您可能还想看看2个编译器示例here
希望我能帮上忙。
答案 1 :(得分:0)
以这种方式使用std::map
:
std::map<string, string> my_map = {
{ ";", "SEMICOLON" },
{ "while", "KEYWORD" },
...
};