2013-05-11 12 views
9

Wie passt man Text in ANTLRv4? Ich meine Text, der zum Zeitpunkt des Grammatikschreibens unbekannt ist?Übereinstimmender beliebiger Text (sowohl Symbole als auch Leerzeichen) mit ANTLR?

Meine Grammatik ist folgendermaßen:

grammar Anytext; 

line : 
    comment; 

comment : '#' anytext; 

anytext: ANY*; 

WS : [ \t\r\n]+; 

ANY : .; 

Und mein Code folgt ist:

String line = "# This_is_a_comment"; 

    ANTLRInputStream input = new ANTLRInputStream(line); 

    AnytextLexer lexer = new AnytextLexer(input); 

    CommonTokenStream tokens = new CommonTokenStream(lexer); 

    AnytextParser parser = new AnytextParser(tokens); 

    ParseTree tree = parser.comment(); 

    System.out.println(tree.toStringTree(parser)); // print LISP-style tree 

Ausgang folgt:

line 1:1 extraneous input ' ' expecting {<EOF>, ANY} 
(comment # (anytext T h i s _ i s _ a _ c o m m e n t)) 

Wenn ich ANY Regel

ANY : [ \t\r\n.]; 
ändern

es hört auf, irgendein Symbol überhaupt zu erkennen.

UPDATE1

Ich habe keine Endlinie Zeichen am Ende.

UPDATE 2

Also, ich verstanden, dass es mit Lexer beliebigen Text übereinstimmen, da Lexer nicht zulassen, können mehrere Klassen unmöglich ist. Wenn ich die Lexer-Regel für ein beliebiges Symbol definiere, werden alle anderen Regeln entweder ausgeblendet oder funktionieren nicht.

Aber die Frage bleibt.

Wie alle Symbole auf Parser Ebene dann passen?

Angenommen, ich tabellenförmigen Daten haben, und ich wan't einige Felder zu bearbeiten und andere ignorieren. Wenn ich anytext Regel hätte, würde ich

infoline : 
    (codepoint WS 'field1' WS field1Value) | 
    (codepoint WS 'field2' WS field2Value) | 
    (codepoint WS anytext); 

schreiben hier bin ich Parsen weitere Zeilen zweite Spalte enthält field1 und field2 Werte und ignorieren Zeilen anders.

, wie dieser Ansatz zu erreichen?

Antwort

1

Verwenden Linie Kommentare folgende Regel:

LINE_COMMENT 
    : '#' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;} 
    ; 

Es passt ‚#‘ und ein beliebiges Symbol, bis es bis zum Ende der Zeile (Unix/Windows-Zeilenumbrüche) bekommt.

Bearbeiten von 280Z28: hier ist genau die gleiche Regel in ANTLR 4 Syntax:

LINE_COMMENT 
    : '#' ~[\r\n]* '\r'? '\n' -> channel(HIDDEN) 
    ; 
+0

Ich bearbeitet Ihren Beitrag, um genau die gleiche Regel in ANTLR 4 Syntax geben. Auf einer separaten Notiz empfehle ich * nicht * einschließlich der ''\ r' '? '\ n''-Zeilenabschluss als Teil der 'LINE_COMMENT'-Regel selbst (es darf Zeichen bis einschließlich, aber nicht am Ende der Zeile enthalten). Es gibt ein paar Gründe, warum ich das empfehle, aber die größte ist die Tatsache, dass 'LINE_COMMENT' in der aktuellen Form nicht mit einem Kommentar in der letzten Zeile einer Datei übereinstimmt, wenn auf sie kein expliziter Zeilenabschluss folgt. –

+0

Ja, das war für ANTLR 3, danke für die Änderungen – hoaz

+0

Warum ist es so komplex? Ist es möglich, einfacher zu schreiben? Warum funktioniert meine Regel nicht? –

7

Es ist wichtig, sich daran zu erinnern, dass ANTLR Ihre vollständige Eingabe in Token brechen, bevor der Parser immer das erste Token sieht (bei zumindest verhält es sich so). Ihre Lexer-Grammatik sieht folgendermaßen aus.

T__0 : '#'; // implicit token created due to the use of '#' in parser rule comment 

WS : [ \t\r\n]+; 

ANY : .; 

Für Ihre Eingabe werden die Tokens die folgenden:

  1. # (Typ T__0)
  2. [Leerzeichen] (Typ WS)
  3. T (Typ ANY)
  4. h (Typ ANY)
  5. i (Typ ANY)
  6. s (Typ ANY)
  7. _ (Typ ANY)
  8. i (Typ ANY)
  9. s (Typ ANY)
  10. _ (Typ ANY)
  11. a (Typ ANY)
  12. _ (Typ ANY)
  13. c (Typ ANY)
  14. o (Typ ANY)
  15. m (Typ ANY)
  16. m (Typ ANY)
  17. e (Typ ANY)
  18. n (Typ ANY)
  19. t (Typ ANY)

Ihre aktuelle Grammatik schlägt fehl, da die WS Token in der comment Regel darf nicht zu analysieren. Es wäre analysieren dieses Eingang (kann aber auch auf Probleme stoßen, wie Sie Ihre Grammatik erweitern), wenn Sie benutzten:

// remember that '#' is its own token 
anytext: (ANY | WS | '#')*; 

Was könnten Sie tun, ist comment ändern eine Lexer Regel zu sein, die sich entlang der # Zeichen verbraucht mit was auch immer folgt (in diesem Fall, bis zum Ende der Zeile):

grammar Anytext; 

line : COMMENT; 

COMMENT : '#' ~[\r\n]*; 

WS : [ \t\r\n]+; 

ANY : .; 
+0

Ich verstehe nicht, warum du '[space] (type WS)' geschrieben hast. Aus meiner Sicht ist es auch "ANY"? Warum nicht? –

+2

@SuzanCioc ANTLR weist einem Token nie mehr als einen Typ zu. Das Leerzeichen entspricht der Regel "WS" und "ANY". Um die Mehrdeutigkeit aufzulösen, wird, da "WS" in der Grammatik vor "ANY" steht, dem Token der Typ "WS" zugewiesen. Die Mehrdeutigkeit wird aufgelöst und der Tokentyp wird zugewiesen, bevor der Parser das Token sieht. Daher wird der Parser niemals ein Leerzeichen-Token mit dem Typ "ANY" sehen. –

+0

Was ist mit Bäumen? Sie sind auch in Lexer verboten? Was, wenn ich 'WS schreibe: [\ t \ r \ n]; ANY: WS | . Wird der Platz sowohl mit "ANY" als auch mit "WS" markiert? –