Algorithm 语法树

Algorithm 语法树,algorithm,parsing,tree,grammar,Algorithm,Parsing,Tree,Grammar,我在大学里有一个实验室。但我不明白我怎么能做到。 我有某种语言的语法(例如,算术表达式语法)。我必须建立这个语法树(我不知道怎么做)。然后我必须确定,输入的句子是否是这种语言的句子?我怎么做? 顺便说一句,我读了《龙之书》的几章,但还没有找到我需要的东西。 我不能用lex/flex和yacc/bison 编辑对不起!我应该更专心一点。真的,我有一个语法,我必须用这个语法和输入句子建立树(我知道怎么做),如果可能的话(在另一种情况下,我必须显示有关它的信息)。有什么简单的算法可以理解吗?我可以使

我在大学里有一个实验室。但我不明白我怎么能做到。 我有某种语言的语法(例如,算术表达式语法)。我必须建立这个语法树(我不知道怎么做)。然后我必须确定,输入的句子是否是这种语言的句子?我怎么做? 顺便说一句,我读了《龙之书》的几章,但还没有找到我需要的东西。 我不能用lex/flex和yacc/bison



编辑对不起!我应该更专心一点。真的,我有一个语法,我必须用这个语法和输入句子建立树(我知道怎么做),如果可能的话(在另一种情况下,我必须显示有关它的信息)。有什么简单的算法可以理解吗?我可以使用任何简单语言的语法,比如算术表达式。

我已经很久没有这样做了,所以我将给你一个简短的理论答案。我相信其他人会有更深入的解释

因为你还没有说你做了什么(你应该在将来的问题中这样做),所以第一步是标记输入

一旦您拥有了令牌,您就可以构建一个状态机来遍历令牌并将其推送到所需的树结构中。这应该包含在你的书(我还没有读过),但你可能要开始建立一个模型在纸上(或电子),并考虑有效的输入从每一个步骤。等式语句的有效左手值是多少?如果你在树上有令牌x,你可以从这里去哪里

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


再说一次,我已经10多年没有这样做了,所以我的记忆很模糊。希望我已经为您提供了足够的框架来完善您的答案,或者给其他对此问题有更深入了解的人,以批评我的错误或过时(从而得出您作为一个群体正在寻找的答案)。

我想回答这个问题,但实际上没有足够的材料可供使用-我只剩下以下问题:

  • 因为这是一个大学实验室,没有附带的学习材料或课程吗?还有,你还有多少时间
  • 到目前为止你试过什么
  • 您可以将给定的语法硬编码到您的程序中,或者您的程序需要能够从文件中读取任何语法并从中构建解析树吗
  • 语法有多复杂;具体来说:它们是递归的吗
  • 语法标记是单字符还是多字符
编辑:将注释和更新的问题考虑在内:我认为最直接的方法是递归下降解析器,它在输入匹配时构建树。查找Niklaus Wirth的“编译器构造”一书,该书已在web上以PDF格式提供,它描述了一种简单语言的RDP

递归下降解析器的基本思想是语法中的每个规则对应一个函数,每个函数检查下一个标记并调用对应的下一个较低的解析函数。例如,如果你的语法有一条规则

表达式:常量“+”常量

关联的分析方法如下所示:

void parseExpression() {
    parseConstant();
    Token token = peek_at_next_token();
    if (token == '+') {
        parseConstant();
        ... tree building code here ...
    }
    else
        throw ParseException("Expected '+', found "+token);
}
                          start
                            | (b)
                        expression
                        /   |   \ (c)
               expression  '-'  term
                /  |  \ (e)       | (d)
       expression '+' term       'a'
           | (f)        | (h)
          term         'b'
           | (g)
          'a'

但也可以看到这个问题的其他答案。

我假设这是理论性的,因为这是家庭作业,而不是您现在实际需要编写的代码。(肯德里克的回答涵盖了代码方法)

基本思想是从BNF start变量开始,尝试找出如何展开它,一次应用一个规则,看看是否可以得出输入序列

对于类似以下的规则集:

(1) start: expression

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

(5) term: 'a'
(6)     | 'b'
给定表达式
a+b-a
,您可以这样做:

void parseExpression() {
    parseConstant();
    Token token = peek_at_next_token();
    if (token == '+') {
        parseConstant();
        ... tree building code here ...
    }
    else
        throw ParseException("Expected '+', found "+token);
}
                          start
                            | (b)
                        expression
                        /   |   \ (c)
               expression  '-'  term
                /  |  \ (e)       | (d)
       expression '+' term       'a'
           | (f)        | (h)
          term         'b'
           | (g)
          'a'
a<代码>开始
(给定)
b<代码>表达式(1)
c<代码>表达式“-”术语(3)
d<代码>表达式'-''a'(5)
e<代码>表达式“+”术语“-”a'(2)
f<代码>术语'+'术语'-''a'(4)
g<代码>'a''+'术语'-'a'(5)
h<代码>'a'+'b'-'a'(6)

所以这就是你一步一步做的方式。。。现在的诀窍是,您需要跟踪所有规则调用。所以你真正的树看起来像这样:

void parseExpression() {
    parseConstant();
    Token token = peek_at_next_token();
    if (token == '+') {
        parseConstant();
        ... tree building code here ...
    }
    else
        throw ParseException("Expected '+', found "+token);
}
                          start
                            | (b)
                        expression
                        /   |   \ (c)
               expression  '-'  term
                /  |  \ (e)       | (d)
       expression '+' term       'a'
           | (f)        | (h)
          term         'b'
           | (g)
          'a'
一开始有点复杂,但一旦你真正了解了它是如何完成的,就不难理解了

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


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

No-No-No。我必须准确地构建语法树,也就是说,我有BNF notation()中的语法描述,我必须构建此语法树。语法可以固定。+1表示良好的高级技术概述。我不确定你的方法或我的方法是否符合原始海报的目的。我很困惑,如果不使用标识符来指示递归,如何使用递归规则(如
:=|
)构建树节点。你能在你的课本中找到一些例子吗?好的,在编辑之后你想用肯德里克的答案。你在哪一部分有问题?(按照他所说的顺序去做,忽略你所说的你已经知道和不知道的。)我想这个答案对他们不会有帮助。他们可以在书中找到这一点和更多内容,这样看起来他们希望你给他们工作代码。@ChaosPandion:也许没有,但是(a)我还没有读过《龙之书》,(b)海报还没有提供足够的细节,说明他/她到底需要什么(并且已经尝试过了)