方括号在 ANTLR 中不被识别为标记

Square brackets not recognized as tokens in ANTLR

我目前正在为我的学期项目创建一种编程语言。我们正在使用ANTLR作为CC的选择,现在我们已经运行陷入了困境。在指定数组声明的语法时,ANTLR 似乎无法将方括号识别为标记。例如下面一行代码:

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

会产生错误

extraneous input 'string[]' expecting {'end', 'num', 'bool', 'string', 'block', 'item', 'coords', 'break', 'for', 'while', 'until', 'switch', 'if', 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+ ']'
    ;

好像是行

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

创建了代币

num[] string[] block[] and item[]

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