方括号在ANTLR中未被识别为令牌

时间:2016-03-03 09:04:27

标签: antlr antlr4 context-free-grammar

我目前正在为我的学期项目创建一种编程语言。我们使用ANTLR作为CC的选择,现在我们遇到了一个问题。在为数组声明指定语法时,ANTLR似乎没有将方括号识别为标记。例如,以下代码行:

string[] names = { "Bob", "Hans" }

将产生错误

  

无关输入'string []'期待{'end','num','bool','string','block','item','coords','break','for','while ','直到','切换','如果',IDENTIFIER}

当声明的语法指定为以下

dcl
    : 'num' IDENTIFIER '=' (NUM | IDENTIFIER | accessing)
    | 'bool' IDENTIFIER '=' (BOOL | IDENTIFIER | accessing)
    | 'string' '[' ']' IDENTIFIER '=' ('{' str_arr_items '}' | IDENTIFIER)
    | 'string' IDENTIFIER '=' (STR | IDENTIFIER | accessing)
    | 'block' IDENTIFIER '=' (ITEM_ID | IDENTIFIER | accessing)
    | 'item' IDENTIFIER '=' (ITEM_ID | IDENTIFIER | accessing)
    | 'coords' IDENTIFIER '=' (COORDS | IDENTIFIER | accessing)
    ;

但是,如果我将'[]'与'{}'或'()'交换,似乎工作正常。例如,以下代码行

string() names = { "Bob", "Hans" }

使用以下语法正常工作

 | 'string' '(' ')' IDENTIFIER '=' ('{' str_arr_items '}' | IDENTIFIER)

当它不适用于方括号时,为什么它适用于其他类型的括号和符号?

修改

这是整个语法

  grammar Minecraft;

/* LEXER RULES */
SINGLE_COMMENT      : '//' ~('\r' | '\n')* -> skip ;
MULTILINE_COMMENT   : '/*' .*? '*/' -> skip ;
WS                  : [ \t\n\r]+ -> skip ;
fragment LETTER     : ('a' .. 'z') | ('A' .. 'Z') ;
IDENTIFIER          : LETTER+ ;
fragment NUMBER     : ('0' .. '9') ;
BOOL                : 'true' | 'false' ;
NUM                 : NUMBER+ | NUMBER+ '.' NUMBER+ ;
STR                 : '"' (LETTER | NUMBER)* '"' | '\'' (LETTER | NUMBER)* '\'' ;
COORDS              : NUM ',' NUM ',' NUM ;
ITEM_ID             : NUMBER+ | NUMBER+ ':' NUMBER+ ;
MULDIVMODOP         : '*' | '/' | '%' ;
ADDSUBOP            : '+' | '-' ;
NEGOP               : '!' ;
EQOP                : '==' | '!=' | '<' | '<=' | '>' | '>=' ;
LOGOP               : '&&' | '||' ;

/* PROGRAM GRAMMAR */

prog                : 'begin' 'bot' body 'end' 'bot' ;
body                : glob_var* initiate main function* ;
initiate            : 'initiate' stmt* 'end' 'initiate' ;
main                : 'loop' stmt* 'end' 'loop' ;
type                : 'num' | 'bool' | 'string' | 'block' | 'item' | 'coords' ;

function
    : 'function' IDENTIFIER '(' args ')' stmt* 'end' 'function'
    | 'activity' IDENTIFIER '(' args ')' stmt* 'end' 'activity'
    ;

arg
    : (type | arr_names) IDENTIFIER
    | dcl
    ;

args                : arg ',' args | arg ;
i_args              : IDENTIFIER ',' i_args | /* epsilon */ ;

cond
    : '(' cond ')'
    | left=cond MULDIVMODOP right=cond
    | left=cond ADDSUBOP right=cond
    | NEGOP cond
    | left=cond EQOP right=cond
    | left=cond LOGOP right=cond
    | (NUM | STR | BOOL | ITEM_ID | COORDS | IDENTIFIER)
    ;

stnd_stmt
    : dcl
    | 'for' IDENTIFIER '=' NUM ('to' | 'downto') NUM 'do' stmt* 'end' 'for'
    | ('while' | 'until') cond 'repeat' stmt* 'end' 'repeat'
    | IDENTIFIER '(' i_args ')'
    | 'break'
    ;

stmt                : stnd_stmt | if_stmt ;
else_stmt           : stnd_stmt | ifelse_stmt ;

if_stmt
    : 'if' cond 'then' stmt* 'end' 'if'
    | 'if' cond 'then' stmt* 'else' else_stmt* 'end' 'if'
    ;

ifelse_stmt
    : 'if' cond 'then' else_stmt*
    | 'if' cond 'then' else_stmt* 'else' else_stmt*
    ;

glob_var            : 'global' dcl ;


str_arr_items       : (STR | IDENTIFIER) ',' str_arr_items | (STR | IDENTIFIER) ;

dcl
    : 'num' IDENTIFIER '=' (NUM | IDENTIFIER | accessing)
    | 'bool' IDENTIFIER '=' (BOOL | IDENTIFIER | accessing)
    | 'string' '[' ']' IDENTIFIER '=' ('{' str_arr_items '}' | IDENTIFIER)
    | 'string' IDENTIFIER '=' (STR | IDENTIFIER | accessing)
    | 'block' IDENTIFIER '=' (ITEM_ID | IDENTIFIER | accessing)
    | 'item' IDENTIFIER '=' (ITEM_ID | IDENTIFIER | accessing)
    | 'coords' IDENTIFIER '=' (COORDS | IDENTIFIER | accessing)
    ;

arr_items        : 'num[]' | 'string[]' | 'block[]' | 'item[]' ;

accessing
    : IDENTIFIER '[' ('X' | 'Y' | 'Z') ']'
    | IDENTIFIER '[' NUM+ ']'
    ;

1 个答案:

答案 0 :(得分:1)

好像是

arr_items        : 'num[]' | 'string[]' | 'block[]' | 'item[]' ;

创建了令牌

  

NUM []   串[]   阻止[]和   项[]

这意味着,当解析器解析符号'string []'时,它会自动将其转换为令牌'string []'而不是令牌'string''['和']'。当我从CFG中删除该行时,解析器将按预期运行。感谢Bart Kiers指点我:)