语法树

时间:2010-12-07 17:54:10

标签: algorithm parsing tree grammar

我在大学有一个实验室。但我不明白我是怎么做到的。 我有一些语言的语法(例如,算术表达式语法)。我必须构建这种语法的树(我不知道如何)。然后我必须确定,输入句子是否是这种语言的句子?我该怎么做? 附:我读过龙书的几个章节,但我找不到任何我需要的东西。 P.P.S.我不能使用lex / flex和yacc / bison。


编辑抱歉!我更加专注。真的我有一个语法,我必须使用这个语法和输入句子(我明白该怎么做)构建树,如果可能的话(在另一种情况下我必须显示关于它的消息)。有没有简单的理解它的算法?我可以使用任何简单语言的语法,如算术表达式。

3 个答案:

答案 0 :(得分:3)

我认为这是理论上的,因为它是家庭作业,而不是你现在需要编码的东西。 (肯德里克的答案涵盖了代码方法)

基本思路是从你的BNF开始变量开始,尝试弄清楚如何扩展它,一次应用一个规则,看看你是否可以提出你的输入序列。

对于如下规则集:

(1) start: expression

(2) expression: expression '+' term
(3)           | expression '-' term
(4)           | term

(5) term: 'a'
(6)     | 'b'

鉴于表达式a + b - a,您可能会这样:

一个。 start(给定)
expression(1)
C。 expression '-' term(3)
d。 expression '-' 'a'(5)
expression '+' term '-' 'a'(2)
F。 term '+' term '-' 'a'(4)
G。 'a' '+' term '-' 'a'(5)
H。 'a' '+' 'b' '-' 'a'(6)

这就是你如何一步一步地做到这一点......现在的诀窍是,你需要追踪你所有的规则调用。所以你真正的树看起来像这样:

                          start
                            | (b)
                        expression
                        /   |   \ (c)
               expression  '-'  term
                /  |  \ (e)       | (d)
       expression '+' term       'a'
           | (f)        | (h)
          term         'b'
           | (g)
          'a'

一开始有点复杂,但是一旦你真正看到它是如何完成的,它就不会太难接受。

注意:有些人发现向后工作更容易,从输入开始,然后反向应用规则以尝试查找起始表达式。当你编写解析器时,你将不可避免地需要在某种程度上遵循这条路线。

编辑:我使用上面的小写字母列出了所有表达式步骤,然后显示树中的每组分支实际上与其中一个规则应用程序对应。可能会或可能没有帮助。

答案 1 :(得分:2)

我已经做了很长时间了,所以我会给你简短的理论答案。我相信其他人会有更深入的解释。

由于你还没有说你做了什么(并且你将来作为问题的一部分),第一步是标记输入。

获得令牌后,您可以构建一个状态机来移动令牌并将其推入所需的树结构中。这应该在你的书中介绍(我还没有读过),但你可能想从纸上(或电子版)建立模型开始,并考虑每一步的有效输入。什么是相等声明的有效左手值?如果树上有令牌x,你可以从哪里出发?

如果您无法从当前状态确定下一步,那么您可能需要在状态机中实现预测(是否需要这取决于您的语言的复杂程度)。

同样,我在十多年内没有这样做,所以我的回忆是模糊的。希望我已经为你提供了足够的框架来改进你的答案,或者让那些对这个主题更有了解的人给我带来错误或过时的问题(从而得到你正在寻找的答案作为一个群体)。

答案 2 :(得分:1)

我想回答这个问题,但是没有足够的材料可以使用 - 我留下了这些问题:

  • 由于这是一所大学实验室,是否有随附的学习材料或课程?还有,你有多少时间?
  • 到目前为止你尝试了什么?
  • 您可以将给定语法硬编码到您的程序中,或者您的程序是否需要能够从文件中读取任何语法并从中构建解析树?
  • 语法有多复杂;具体来说:他们是递归的吗?
  • 语法标记是单字符还是多字符?

编辑:考虑评论和更新的问题:我认为最直接的方法是递归下降解析器,它在输入匹配时构建树。寻找Niklaus Wirth的“编译器构建”一书,该书已在网上以PDF格式提供,并描述了一种简单语言的RDP。

递归下降解析器的基本思想是语法中的每个规则都对应一个函数,每个函数检查下一个令牌并调用相应的next-lower解析函数。例如,如果您的语法有规则

expression : constant '+' constant

相关的解析方法如下所示:

void parseExpression() {
    parseConstant();
    Token token = peek_at_next_token();
    if (token == '+') {
        parseConstant();
        ... tree building code here ...
    }
    else
        throw ParseException("Expected '+', found "+token);
}

但请参阅此问题的其他答案。

相关问题