java - 为什么解析树可视化和我的访问者/听众遍历之间存在这样的差异?

标签 java intellij-idea antlr4

我使用 ANTLR4 plugin 创建了这个示例语法在 IntelliJ 中,当我使用它的工具链为一些无效内容(在本例中为空字符串)生成可视化表示时,这种表示似乎与我在使用示例访问者进行实际解析树遍历时能够得到的不同/相同输入的监听器实现。

这是语法:

grammar TestParser;

THIS            : 'this';

Identifier
    : [a-zA-Z0-9]+
    ;

WS  :  [ \t\r\n\u000C]+ -> skip;

parseExpression:
    expression EOF
;

expression
    : expression bop='.' (Identifier | THIS ) #DottedExpression
    | primary                                 #PrimaryExpression
    ;

primary
        : THIS                                #This
        | Identifier                          #PrimaryIdentifier
        ;

对于空字符串,我得到以下树:

parse tree

这棵树表示解析器构建了一个包含“DottedExpression”和“primary:This”的解析树(假设它使用自己的访问者/监听器实现来执行此操作)。然而,当我尝试使用以下代码进行相同操作时:

package org.example.so;

import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTreeWalker;

public class TestParser {
    public static void main(String[] args) {
        String input = "";
        TestParserLexer lexer = new TestParserLexer(CharStreams.fromString(input));
        CommonTokenStream tokenStream = new CommonTokenStream(lexer);
        TestParserParser parser = new TestParserParser(tokenStream);

        TestParserParser.ParseExpressionContext parseExpressionContext = parser.parseExpression();

        MyVisitor visitor = new MyVisitor();
        visitor.visit(parseExpressionContext);

        System.out.println("----------------");

        ParseTreeWalker walker = new ParseTreeWalker();
        walker.walk(new MyListener(), parseExpressionContext);

        System.out.println("----------------");
    }

    private static class MyVisitor extends TestParserBaseVisitor {

        @Override
        public Object visitParseExpression(TestParserParser.ParseExpressionContext ctx) {
            System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()]);
            return super.visitParseExpression(ctx);
        }

        @Override
        public Object visitDottedExpression(TestParserParser.DottedExpressionContext ctx) {
            System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()] + ":DottedExpression");
            return super.visitDottedExpression(ctx);
        }

        @Override
        public Object visitPrimaryExpression(TestParserParser.PrimaryExpressionContext ctx) {
            System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()] + ":PrimaryExpression");
            return super.visitPrimaryExpression(ctx);
        }

        @Override
        public Object visitThis(TestParserParser.ThisContext ctx) {
            System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()]);
            return super.visitThis(ctx);
        }

        @Override
        public Object visitPrimaryIdentifier(TestParserParser.PrimaryIdentifierContext ctx) {
            System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()]);
            return super.visitPrimaryIdentifier(ctx);
        }
    }

    private static  class MyListener extends TestParserBaseListener {

        @Override
        public void enterParseExpression(TestParserParser.ParseExpressionContext ctx) {
            System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()]);
        }

        @Override
        public void enterDottedExpression(TestParserParser.DottedExpressionContext ctx) {
            System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()] + ":DottedExpression");
        }

        @Override
        public void enterPrimaryExpression(TestParserParser.PrimaryExpressionContext ctx) {
            System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()] + ":PrimaryExpression");
        }

        @Override
        public void enterThis(TestParserParser.ThisContext ctx) {
            System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()]);
        }

        @Override
        public void enterPrimaryIdentifier(TestParserParser.PrimaryIdentifierContext ctx) {
            System.out.println(TestParserParser.ruleNames[ctx.getRuleIndex()]);
        }
    }
}

我得到以下输出:

line 1:0 mismatched input '<EOF>' expecting {'this', Identifier}
parseExpression
expression:PrimaryExpression
----------------
parseExpression
expression:PrimaryExpression
----------------

因此,不仅树深度不匹配,输出甚至表明第二个匹配了不同的规则(“PrimaryExpression”而不是“DottedExpression”)。

为什么我展示的内容和我试图展示的内容之间存在如此大的差异?如何创建与插件所示相同的树表示?

使用 ANTLR 4.7 版。插件版本为1.8.4。

最佳答案

此问题已在插件的 1.8.2 版本中修复。如果您使用的是 1.8.2 或更高版本,那么您可能发现了该问题的另一个未知子案例。

但是(基于我所指的问题),只有当解析导致错误时树才会不同。因此,如果您对使用错误信息不感兴趣,应该没问题。

关于java - 为什么解析树可视化和我的访问者/听众遍历之间存在这样的差异?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45945094/

相关文章:

java - 编写一个返回字符串偶数索引的方法

intellij-idea - 运行/调试配置中的共享复选框

java - 如何在 Intellij 中从 CVS 中 check out 空目录?

java - Intellij 中的正则表达式编译

java - Antlr异常: there is no serialized ATN

java - 将多个整数值混淆为固定长度值并将其读回

java - ejb 2.x Ear 还需要什么?

eclipse - Eclipse 下的 ANTLR4 在不正确的包中生成源

java - 使用 bash,如何从目录中的所有文件中创建类路径?

antlr - 将 ANTLR v2 语法迁移到 ANTLR v4