使用递归下降分析器既能验证语法又能同时构建解析树,这种做法可行吗?

8

在使用递归下降解析器检查数据是否符合语法的同时,生成解析树是否可能?

如果可以,我应该使用什么方法来构建解析树呢?

谢谢,Boda Cydo。

注意:我是新手。 (已在SO上提出了几个问题,并且我正在变得更加熟练。)

1个回答

7

是的,这是可能的。如何实现取决于您想要的具体实现方式。以下是一个可能适用于您的示例:

首先,定义您的节点:

class ParseTreeNode {
  private final String name;
  private final List<ParseTreeNode> children = /* new */;
  public ParseTreeNode(String name) {
    this.name = name;
  }
  public void addChild(ParseTreeNode child) {
    children.add(child);
}

接下来,您需要将其集成到您的递归下降函数中:
class RDParser {
  ParseTreeNode parse(Input input) {
    ParseTreeNode root = createParseTreeNodeNamed("Root")
    switch (input.nextToken()) {
      case OPT1:
        root.addChild(createParseTreeNodeNamed("Opt1"));
        break;
      case OPT2:
        while (/*someCondition*/) {
          root.addChild(createParseTreeNodeNamed("Opt2-sibling" + /* i */));
        }
      case SUBTREE:
        ParseTreeNode subtree = createParseTreeNodeNamed("Subtree");
        root.addChild(subtree);
        parseSubtree(subtree, input);
        break;
      default:
        error("Input %s was not in the expected first/follow sets", input.nextToken());
    }
  }
  void parseSubtree(ParseTreeNode node, Input input) {
    node.addChild(createParseTreeNodeNamed("subtree-child"));
    /* ... */
  }

  /* and other functions do similarly */
  ParseTreeNode createParseTreeNodeNamed(String name) {
    return new ParseTreeNode(name);
  }
}

当您遍历解析树时,您可能希望发送新的“根”节点,以便可以向其添加子节点。或者,parseSubtree可以创建并返回一个节点,然后将其添加到根节点。
使用上述过程,可以构建解析树或简单的抽象树。由于解析函数返回根节点,该节点将引用任何和所有子节点,因此在解析后,您将完全访问解析树。
无论您使用异构还是同构解析树,都需要一种存储足够信息以使其有用的方法。

1
非常好的回答,Kaleb。它立即让我开始动手写,我想现在我能自己写了!但是你能否请澄清一下"parse tree"和"abstract tree"以及"heterogeneous"和"homogeneous"解析树之间的区别?(我还不知道区别,但我很想知道!) - bodacydo
1
同质 - 由相同类型的节点组成的树。异质 - 由不同类型的节点组成的树。解析树表示输入数据的结构,通常包含不必要的语法。抽象语法树维护基本结构和信息,但消除不必要的结构或语法。我修改了我的帖子以显示树如何变得更深 - 希望这样能澄清。 - Kaleb Pederson
谢谢解释!我已经在实现了。 :) 如果遇到问题,我会问的。我的树将是抽象的、异构的树。 :) - bodacydo
@KalebPederson AST是二叉树吗? - user11747064

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接