2017-01-08 5 views
0

я создал очень простую грамматику, чтобы показать проблему я столкнулся:antlr4 - Parser не работает должным образом при использовании маркеров

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]; 

Грамматика выше генерирует следующий AST с этим примером кода:

void Sieve(int n); // declaration 

AST

Это то, что грамматика выглядит как после изменения type в знак (изменение type к TYPE):

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

После этого, я получаю следующее сообщение об ошибке:

line 1:0 mismatched input 'void' expecting TYPE 

Почему? Как только я использую токен для типа, синтаксический анализатор выдает эту ошибку. Но токен IDENTIFIER работает независимо ...

+0

Как я помню, наибольшее первое правило совпадения выигрывает, а «void» соответствует TYPE и IDENTIFIIER. Итак, определение ТИПА выше IDENTIFIER? – CoronA

+0

Правда, это то, что делает синтаксический анализатор, но 'TYPE' определен до' IDENTIFIER'. 'TYPE' определен в строке 10, а' IDENTIFIER' определен в строке 18. (В основном я просто переименовал 'type' в' TYPE' из моего исходного кода кода) – Johannes

+0

Вы попробовали его ниже IDENTIFIER? – CoronA

ответ

0

Вы изменили свой formParList, чтобы не содержать 'void'. Каждый литерал, используемый в секции парсера, становится неявным Lexer Token с приоритетом над явно определенными токенами.

Если вам нужно аннулирование в этом положении вы можете сделать что-то вроде этого:

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

... 

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

... 

Или присвоить каждый тип своего собственного маркер LeXeR, то правило анализатора для типа будет выглядеть так: type: VOID | BOOL | INT. Это, вероятно, более удобно, если вам нужно позже интерпретировать AST.

+0

Это не работает, как есть, но это дало мне некоторые идеи о том, как исправить это (еще не реализовано). Не могли бы вы добавить ответы, предоставленные вами в комментариях по моему вопросу, чтобы я мог принять это? – Johannes