【发布时间】:2013-02-10 03:06:41
【问题描述】:
C++ 我不知道如何为以下语法编写递归下降解析器:
<Datalog Program> -> Schemes : <Scheme List>
Facts : <Fact List>
Rules : <Rule List>
Queries : <Query List>
<EOF>
<Scheme List> -> <Scheme> <Scheme List Tail>
<Scheme List Tail> -> <Scheme List> | ε
<Scheme> -> <Identifier> ( <Identifier List> )
<Identifier List> -> <Identifier> <Identifier List Tail>
<Identifier List Tail>-> , <Identifier List> | ε
<Fact List> -> <Fact> <Fact List> | ε
<Fact> -> <Identifier> ( <Constant List> ) .
<Constant List> -> <String> <Constant List Tail>
<Constant List Tail> -> , <Constant List> | ε
<Rule List> -> <Rule> <Rule List> | ε
<Rule> -> <Head Predicate> :- <Predicate List> .
<Head Predicate> -> <Identifier> ( <Identifier List> )
<Predicate List> -> <Predicate> <Predicate List Tail>
<Predicate List Tail> -> , <Predicate List> | ε
<Predicate> -> <Identifier> ( <Parameter List> )
<Parameter List> -> <Parameter> <Parameter List Tail>
<Parameter List Tail> -> , <Parameter List> | ε
<Parameter> -> <String> | <Identifier> | <Expression>
<Expression> -> ( <Parameter> <Operator> <Parameter> )
<Operator> -> + | *
<Query List> -> <Query> <Query List Tail>
<Query List Tail> -> <Query List> | ε
<Query> -> <Predicate> ?
这是一个简单的类似数据记录的语法。我在尝试编写解析器时完全迷失了。我已经编写了一个词法分析器,它输出一个带有所有标记的向量。我知道我需要为每个产品编写方法,但我不知道如何将标记连接到解析树中(因此我可以在树完成后运行 toString() 函数)。我需要指出正确的方向。谢谢。
【问题讨论】:
-
这件事有很多文本,它被处理为e.g.在神话龙的书中,Aho、Sethi、Ullman 的《编译器:原理、技术和工具》。 IIRC 在 Wirth 的“算法 + 数据结构 = 程序”(这可能是他的另一本书)中有一个关于构建递归下降解析器的非常清晰的解释。
-
愚蠢的问题:你不能使用像 bison 或 byacc 这样的工具吗?以这种方式编写/维护解析器的源代码要容易得多。这些(和其他)工具提供独立的 C 程序(或 C++ 也用于野牛)。
-
老实说,正确分解语法并删除左递归是困难的部分,看起来你已经在那里了。在这一点上,这个东西应该几乎写成它自己。假设您有一个合适的词法分析器,您可以将每个产生式视为一个要调用的函数,并在此过程中撒上令牌获取以验证下一个产生式路径。做出正确的决定,在首先充分发挥作用之前,不要走捷径。
-
@vonbrand 我要去看看 GNU bison - 谢谢。
-
@WhozCraig 我知道此时大部分工作已经完成——但我无法完全理解递归下降解析器。生产方法内部发生了什么?完整的树是如何构建和连接的?
标签: c++ parsing compiler-construction