【发布时间】:2016-02-22 04:51:43
【问题描述】:
我已经构建了一个基于语法的递归体面解析器。目前我的解析器只告诉语法是否接受输入的令牌序列。如果语法接受输入和抽象语法树,我想返回。我不知道该怎么做。
到目前为止,我所拥有的是一个对应于语法中每个生产规则的函数。我已经改变了语法,因此终端始终是每个生产规则的第一个元素。下面是我尝试为其构建语法树的语法子集。
program -> VAR = exp
exp -> NUM term
exp -> LEFTPAR exp RIGHTPAR
term -> MUL NUM term
term -> DIV NUM term
term -> . (empty)
规则的函数示例如下:
public Pair<bool, Token> exp(Token tok)
{
if (tok.type == NUM)
{
return term(tok.next);
}
if (tok.type = LEFTPAR)
{
Pair<bool, Token> temp = exp(tok.next);
if (temp.left && temp.right.type == RIGHTPAR)
return new Pair<bool, Token>(true,temp.right.next);
return new Pair<bool, Token>(false,null);
}
}
将这样的函数转换为语法树构建器的策略是什么?我试图将一个树节点作为输入传递给所有函数,但是当存在具有多个非终端的规则时,它会变得更加混乱。似乎构建解析树会更容易,然后将其转换为 AST 后缀。任何帮助表示赞赏!
【问题讨论】:
-
查看我关于如何构建递归下降解析器的回答,其中讨论了如何构建 AST。 stackoverflow.com/questions/2245962/…(您不必让每个规则都以终端开头;迭代可以处理许多“左递归”情况。)
-
谢谢!这很有帮助!当您在我的示例中具有像
term这样的可空规则或多个(如在我的完整语法中)时,您会怎么做?似乎唯一的解决方案是有一堆 if 语句来检查哪些是空的,然后不返回它们。 -
由于您可以控制每个规则返回的节点,因此您可以将任何您喜欢的内容向上传递。是的,您可能需要复杂的逻辑来决定在每个规则中实际构建什么。这就是拥有与语法(例如 CST)的形状不完全相同的 AST 的代价。对于小型语法,您可能愿意进行额外的编码。对于大型或快速发展的语法,构建与语法相同形状的树是无脑且容易的。你没有得到一个“真正的”AST,但如果你按照我的建议去消除一些节点,你得到的就足够接近了。
-
我发现递归下降解析适合通过面向过程的语言实现,但并不完全适合面向对象的编程。
标签: c# parsing abstract-syntax-tree recursive-descent