2

我编写了一个表驱动的 LR(1) 解析器,它工作得很好,但是在将解析转换为语法树/抽象语法树的阶段我有点脱节。这是一个我非常热衷的项目,但我真的只是在这里遇到了死胡同。提前谢谢你的帮助。

编辑:我的解析器也只使用一个二维数组和一个动作对象,告诉它下一步去哪里,或者它是否减少去哪里以及要弹出多少项目。我注意到很多人使用访问者模式。我不确定他们如何知道要制作哪种类型的节点。

这是上下文的下推自动机

 while (lexer.hasNext() || parseStack.size() > 0) {
        Action topOfStack = parseStack.peek();
        token = parseStack.size() > 0 ? lexer.nextToken() : new Token(TokenType.EOF, "EOF");
        topOfStack.setToken(token);

        int row = topOfStack.getTransitionIndex();
        int column = getTerminalIndex(token.getLexeme());

        column = token.getType() == TokenType.IDENTIFIER
                && !terminalsContain(token.getLexeme()) ? 0 : column;

        Action action = actionTable[row][column];

        if (action instanceof Accept) {
            System.out.println("valid parse!!!!!!");
        } else if (action instanceof Reduction) {
            Reduction reduction = (Reduction) action;

            popStack(parseStack, reduction.getNumberOfItemsToPop());
            column = reduction.getTransitionIndex();
            row = parseStack.peek().getTransitionIndex();

            parseStack.push(new Action(gotoTable[row][column]));
            lexer.backupTokenStream();
        } else if (action != null) {
            parseStack.push(actionTable[row][column]);
        } else {
            System.out.println("Parse error");
            System.out.println("On token: " + token.getLexeme());
            break;
        }
4

1 回答 1

3

LR 解析过程中的每个缩减都对应于解析树中的一个内部节点。减少的规则是内部 AST 节点,从堆栈中弹出的项目对应于该内部节点的子节点。为 goto 推送的项目对应于内部节点,而由 shift 操作推送的项目对应于 AST 的叶子(令牌)。

将所有这些放在一起,您可以通过在每次进行缩减时创建一个新的内部节点并将所有内容适当地连接在一起来轻松构建 AST。

于 2015-05-25T20:47:21.747 回答