2017-08-29 71 views
11

Utworzyłem tę przykładową gramatykę przy użyciu ANTLR4 plugin w IntelliJ i kiedy używam jej łańcucha narzędzi do generowania wizualnej reprezentacji dla niektórych nieprawidłowych treści (w tym przypadku pustego ciągu), ta reprezentacja wydaje się różnić od mojej można uzyskać podczas wykonywania rzeczywistego przejścia drzewa parse za pomocą przykładowej implementacji gościa/detektora dla tego samego wejścia.Dlaczego istnieje taka różnica między wizualizacją drzewa analiz i moją wizytą użytkownika/słuchacza?

Jest to gramatyka:

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 
     ; 

Na pustym ciągiem znaków, pojawia się następujący drzewa:

parse tree

To drzewo wskazuje, że parser zbudowali drzewo składniowy, który zawiera „DottedExpression "i" primary: This "(zakładając, że używa do tego własnej implementacji visitor/listener). Jednak gdy próbuję to samo za pomocą następującego kodu:

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()]); 
     } 
    } 
} 

pojawia się następujący komunikat:

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

Tak więc, nie tylko głębie drzewo nie pasują, wyjście nawet wskazuje inna reguła została dopasowana druga ("Ekspresja podstawowa" zamiast "Przekreślona ekspresja").

Dlaczego istnieje taka różnica między tym, co pokazałem, a tym, co próbuję pokazać? Jak utworzyć tę samą reprezentację drzewa, jak pokazuje wtyczka?

Korzystanie z ANTLR w wersji 4.7. Wersja wtyczki to 1.8.4.

+0

Szybko przyjrzano się źródłu ANTLR. Domyślam się, że drzewo analizowania graficznego jest tworzone przy użyciu analizatora składni w innym trybie przewidywania niż w przypadku samodzielnego uruchamiania analizatora składni. – Gene

+1

Nawiasem mówiąc, wygląda na to, że kod generuje drzewo analizy, które jest renderowane graficznie. Być może możesz znaleźć wskazówki dotyczące konfiguracji parsera: https://github.com/antlr/antlr4/blob/46b3aa98cc8d8b6908c2cabb64a9587b6b973e6c/tool/src/org/antlr/v4/gui/TestRig.java#L170 – Gene

Odpowiedz

3

Ten problem został rozwiązany w wersji 1.8.2 wtyczki. Jeśli masz wersję 1.8.2 lub nowszą, prawdopodobnie odkryłeś inną nieznaną jej część.

Jednak (w zależności od problemu, który mam na myśli), drzewa różnią się tylko wtedy, gdy przetwarzanie powoduje błąd. Więc jeśli nie jesteś zainteresowany wykorzystaniem informacji o błędach, powinieneś być w porządku.

+0

I używam nowszej wersji (1.8.4). Czy masz link do problemu, o którym wspomniałeś? Muszę wiedzieć, jak działa parser z błędnymi danymi wejściowymi. – predi

+0

Nie mam linku, ale jest gdzieś na stronie github https://github.com/antlr/intellij-plugin-v4 – MaanooAk

+0

Prawdopodobnie [to] (https://github.com/antlr/intellij-plugin -v4/issues/180). – predi