在一个采访问题中我问过这个问题:
编写一个代码来生成解析树,就像编译器在内部为任何给定的表达式做的那样。例如:
a+(b+c*(e/f)+d)*g
答案 0 :(得分:3)
简单的方法是将表达式转换为后缀表示法(abcef / * ++)&然后参考这个问题的答案(http://stackoverflow.com/questions/423898/postfix-notation-to-expression-tree)将后缀表达式转换为树。
这是面试官所期望的:)
答案 1 :(得分:3)
首先定义语言。没有人可以将解析器或编译器实现到没有很好定义的语言。举个例子:'a +(b + c *(e / f)+ d)* g',它应触发以下问题:
一旦你掌握了语言语法的良好定义,就要开始实现一个标记器。标记化器获取字符流并生成标记列表。在上面的示例中,每个字符都是一个标记,但在var * 12(var power 12)中有3个标记:'var',' *'和'12'。如果允许使用正则表达式,则可以使用正则表达式执行此部分解析。
接下来,有一个按类型标识每个标记的函数:它是一个运算符,它是一个变量,一个数字文字,字符串文字等。在一个名为NextToken的方法中打包所有,它返回一个标记及其类型。 / p>
最后,开始解析。在上面的示例中,解析树的根将是一个带有“+”运算符的节点(优先于'')。左子项是变量标记'a',右子项是具有根元素''标记的树。递归地工作。
答案 2 :(得分:1)
每当您打算编写解析器时,要问的主要问题是您是要手动执行还是使用解析器生成器框架。
在这种情况下,我会说自己写一遍是一个很好的练习。
从树本身的良好表示开始。这将是您算法的输出。例如,这可以是对象的集合,其中一个对象类可以表示示例中的a
,b
和c
之类的“标签”。其他人可能代表数字。然后,您可以定义运算符的表示,例如+
是一个二元运算符,它有两个子对象,表示左右子表达式。
下一步是实际的解析器,我建议一个经典的递归式解析器。描述这一点并提供标准伪代码实现的一个文本是Theodore Norvell
的文本答案 3 :(得分:0)
我从简单的语法开始,类似于ANTLR和JavaCC使用的语法。