我正在编写一个C / C ++ / ...构建系统(我明白这很疯狂;)),而且我在设计解析器时遇到了麻烦。
我的“食谱”看起来像这样:
global
{
SOURCE_DIRS src
HEADER_DIRS include
SOURCES bitwise.c \
framing.c
HEADERS \
ogg/os_types.h \
ogg/ogg.h
}
lib static ogg_static
{
NAME ogg
}
lib shared ogg_shared
{
NAME ogg
}
(这是基于超级简单的libogg源代码树)
#
是注释,\
是“换行符”,意味着该行在下一行继续(请参阅QMake语法)。 {}
是范围,就像在C ++中一样,全局是适用于每个“目标”的设置。这是所有背景,而不是 相关......我真的不知道如何使用我的示波器。我需要能够拥有多个范围,还需要一种条件处理形式:
win32:DEFINES NO_CRT_SECURE_DEPRECATE
解析函数需要知道它所处的范围级别,并在范围增加时调用自身。大括号的位置也存在问题(global {
或global{
或示例中的问题。)
我怎样才能使用标准C ++和STL?我知道这是一项很多工作,而这正是我需要一个好起点的原因。谢谢!
我已经拥有的是整个ifstream和内部字符串/ stringstream存储,所以我可以读出每个单词的字数。
答案 0 :(得分:2)
我建议(并且这或多或少地在编译器教科书之外)你分阶段解决问题。这样就可以解决问题,从而使问题在每个阶段都更易于管理。
首先关注词法分析阶段。您的lexing阶段应该采用原始文本并为您提供一系列令牌,例如单词和特殊字符。词法分析器阶段可以处理行继续,并根据需要处理空格或注释。通过处理空格,词法分析器可以简化解析器的任务:您可以编写词法分析器,以便global{
,global {
,甚至
global
{
将产生两个令牌:一个代表global
,一个代表{
。
另请注意,词法分析器可以将行号和列号添加到令牌上,以便稍后在遇到错误时使用。
一旦你获得了很好的令牌流,就可以解决你的解析阶段了。解析器应该采用该标记序列并构建一个抽象语法树,该树模拟文档的语法结构。此时,您不应该担心ifstream
和operator>>
,因为词法分析者应该为您完成所有阅读。
您已经表示有兴趣在看到范围后递归调用解析函数。这当然是一种方法。正如您将看到的,您必须重复进行的设计决策是您是否真的希望以递归方式调用相同的解析函数
(允许你可能想要在语法上禁用global { global { ... } }
之类的结构),或者是否要定义一个适用于范围内的稍微(或甚至显着)不同的语法规则集。
一旦你发现自己不得不改变规则:关键是通过重构函数来重用,就像你可以在不同的语法变体之间重用一样。如果你继续朝着这个方向前进 - 使用代表你想要处理的不同语法块的单独函数,并让它们在需要的地方相互调用(可能递归) - 你最终会得到我们称之为的东西递归下降解析器。维基百科条目有一个简单的例子;见http://en.wikipedia.org/wiki/Recursive_descent_parser。
如果您发现自己真的想深入研究词法分析器和解析器的理论和实践,我建议您使用一本优秀的编译器教科书来帮助您。上面评论中提到的Stack Overflow主题将帮助您入门:Learning to write a compiler
答案 1 :(得分:2)
boost::spirit
是一个很好的递归下降解析器生成器,它使用C ++模板作为语言扩展来描述解析器和词法分析器。它适用于本机C ++编译器,但不会在Managed C ++下编译。
Codeproject有tutorial article可能会有帮助。
答案 2 :(得分:1)
ANTLR(使用ANTLRWorks)之后,您可以查找FLEX / BISON和其他人lemon。有很多工具,但ANTLR和flex / bison应该足够了。我个人非常喜欢ANTLRWorks推荐别的东西。
LATER :使用ANTLR,您可以为variety of languages生成解析器/词法分析器代码。
答案 3 :(得分:0)
除非项目的重点是学习如何编写词法分析器和shift-reduce解析器,否则我建议使用Flex和Bison,它将为您处理大部分解析grunt工作。编写语法和语义分析仍然是一大堆工作,不用担心;)