2016-06-02 26 views
1

Angesichts der folgenden ANTLR Grammatik:ANTLR: unerwartetes Zeichen

tokens 
{ 
    SET; 
    UNKNOWN; 
    LIST; 
} 


statement : SET_KEYWORD list = value_list -> ^(SET $list) 
      | UNKNOWN_KEYWORD -> ^(UNKNOWN); 

value_list : element += value (COMMA_KEYWORD element += value)* -> ^(LIST $element+); 

value : STRING_KEYWORD; 


SET_KEYWORD : 'SET'; 

UNKNOWN_KEYWORD : .; 

fragment STRING_KEYWORD : '"' ('a'..'z' | 'A'..'Z')* '"'; 

Wenn man analysiert den folgenden Text (dh ohne die Anführungszeichen zu schließen):

SET "example 

ANTLR gibt den folgenden Fehler:

TEST(1) : lexer error 1 : 
     Unexpected character at offset 12, (end of input). 
     This indicates a poorly specified lexer RULE 
     or unterminated input element such as: "STRING["] 
     The lexer was matching from line 1, offset 3, which 
     looks like this: 
       "example 

Man könnte denken, dass das UNKNOWN_KEYWORD diese Art von Problemen aufholen wird. Wie kann man die Grammatik korrigieren, so dass die oben genannte Fehlermeldung nicht mehr angezeigt wird?

Antwort

0

Haupt Fehler

Der Haupt Fehler Ihrer Grammatik beschreibt UNKNOWN_KEYWORD und STRING_KEYWORD als Lexer Regeln. Ihr Parser entspricht nicht SET "example Eingang, da die Lexer hat die following:

Lexer looks for the first longest matching rule. In other words, if multiple rules match the input, the longest one is selected.

Wenn die Lexer die " trifft, die als UNKNOWN_KEYWORD und als Anfang STRING_KEYWORD angepasst werden konnte, entscheidet er Eingaben STRING_KEYWORD anzupassen, weil diese Regel länger als UNKNOWN_KEYWORD.

Also, es wird besser sein, diese Regeln als Parser-Regeln neu zu schreiben. Lass den Lexer mit einfacheren Token übereinstimmen.

Andere Bugs

Neben diesen gibt es andere Fehler in der Grammatik:

  • Fehlende options Block für die Ausgabe Typ beschreiben in Regeln AST Operatoren.
  • Fehlende + nach UNKNOWN_KEYWORD in der statement Regel. Ohne + sagen Sie, dass die Aussage ein SET_KEYWORD value_list oder irgendein einzelnes Zeichen ist.
  • Fehlende Regeln für Zeilenumbrüche und Leerzeichen.
  • Fehlende EOF am Ende der statement Regel. Die Eingabe wie SET "abc"bla-bla-bla wird geparst als mit AST (SET (LIST "abc")), d. H. bla-bla-bla wird ohne EOF ignoriert.
  • Fehlende Beschreibung der COMMA_KEYWORD Regel.
  • Beschreibung STRING_KEYWORD als eine Fragment-Regel. Wenn die Regel ein Fragment ist, erhält der Parser niemals das Token, das durch diese Regel beschrieben wird.

AST Ausgabe

Wenn Sie UNKNOWN_KEYWORD und STRING_KEYWORD als Parser Regeln neu zu schreiben und versuchen Sie Ihren Parser für SET "example" Eingang Sie den folgenden AST erhalten:

(SET (LIST " e x a m p l e ")) 

D.h. "example" ist kein gesamter AST-Knoten. Für jedes Zeichen gibt es separate Knoten, da ein Knoten in AST im allgemeinen Fall für ein Token konstruiert.Aber es kann über Aufruf Konstruktor für CommonTree Klasse durch die Schaffung von imaginären Token und die Schaffung von Knoten aufgelöst werden (siehe ANTLR 3 Runtime 3.5.2 API):

value : st = string_keyword -> {new CommonTree(new CommonToken(KEYWORD, $st.text))}; 

Resultierende Grammatik

Also, Ihre Grammatik kann wie folgt aussehen:

options { 
    output=AST; 
    ASTLabelType=CommonTree; 
} 

tokens { 
    SET; 
    UNKNOWN; 
    LIST; 
    KEYWORD; 
} 

statement : ((SET_KEYWORD value_list)=> SET_KEYWORD list= value_list NEWLINE -> ^(SET $list) 
      | unknown_keyword+ NEWLINE -> ^(UNKNOWN) 
      ) 
      EOF; 

value_list : element += value (COMMA_KEYWORD element += value)* -> ^(LIST $element+); 

value : st= string_keyword -> {new CommonTree(new CommonToken(KEYWORD,$st.text))}; 

NEWLINE:'\r'? '\n' ; 
WS: (' '|'\t'|'\n'|'\r')+ {skip();}; 
COMMA_KEYWORD: ','; 
SET_KEYWORD : 'SET'; 
QUOTES:'"'; 
LETTER:('a'..'z' | 'A'..'Z'); 
ANY:.; 
string_keyword : QUOTES LETTER* QUOTES ; 
unknown_keyword : SET_KEYWORD|QUOTES|LETTER|COMMA_KEYWORD|ANY;