Я создал эту грамматику образца, используя 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
;
Для пустой строки я получаю следующее дерево:
Это дерево указывает, что синтаксический анализатор построил дерево синтаксического анализа, содержащее "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.