Внутренняя ошибка в грамматических правилах ANTLR4
Я написал свою собственную грамматику:
grammar SimpleCode;
program: 'class Program' '{' field_decl* method_decl* '}' ;
field_decl: type id_int_list ;
id_int: id
| id '[' int_literal ']'
;
id_int_list: id_int
| id_int (',' id_int)*
;
method_decl: (type | 'void') id id_type_list? block ;
id_type_list: (type id)
| (type id) (','(type id))*
;
block: '{' var_decl* statement* '}' ;
var_decl: type id_list ;
id_list: id
| id (',' id)*
;
type: 'int'
| 'boolean'
;
statement: location assign_op expr ';'
| method_call ';'
| 'if' expr block 'else' block
| 'for' id '=' expr ',' expr block
| 'return' expr? ';'
| 'break' ';'
| 'continue' ';'
| block
;
assign_op: '='
| '+='
| '-='
;
method_call: method_name expr_list?
| 'callout' (string_literal (',' callout_arg_list)?)
;
expr_list: expr
| expr (',' expr)*
;
callout_arg_list: callout_arg
| callout_arg (',' callout_arg)*
;
method_name: id ;
location: id
| id '[' expr ']'
;
expr: location
| method_call
| literal
| expr bin_op expr
| '-' expr
| '!' expr
| '(' expr ')'
;
callout_arg: expr
| string_literal
;
bin_op: arith_op
| rel_op
| eq_op
| cond_op
;
arith_op: '+'
| '-'
| '*'
| '\\'
| '%'
;
rel_op: '>'
| '<'
| '>='
| '<='
;
eq_op: '=='
| '!='
;
cond_op: '&&'
| '||'
;
literal: int_literal
| char_literal
| bool_literal
;
id: alpha alpha_num* ;
alpha_num: alpha
| digit
;
alpha: ( 'a'..'z' | 'A'..'Z' ) ;
digit: '0'..'9' ;
hex_digit: digit
| 'a'..'f'
| 'A'..'F'
;
int_literal: decimal_literal
| hex_literal
;
decimal_literal: digit digit* ;
hex_literal: '0x' hex_digit hex_digit* ;
bool_literal: 'true'
| 'false'
;
char_literal: '\'' char '\'' ;
string_literal: '\"' char* '\"' ;
WS: [ \t\r\n]+ ->skip ;
Я получил эту ошибку:
error(20): SimpleCode.g4:8:12: internal error: Rule int_literal undefined
Я не знаю, почему произошла эта ошибка. Int_literal был определен. Пожалуйста, объясните мне, почему произошла эта ошибка. Я не выяснил причину.
Спасибо за помощь.
1 ответ
Я просмотрел ваш код, и главная проблема в том, что вы не отделили правила Parser от правил Lexer. Это делается с помощью Capitals/Case чувствительности. Правила Lexer определены заглавными буквами. как только это было исправлено, ваша грамматика также имела еще 1 ошибку в том, что правило "char" было неопределенным.
вот исправленная версия:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
grammar SimpleCode;
program: 'class Program' '{' field_decl* method_decl* '}' ;
field_decl: type id_int_list ;
id_int: id
| id '[' int_literal ']'
;
id_int_list: id_int
| id_int (',' id_int)*
;
method_decl: (type | 'void') id id_type_list? block ;
id_type_list: (type id)
| (type id) (','(type id))*
;
block: '{' var_decl* statement* '}' ;
var_decl: type id_list ;
id_list: id
| id (',' id)*
;
type: 'int'
| 'boolean'
;
statement: location assign_op expr ';'
| method_call ';'
| 'if' expr block 'else' block
| 'for' id '=' expr ',' expr block
| 'return' expr? ';'
| 'break' ';'
| 'continue' ';'
| block
;
assign_op: '='
| '+='
| '-='
;
method_call: method_name expr_list?
| 'callout' (string_literal (',' callout_arg_list)?)
;
expr_list: expr
| expr (',' expr)*
;
callout_arg_list: callout_arg
| callout_arg (',' callout_arg)*
;
method_name: id ;
location: id
| id '[' expr ']'
;
expr: location
| method_call
| literal
| expr bin_op expr
| '-' expr
| '!' expr
| '(' expr ')'
;
callout_arg: expr
| string_literal
;
bin_op: arith_op
| rel_op
| eq_op
| cond_op
;
arith_op: '+'
| '-'
| '*'
| '\\'
| '%'
;
rel_op: '>'
| '<'
| '>='
| '<='
;
eq_op: '=='
| '!='
;
cond_op: '&&'
| '||'
;
literal: int_literal
| char_literal
| bool_literal
;
id: ALPHA alpha_num* ;
alpha_num: ALPHA
| DIGIT
;
ALPHA: ( 'a'..'z' | 'A'..'Z' ) ;
DIGIT: '0'..'9' ;
HEX_DIGIT: DIGIT
| 'a'..'f'
| 'A'..'F'
;
int_literal: decimal_literal
| hex_literal
;
decimal_literal: DIGIT DIGIT* ;
hex_literal: '0x' HEX_DIGIT HEX_DIGIT* ;
bool_literal: 'true'
| 'false'
;
char_literal: '\'' ALPHA '\'' ;
string_literal: '\"' ALPHA* '\"' ;
WS: [ \t\r\n]+ ->skip ;
Правила лексера используются для создания потоков токенов, а синтаксический анализатор - для определения семантики, что важно для объединенной грамматики.
На этом форуме есть хороший пост с довольно подробным описанием разницы и причин, по которым она нужна. Но кроме отсутствующего правила и отсутствия определения лексера все это было хорошо. Просто запомните INT: DIGIT+; // правила лексера в заглавных буквах.
Удачи с проектом!