2016-04-28 12 views
0

folgende ANTLR v3 Grammatik Gegeben:Wrong AST Auswahl

tokens 
{ 
    OPTION; 
    UNKNOWN; 
} 

statement : my_statement 
      | UNKNOWN_KEYWORD -> ^(UNKNOWN) 
      ; 

my_statement : FIRST SECOND type = THIRD? -> ^(OPTION $type?); 


FIRST : 'my'; 

SECOND : 'keyword'; 

THIRD: 'best'; 

UNKNOWN_KEYWORD : .; 

Warum das ist, wenn die Zeichenfolge „mein Stichwort this_is_garbage“ analysiert wird, wird abgeholt von my_statement während es picked- hätte sein sollen up von UNKNOWN_KEYWORD (dh der AST, die zurückgegeben wird, ist ^(OPTION $ type?) während es ^(UNKNOWN) hätte sein sollen)?

FIRST    'my' 
SECOND    'keyword' 
UNKNOWN_KEYWORD 't' 
UNKNOWN_KEYWORD 'h' 
... 
UNKNOWN_KEYWORD 'e' 

das heißt, ein FIRST Token ein Token SECOND und dann 15 UNKNOWN_KEYWORD Tokens:

+0

"THIRD" ist in Ihrer Parser-Regel optional, daher passte die Regel "mein Schlüsselwort" gut und ging nicht einmal zu "this_is_garbage". –

+0

Ja, es passt nicht zu my_keyword, aber es liefert nicht den AST^(UNKNOWN), was man erwarten würde. Wie kann die Grammatik korrigiert werden, so dass sie diesen AST zurückgibt? – user5793565

+1

Das Verhalten, das Sie sehen, ist genau das, was ich von dieser Grammatik erwarten würde :) Nun, vorausgesetzt, dass 'UNKNOWN_KEYWORD' irgendwo definiert ist (' UNKNOWN' ist ein einzelnes Zeichen). 'my_statement' stimmt überein, so dass der zweite Zweig von' statement' nicht einmal ausprobiert wird. –

Antwort

2

Der Eingang my keyword this_is_garbage wird wie folgt (unter der Annahme Räumen versteckt sind) werden in Token aufgeteilt.

Wenn Sie nun versuchen, statement übereinstimmen, wird die Regel my_statement verbrauchen würde gerne die FIRST und SECOND Token, die 15 UNKNOWN_KEYWORD Token in dem Token-Strom zu verlassen.

Wenn Sie jedoch immer wieder Ihre statement Regel wie diese passen würde:

parse 
: statement+ EOF 
; 

dann würden Sie mit dem folgenden Parsing-Baum am Ende:

enter image description here

oder dieses AST:

enter image description here

Und wenn Sie alle UNKNOWN_KEYWORD Token in 1 Alternative zur Gruppe wollen, müssen Sie tun müssen:

statement : my_statement 
      | UNKNOWN_KEYWORD+ -> ^(UNKNOWN) 
      ; 

Beachten Sie, dass Sie kann nicht Gruppe UNKNOWN_KEYWORD in Ihrem Lexer:

UNKNOWN_KEYWORD : .+ ; 

weil das würde dazu führen, dass der Lexer den gesamten Zeichenstrom in ein einzelnes UNKNOWN_KEYWORD Token verschlingt.

+0

Sie sollten auch hier hinzufügen, dass UNKNOWN_KEYWORD eine *. Schleife sein sollte, nicht nur ein einzelnes Zeichen, um dem beabsichtigten Verhalten zu entsprechen. –

+0

Ja, aber du meinst wahrscheinlich '+'. –

+0

Richtig, ein Plus ist richtig. Aber Ihr Zusatz über diese Schleife ist nicht :-) UNKNOWN_KEYWORD würde nur alles essen, wenn vorher keine andere Regel übereinstimmte. Es ist vollkommen in Ordnung, am Ende einer Grammatik eine Catch-All-Regel zu haben. –