Algorithm 语法树
我在大学里有一个实验室。但我不明白我怎么能做到。 我有某种语言的语法(例如,算术表达式语法)。我必须建立这个语法树(我不知道怎么做)。然后我必须确定,输入的句子是否是这种语言的句子?我怎么做? 顺便说一句,我读了《龙之书》的几章,但还没有找到我需要的东西。 我不能用lex/flex和yacc/bisonAlgorithm 语法树,algorithm,parsing,tree,grammar,Algorithm,Parsing,Tree,Grammar,我在大学里有一个实验室。但我不明白我怎么能做到。 我有某种语言的语法(例如,算术表达式语法)。我必须建立这个语法树(我不知道怎么做)。然后我必须确定,输入的句子是否是这种语言的句子?我怎么做? 顺便说一句,我读了《龙之书》的几章,但还没有找到我需要的东西。 我不能用lex/flex和yacc/bison 编辑对不起!我应该更专心一点。真的,我有一个语法,我必须用这个语法和输入句子建立树(我知道怎么做),如果可能的话(在另一种情况下,我必须显示有关它的信息)。有什么简单的算法可以理解吗?我可以使
编辑对不起!我应该更专心一点。真的,我有一个语法,我必须用这个语法和输入句子建立树(我知道怎么做),如果可能的话(在另一种情况下,我必须显示有关它的信息)。有什么简单的算法可以理解吗?我可以使用任何简单语言的语法,比如算术表达式。我已经很久没有这样做了,所以我将给你一个简短的理论答案。我相信其他人会有更深入的解释 因为你还没有说你做了什么(你应该在将来的问题中这样做),所以第一步是标记输入 一旦您拥有了令牌,您就可以构建一个状态机来遍历令牌并将其推送到所需的树结构中。这应该包含在你的书(我还没有读过),但你可能要开始建立一个模型在纸上(或电子),并考虑有效的输入从每一个步骤。等式语句的有效左手值是多少?如果你在树上有令牌x,你可以从这里去哪里 如果您无法从当前状态确定下一步的位置,那么您可能需要在状态机中实现前瞻(这是否需要取决于语言的复杂性)
再说一次,我已经10多年没有这样做了,所以我的记忆很模糊。希望我已经为您提供了足够的框架来完善您的答案,或者给其他对此问题有更深入了解的人,以批评我的错误或过时(从而得出您作为一个群体正在寻找的答案)。我想回答这个问题,但实际上没有足够的材料可供使用-我只剩下以下问题:
- 因为这是一个大学实验室,没有附带的学习材料或课程吗?还有,你还有多少时间
- 到目前为止你试过什么
- 您可以将给定的语法硬编码到您的程序中,或者您的程序需要能够从文件中读取任何语法并从中构建解析树吗
- 语法有多复杂;具体来说:它们是递归的吗
- 语法标记是单字符还是多字符
表达式:常量“+”常量
关联的分析方法如下所示:
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)海报还没有提供足够的细节,说明他/她到底需要什么(并且已经尝试过了)