Ожидается несовпадение ввода ANTLR4

В настоящее время я только что определил простые правила в ANTLR4:

// Recognizer Rules

program  : (class_dcl)+ EOF;
class_dcl: 'class' ID ('extends' ID)? '{' class_body '}';
class_body: (const_dcl|var_dcl|method_dcl)*;
const_dcl: ('static')? 'final' PRIMITIVE_TYPE ID '=' expr ';';
var_dcl: ('static')? id_list ':' type ';';
method_dcl: PRIMITIVE_TYPE ('static')? ID '(' para_list ')' block_stm;
para_list: (para_dcl (';' para_dcl)*)?;
para_dcl: id_list ':' PRIMITIVE_TYPE;
block_stm: '{' '}';
expr: <assoc=right> expr '=' expr | expr1;
expr1: term ('<' | '>' | '<=' | '>=' | '==' | '!=') term | term;
term: ('+'|'-') term | term ('*'|'/') term | term ('+'|'-') term | fact;
fact: INTLIT | FLOATLIT | BOOLLIT | ID | '(' expr ')';
type: PRIMITIVE_TYPE ('[' INTLIT ']')?;
id_list: ID (',' ID)*;

// Lexer Rules

KEYWORD: PRIMITIVE_TYPE | BOOLLIT | 'class' | 'extends' | 'if' | 'then' | 'else'
    | 'null' | 'break' | 'continue' | 'while' | 'return' | 'self' | 'final'
    | 'static' | 'new' | 'do';
SEPARATOR: '[' | ']' | '{' | '}' | '(' | ')' | ';' | ':' | '.' | ',';
OPERATOR: '^' | 'new' | '=' | UNA_OPERATOR | BIN_OPERATOR;
UNA_OPERATOR: '!';
BIN_OPERATOR: '+' | '-' | '*' | '\\' | '/' | '%' | '>' | '>=' | '<' | '<='
    | '==' | '<>' | '&&' | '||' | ':=';
PRIMITIVE_TYPE: 'integer' | 'float' | 'bool' | 'string' | 'void';
BOOLLIT: 'true' | 'false';
FLOATLIT: [0-9]+ ((('.'[0-9]* (('E'|'e')('+'|'-')?[0-9]+)? ))|(('E'|'e')('+'|'-')? [0-9]+));
INTLIT: [0-9]+;
STRINGLIT: '"' ('\\'[bfrnt\\"]|~[\r\t\n\\"])* '"';
ILLEGAL_ESC: '"' (('\\'[bfrnt\\"]|~[\n\\"]))* ('\\'(~[bfrnt\\"]))
    {if (true) throw new bkool.parser.IllegalEscape(getText());};
UNCLOSED_STRING: '"'('\\'[bfrnt\\"]|~[\r\t\n\\"])*
    {if (true) throw new bkool.parser.UncloseString(getText());};
COMMENT: (BLOCK_COMMENT|LINE_COMMENT) -> skip;
BLOCK_COMMENT: '(''*'(('*')?(~')'))*'*'')';
LINE_COMMENT: '#' (~[\n])* ('\n'|EOF);
ID: [a-zA-z_]+ [a-zA-z_0-9]* ;

WS: [ \t\r\n]+ -> skip ;
ERROR_TOKEN: . {if (true) throw new bkool.parser.ErrorToken(getText());};

Я открыл дерево синтаксического анализа и попытался проверить:

class abc
{
 final integer x=1;
}

Он вернул ошибки:

BKOOL::program:3:8: mismatched input 'integer' expecting PRIMITIVE_TYPE
BKOOL::program:3:17: mismatched input '=' expecting {':', ','}

Я до сих пор не понял почему. Не могли бы вы помочь мне, почему он не распознал правила и токены, как я ожидал?


person necroface    schedule 23.09.2015    source источник


Ответы (1)


Правила Lexer являются эксклюзивными. Побеждает самый длинный, и решающим фактором является порядок грамматики.

В твоем случае; integer это KEYWORD вместо PRIMITIVE_TYPE.

Что вы должны сделать здесь:

  • Создайте один отдельный токен для каждого ключевого слова вместо универсального правила KEYWORD.
  • Превратите PRIMITIVE_TYPE в правило парсера
  • То же самое для операторов

Прямо сейчас ваш пример:

class abc
{
 final integer x=1;
}

Преобразуется в такие лексемы, как:
class ID { final KEYWORD ID = INTLIT ; }

Это благодаря неявной типизации токенов, поскольку вы использовали такие определения, как 'class', в правилах парсера. Они преобразуются в анонимные токены, такие как T_001 : 'class';, которые получают наивысший приоритет.

Если бы это было не так, вы бы получили:
KEYWORD ID SEPARATOR KEYWORD KEYWORD ID OPERATOR INTLIT ; SEPARATOR

И это... не совсем легко разобрать ;-)
Вот почему я говорю вам правильно разбивать свои токены.

person Lucas Trzesniewski    schedule 23.09.2015
comment
Чтобы избежать новой ветки, я редактирую свой вопрос на другой более сложный и запутанный вопрос. - person necroface; 23.09.2015
comment
Не делайте этого, это противоречит стандартам SO. Пожалуйста, верните свой вопрос к предыдущей версии и опубликуйте этот как новый вопрос. - person Lucas Trzesniewski; 24.09.2015
comment
Вчера вечером я открыл новую тему. К счастью, через несколько часов после этого мне удалось успешно отладить себя. Спасибо - person necroface; 24.09.2015
comment
Тогда все хорошо :) Откатил ваш вопрос на предыдущую ревизию. - person Lucas Trzesniewski; 24.09.2015