2017-01-08 4 views
0

Ich habe eine sehr einfache Grammatik geschaffen, das Problem zu zeigen, die ich gestoßen:antlr4 - Parser nicht richtig funktioniert, wenn Token mit

grammar Expr; 
test: funcDecl; 
//----------------------------------------------------------------------- 
funcDecl: funcHead ';'; 
funcHead: type '*'? IDENTIFIER '(' formParList? ')'; 
formParList: ('void' | 
       type '*'? IDENTIFIER ('[' ']')? 
       (',' type '*'? IDENTIFIER ('[' ']')?)* 
      ); 
type:  'void' | 'bool' | 'int'; 

// ---------------------------------------------------------------------- 
Whitespace:  [ \t]+ -> skip; 
LineComment: '//' ~[\r\n]* -> skip; 
NEWLINE :  ('\r' '\n'? | '\n') -> skip; 

IDENTIFIER:  CHARACTER (CHARACTER | DIGIT)*; 

fragment 
CHARACTER: [a-zA-Z_]; 
fragment 
DIGIT:  [0-9]; 

Die Grammatik oben erzeugt folgenden AST mit diesem Beispielcode:

void Sieve(int n); // declaration 

AST

So sieht die Grammatik aus, nachdem die type in ein Token geändert wurde (Änderung type bis TYPE):

... 
funcHead: TYPE '*'? IDENTIFIER '(' formParList? ')'; 
... 
TYPE:  'void' | 'bool' | 'int'; 
... 

Nach so tun, ich die folgende Fehlermeldung erhalten:

line 1:0 mismatched input 'void' expecting TYPE 

Warum ist das so? Sobald ich einen Token für den Typ verwende, löst der Parser diesen Fehler aus. Aber das Token IDENTIFIER funktioniert unabhängig ...

+0

Wie ich mich erinnere die längste erste übereinstimmende Regel gewinnt und 'void' wird von TYPE und IDENTIFIIER verglichen. Also ist die Definition von TYPE oben IDENTIFIER? – CoronA

+0

Richtig, das tut der Parser, aber der 'TYPE' ist vor' IDENTIFIER' definiert. "TYPE" ist in Zeile 10 definiert, während "IDENTIFIER" in Zeile 18 definiert ist. (Im Grunde habe ich "type" in "TYPE" von meinem ursprünglichen Code-Snippet umbenannt) – Johannes

+0

Haben Sie es unter IDENTIFIER versucht? – CoronA

Antwort

0

Haben Sie Ihre formParList geändert, um nicht 'void' zu enthalten. Jedes im Parser-Abschnitt verwendete Literal wird zu einem impliziten Lexer-Token mit Priorität vor den explizit definierten Token.

Wenn Sie in dieser Position aufheben möchten, können Sie etwas tun:

funcHead: type '*'? IDENTIFIER '(' formParList? ')'; 
formParList: (VOID | 
      type '*'? IDENTIFIER ('[' ']')? 
      (',' type '*'? IDENTIFIER ('[' ']')?)* 
     ); 
type:  TYPE | VOID; 

... 

TYPE:  'bool' | 'int'; 
VOID:  'void'; 

... 

Oder Sie jede Art ihre eigene Lexer-Token zuweisen, dann wird der Parser-Regel für Typ würde wie folgt aussehen: type: VOID | BOOL | INT. Dies ist wahrscheinlich bequemer, wenn Sie den AST später interpretieren müssen.

+0

Dies funktioniert nicht wie es ist, aber es gab mir einige Ideen, wie es zu beheben (noch nicht implementiert). Könnten Sie jedoch die Antworten hinzufügen, die Sie in den Kommentaren zu meiner Frage angegeben haben, damit ich das akzeptieren kann? – Johannes

Verwandte Themen