2010-06-11 48 views
2

我正在写一个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 syntac)。 {}是范围,就像在C++中一样,全局是适用于每个“目标”的设置。这是所有的背景,而不是有关...我真的不知道如何与我的范围工作。我需要能够有多个范围,也有条件处理的一种形式,在该行:

win32:DEFINES NO_CRT_SECURE_DEPRECATE 

解析功能将需要知道它在什么级别的范围,称自己无论何时范围增加了。大括号的位置也有问题(global {global{或如示例中所示)。

如何使用标准C++和STL来解决这个问题?我知道这是一个很大的工作,这正是我需要一个好的起点的原因。谢谢!

我已经是整个ifstream和内部字符串/ stringstream存储,所以我可以阅读每个单词的单词。

+2

这需要使用通常的编译器/解释器方法,并且应该使用标准工具处理(请参阅http://stackoverflow.com/questions/1669/learning-to-write-a-compiler并搜索“解析器发电机“等)。 – dmckee 2010-06-11 18:39:04

+0

相关链接肯定会帮助我形成一个想法。 – rubenvb 2010-06-11 19:00:30

回答

2

我会建议(这是或多或少的编译器教科书)你分阶段接近问题。这样做可以将事情分解,使问题在每个阶段更易于管理。

首先关注词法分析阶段。你的兴趣阶段应该采用原始文本并给你一些令牌,比如单词和特殊字符。词法分析阶段可以处理续行,并根据需要处理空白或注释。通过处理的空白,词法分析器可以简化您的解析器的任务:你可以写的词法分析器,这样global{global {,甚至

global
{

都将产生两个标记:一个代表global,一个表示{

另请注意,如果您遇到错误,词法分析器可以将行号和列号添加到令牌上以备后用。

一旦你有一个很好的令牌流,你的解析阶段工作。解析器应该采用该序列的标记并构建一个抽象语法树,该语法树模拟文档的语法结构。在这一点上,你不应该担心ifstreamoperator>>,因为词法分析器应该已经为你做了所有的阅读。

您已经表示有兴趣在您看到范围后递归地调用解析函数。这绝对是一种方式。正如你所看到的,你必须反复做出的设计决定是,你是否真的想递归地调用相同的解析函数 (允许像global { global { ... } }这样的结构,你可能不想在语法上禁止),或者你是否想要定义一个稍微(或甚至显着)不同的适用于范围内的语法规则集。

一旦你发现自己不得不改变规则:关键是通过重构功能来重复使用尽可能多的东西,因为你可以在不同的语法变体之间重用。如果你继续朝这个方向前进–使用单独的函数,它们代表你想要处理的不同语法块,并让它们在需要的地方互相调用(可能递归)–你最终会以我们所说的递归下降解析器。维基百科条目有一个很好的简单例子;见http://en.wikipedia.org/wiki/Recursive_descent_parser

如果您发现自己真的想深入研究词法分析器和解析器的理论和实践,我建议您获得一本很好的编译器教科书来帮助您。在评论中提到的堆栈溢出的话题上面会帮助您了解:Learning to write a compiler

+0

这就是我想要在脑海中构思的东西。哎呀,维基百科的文章(为什么我不看那里:s)肯定会帮助我获得基本知识。谢谢 – rubenvb 2010-06-13 13:39:29

0

除非项目的要点是专门学习如何编写词法分析器和shift-reduce解析器,否则我会推荐使用Flex和Bison,它将为您处理大部分解析工作。编写语法和语义分析仍然是一大堆工作,不用担心;)

+0

嗯,我认为这是一个“学习C++的难题”学术自我导师试错法的事情,如果你明白我的意思:)。我认为这是一个有价值的原因,并且必将向我展示足够的标准库和STL,以便抓住C++恕我直言。哎呀,我甚至会在这个过程中了解编译器和链接器。 – rubenvb 2010-06-11 19:08:31

+0

@rubenvb:然后写一个递归正常的解析器。我所知道的最简单的边缘实践参考是Crenshaw教程(链接到1669年)。 – dmckee 2010-06-11 19:25:38

+0

@dmckee递归下降对于OP在他的文章中建议的复杂性的语法是否合理?我会这样认为疯狂的谎言...... – user168715 2010-06-11 19:46:25

1

ANTLR(使用ANTLRWorks),之后你可以看看FLEX/BISON和其他类似lemon。那里有很多工具,但ANTLR和flex/bison应该足够了。我个人比较喜欢ANTLRWorks来推荐别的东西。

LATER:使用ANTLR,您可以为variety of languages生成解析器/词法分析器代码。

2

boost::spirit是一个很好的递归下降解析器生成器,它使用C++模板作为语言扩展来描述解析器和词法分析器。它适用于本地C++编译器,但不能在Managed C++下编译。

Codeproject有一个tutorial article可能有所帮助。