方括号在 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 向我指出这一点:)
我目前正在为我的学期项目创建一种编程语言。我们正在使用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 向我指出这一点:)