2016-03-28 7 views
4

Ich benutze Antlr für 3 Tage. Ich kann Ausdrücke analysieren, Listener schreiben, Parse-Bäume interpretieren ... es ist ein Traum, der wahr wird.antlr wörtliche String-Matching: Was mache ich falsch?

Aber dann habe ich versucht, eine literale Zeichenfolge 'foo%' und ich versage. Ich kann viele Beispiele finden, die behaupten, dies zu tun. Ich habe sie alle ausprobiert.

Also habe ich ein kleines Projekt erstellt, um eine literale Zeichenfolge zu finden. Ich muss etwas Dummes tun.

grammar Test; 

clause 
    : stringLiteral EOF 
    ; 

fragment ESCAPED_QUOTE : '\\\''; 
stringLiteral : '\'' (ESCAPED_QUOTE | ~('\n'|'\r')) + '\''; 

Einfacher Test:

public class Test { 

    @org.junit.Test 
    public void test() { 
     String input = "'foo%'"; 
     TestLexer lexer = new TestLexer(new ANTLRInputStream(input)); 
     CommonTokenStream tokens = new CommonTokenStream(lexer); 
     TestParser parser = new TestParser(tokens); 
     ParseTree clause = parser.clause(); 
     System.out.println(clause.toStringTree(parser)); 

     ParseTreeWalker walker = new ParseTreeWalker(); 
    } 
} 

Das Ergebnis:

Running com.example.Test 
line 1:1 token recognition error at: 'f' 
line 1:2 token recognition error at: 'o' 
line 1:3 token recognition error at: 'o' 
line 1:4 token recognition error at: '%' 
line 1:6 no viable alternative at input '<EOF>' 
(clause (stringLiteral ' ') <EOF>) 
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.128 sec - in com.example.Test 

Results : 

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 

Der vollständige Maven-ized Build Baum für eine schnelle Überprüfung verfügbar ist here

31 Zeilen Code. .. das meiste davon aus kleinen Beispielen geliehen.

$ mvn clean test 

Verwenden von antlr-4.5.2-1.

+0

Ihr Fehler ist, dass 'stringLiteral' ist eine Parser-Regel, aber es sollte eine Lexer-Regel sein. Setzen Sie seinen Namen mit einem Großbuchstaben beginnen (oder schreiben Sie es nur in Großbuchstaben, es ist einfacher, so eine Lexer-Regel zu erkennen). –

+0

Danke! Das macht das Problem ziemlich klar! –

Antwort

2

fragment Regeln können nur von anderen Lexer-Regeln verwendet werden. Sie müssen also statt einer Parser-Regel eine Lexer-Regel stringLiteral eingeben. Lass es einfach mit einem Großbuchstaben beginnen.

Außerdem ist es besser, Ihre negierte Klasse erweitern ~('\n'|'\r') einen umgekehrten Schrägstrich und Zitat zu schließen, und Sie können einen umgekehrten Schrägstrich in der Lage sein werden, entkam enthalten sein sollen:

clause 
    : StringLiteral EOF 
    ; 

StringLiteral : '\'' (Escape | ~('\'' | '\\' | '\n' | '\r')) + '\''; 

fragment Escape : '\\' ('\'' | '\\'); 
+0

Danke! Ein kleiner Unterschied (Groß-/Kleinschreibung) machte den Unterschied, und jetzt verstehe ich, was lexer von Parser-Regeln unterscheidet! –