Parsing 如何将令牌流转换为解析树

Parsing 如何将令牌流转换为解析树,parsing,token,lexical-analysis,parse-tree,Parsing,Token,Lexical Analysis,Parse Tree,我已经构建了一个lexer,它可以从输入中输出令牌,但我不确定如何构建过程中的下一步——解析树。关于如何实现这一点,有谁有好的资源或例子吗?我真的很推荐,当然还有经典的Dragon编译器书籍 对于JavaScript这样的简单语言来说,手动使用递归下降解析器并不困难,但使用yacc或antlr这样的工具几乎总是更容易 我想回到你问题的基础上来,你真的想学习BNF式语法,为你的目标选择一种语法。如果你有这样的语法,解析树应该有点崩溃,成为语法的“实例”表现形式 另外,不要试图将解析树的创建转化为最

我已经构建了一个lexer,它可以从输入中输出令牌,但我不确定如何构建过程中的下一步——解析树。关于如何实现这一点,有谁有好的资源或例子吗?

我真的很推荐,当然还有经典的Dragon编译器书籍

对于JavaScript这样的简单语言来说,手动使用递归下降解析器并不困难,但使用yacc或antlr这样的工具几乎总是更容易

我想回到你问题的基础上来,你真的想学习BNF式语法,为你的目标选择一种语法。如果你有这样的语法,解析树应该有点崩溃,成为语法的“实例”表现形式


另外,不要试图将解析树的创建转化为最终的解决方案(比如生成代码等等)。它可能看起来很有能力而且更有效;但总有一天,你会真的希望自己有一棵“原样”的解析树

我认为一种常见的方法是使用a。例如,如果您读取一个操作数,您将进入下一个需要运算符的状态,并且通常使用该运算符作为操作数的根节点,依此类推。

您应该研究适用于您的平台的解析器生成器工具。解析器生成器允许您为您的语言指定上下文无关的语法。语言由一系列规则组成,这些规则将一系列符号“还原”为一个新符号。通常还可以为不同的规则指定优先级和关联性,以消除语言中的歧义。例如,一种非常简单的计算器语言可能如下所示:

%left PLUS, MINUS           # low precedence, evaluated left-to-right
%left TIMES, DIV            # high precedence, left-to-right

expr ::= INT
| expr PLUS expr
| expr MINUS expr
| expr TIMES expr
| expr DIV expr
| LEFT_PAREN expr RIGHT_PAREN
通常,您可以将一位代码与每个规则关联,以从该规则中的其他符号构造一个新值(在本例中为表达式)。解析器生成器将接受语法,并用您的语言生成代码,将令牌流转换为解析树


大多数解析器生成器都是特定于语言的。ANTLR是众所周知的,支持C、C++、Objic C、java和Python。我听说它很难使用。我使用了bison for C/C++,CUP for Java,ocamlyacc for OCaml,它们都非常好。如果您已经在使用lexer生成器,您应该寻找一个与之特别兼容的解析器生成器。

如Marcos Marin所述,一个使用您在BNF中的语言规则来解析您的令牌列表的状态机,如果您想自己做的话,它将完成这项工作。只是,正如Paul Hollingsworth在上面的评论中所说,更简单的方法是使用具有简单FiFo内存堆栈的。 每一类令牌在语法中都有下一个预期的令牌,它也在状态机中表示。堆栈用于“记住”前一个令牌类是什么,以减少所需的状态(可以在没有堆栈的情况下完成,但语法树中拆分的每个类和子类都需要一个新状态)。 接受状态将是(在自然语言和大多数编程语言中也是)开始状态,在特定情况下可能是其他一些状态


如果你想使用一个工具(更快,更不广泛),我建议你。祝你好运

你应该知道,很多这是为了学习经验,而不是为了完成一项特定的任务,所以使用工具对我来说似乎超出了重点。问题是,从语法创建解析树是一件非常容易理解的理论事情。专业人员使用这些工具。如果你对学习感兴趣,参加cs理论课程并使用该工具。经验是使用一个工具并调整它以获得不完美的语言/语法。不正确-你说的是编写一个lexer。要编写解析器,您需要某种“堆栈”,根据定义,有限状态机没有这种堆栈;他似乎在描述魔兽世界,抱歉,4年后才看到这条评论!有限状态机的问题在于它无法识别“平衡圆括号”之类的东西——您需要无限(即非有限)数量的“状态”来识别这些类型的表达式。