点网中的 antlr4“输入不匹配 'begin' 期望 {';', '+', '-', '*', DIV, MOD}
antlr4 in dot net "mismatched input 'begin' expecting {';', '+', '-', '*', DIV, MOD}
我在 C# 中使用 antlr4。
一切正常,除非我使用 'block' 一切都变得疯狂。
例如这是我的输入代码:
a:int;
a:=2;
if(a==2) begin
a:= a * 2;
a:=a + 5;
end
这是我的语法:
grammar Our;
options{
language=CSharp;
TokenLabelType=CommonToken;
ASTLabelType=CommonTree;
}
statements : statement statements
|EOF;
statement :
expression SEMI
| ifstmt
| whilestmt
| forstmt
| readstmt SEMI
| writestmt SEMI
| vardef SEMI
| block
;
block : BEGIN statements END ;
expression : ID ASSIGN expression
| boolexp;
boolexp : relexp AND boolexp
| relexp OR boolexp
| relexp;
relexp : modexp EQUAL relexp
| modexp LE relexp
| modexp GE relexp
| modexp NOTEQUAL relexp
| modexp GT relexp
| modexp LT relexp
| modexp;
modexp : modexp MOD exp
//| exp DIV modexp
| exp;
exp : exp ADD term
| exp SUB term
| term;
term : term MUL factor
| term DIV factor
| factor POW term
| factor;
factor : LPAREN expression RPAREN
| LPAREN vartype RPAREN factor
| ID
| SUB factor
| ID LPAREN explist RPAREN
| ID LPAREN RPAREN
| ID LPAREN LPAREN NUM RPAREN RPAREN
| ID LPAREN LPAREN NUM COMMA NUM RPAREN RPAREN
| const;
explist : exp COMMA explist
|exp;
const : NUM
| BooleanLiteral
| STRING;
ifstmt : IF LPAREN boolexp RPAREN statement
| IF LPAREN boolexp RPAREN statement ELSE statement ;
whilestmt : WHILE LPAREN boolexp RPAREN statement ;
forstmt : FOR ID ASSIGN exp COLON exp statement;
readstmt : READ LPAREN idlist RPAREN ;
idlist : ID COMMA idlist
|ID;
writestmt : WRITE LPAREN explist RPAREN ;
vardef : idlist COLON vartype;
vartype : basictypes
| basictypes LPAREN NUM RPAREN
| basictypes LPAREN NUM COMMA NUM RPAREN ;
basictypes : INT
| FLOAT
| CHAR
| STRING
| BOOLEAN ;
BEGIN : 'begin';
END : 'end';
To : 'to';
NEXT : 'next';
REAL : 'real';
BOOLEAN : 'boolean';
CHAR : 'char';
DO : 'do';
DOUBLE : 'double';
ELSE : 'else';
FLOAT : 'float';
FOR : 'for';
FOREACH : 'foreach';
FUNCTION : 'function';
IF : 'if';
INT : 'int';
READ : 'read';
RETURN : 'return';
VOID : 'void';
WHILE : 'while';
WEND : 'wend';
WRITE : 'write';
LPAREN : '(';
RPAREN : ')';
LBRACE : '{';
RBRACE : '}';
LBRACK : '[';
RBRACK : ']';
SEMI : ';';
COMMA : ',';
ASSIGN : ':=';
GT : '>';
LT : '<';
COLON : ':';
EQUAL : '==';
LE : '<=';
GE : '>=';
NOTEQUAL : '!=';
AND : '&&'|'and';
OR : '||'|'or';
INC : '++';
DEC : '--';
ADD : '+';
SUB : '-';
MUL : '*';
DIV : '/'|'div';
MOD : '%'|'mod';
ADD_ASSIGN : '+=';
SUB_ASSIGN : '-=';
MUL_ASSIGN : '*=';
DIV_ASSIGN : '/=';
POW : '^';
BooleanLiteral : 'true'|'false';
STRING : '\"'([a-zA-Z]|NUM)*'\"';
ID : ([a-z]|[A-Z])([a-z]|[A-z]|[0-9])*;
NUM : ('+'|'-')?[0-9]([0-9]*)('.'[0-9][0-9]*)?;
WS : [ \t\r\n\u000C]+ -> skip ;
COMMENT : '/*' .*? '*/' ;
LINE_COMMENT : '//' ~[\r\n]*;
当我 运行 解析器时,我收到以下错误消息:
输入时没有可行的替代方案'if(a==2)begina:=a*2;a:=a+5;end'
不匹配的输入 'begin' 期待 {';', '+', '-', '*', DIV, MOD}
输入 'end'
没有可行的替代方案
提前致谢。
问题是您对语句列表的规则:
statements : statement statements | EOF ;
此规则有两个选项:statement
后跟另一个 statements
列表,或 EOF
。唯一的 non-recursive 选项是 EOF
,当您在 block
:
的规则中使用它时会出现问题
block : BEGIN statements END ;
你永远不会在 block
的中间遇到 EOF
,所以当解析器在你的示例输入中读取 end
之前的行时,它期望的下一件事阅读是另一个 statement
。单词 end
本身不是有效的 statement
,这就是它抛出您所看到的错误的原因。
一个可能的解决方法是将 statements
规则的递归部分设为可选:
statements : statement statements? | EOF ;
这将使您的示例输入能够成功解析。在我看来,更好的选择是完全删除递归:
statements : statement* | EOF ;
最后可以看到EOF
仍然是statements
规则的选项之一。当您在 block
规则的一部分中使用此规则时,这没有多大意义,因为您不应该在 block
的中间找到 EOF
。我要做的是将其移至新的顶级解析器规则:
program : statements EOF ;
statements : statement* ;
我在 C# 中使用 antlr4。
一切正常,除非我使用 'block' 一切都变得疯狂。
例如这是我的输入代码:
a:int;
a:=2;
if(a==2) begin
a:= a * 2;
a:=a + 5;
end
这是我的语法:
grammar Our;
options{
language=CSharp;
TokenLabelType=CommonToken;
ASTLabelType=CommonTree;
}
statements : statement statements
|EOF;
statement :
expression SEMI
| ifstmt
| whilestmt
| forstmt
| readstmt SEMI
| writestmt SEMI
| vardef SEMI
| block
;
block : BEGIN statements END ;
expression : ID ASSIGN expression
| boolexp;
boolexp : relexp AND boolexp
| relexp OR boolexp
| relexp;
relexp : modexp EQUAL relexp
| modexp LE relexp
| modexp GE relexp
| modexp NOTEQUAL relexp
| modexp GT relexp
| modexp LT relexp
| modexp;
modexp : modexp MOD exp
//| exp DIV modexp
| exp;
exp : exp ADD term
| exp SUB term
| term;
term : term MUL factor
| term DIV factor
| factor POW term
| factor;
factor : LPAREN expression RPAREN
| LPAREN vartype RPAREN factor
| ID
| SUB factor
| ID LPAREN explist RPAREN
| ID LPAREN RPAREN
| ID LPAREN LPAREN NUM RPAREN RPAREN
| ID LPAREN LPAREN NUM COMMA NUM RPAREN RPAREN
| const;
explist : exp COMMA explist
|exp;
const : NUM
| BooleanLiteral
| STRING;
ifstmt : IF LPAREN boolexp RPAREN statement
| IF LPAREN boolexp RPAREN statement ELSE statement ;
whilestmt : WHILE LPAREN boolexp RPAREN statement ;
forstmt : FOR ID ASSIGN exp COLON exp statement;
readstmt : READ LPAREN idlist RPAREN ;
idlist : ID COMMA idlist
|ID;
writestmt : WRITE LPAREN explist RPAREN ;
vardef : idlist COLON vartype;
vartype : basictypes
| basictypes LPAREN NUM RPAREN
| basictypes LPAREN NUM COMMA NUM RPAREN ;
basictypes : INT
| FLOAT
| CHAR
| STRING
| BOOLEAN ;
BEGIN : 'begin';
END : 'end';
To : 'to';
NEXT : 'next';
REAL : 'real';
BOOLEAN : 'boolean';
CHAR : 'char';
DO : 'do';
DOUBLE : 'double';
ELSE : 'else';
FLOAT : 'float';
FOR : 'for';
FOREACH : 'foreach';
FUNCTION : 'function';
IF : 'if';
INT : 'int';
READ : 'read';
RETURN : 'return';
VOID : 'void';
WHILE : 'while';
WEND : 'wend';
WRITE : 'write';
LPAREN : '(';
RPAREN : ')';
LBRACE : '{';
RBRACE : '}';
LBRACK : '[';
RBRACK : ']';
SEMI : ';';
COMMA : ',';
ASSIGN : ':=';
GT : '>';
LT : '<';
COLON : ':';
EQUAL : '==';
LE : '<=';
GE : '>=';
NOTEQUAL : '!=';
AND : '&&'|'and';
OR : '||'|'or';
INC : '++';
DEC : '--';
ADD : '+';
SUB : '-';
MUL : '*';
DIV : '/'|'div';
MOD : '%'|'mod';
ADD_ASSIGN : '+=';
SUB_ASSIGN : '-=';
MUL_ASSIGN : '*=';
DIV_ASSIGN : '/=';
POW : '^';
BooleanLiteral : 'true'|'false';
STRING : '\"'([a-zA-Z]|NUM)*'\"';
ID : ([a-z]|[A-Z])([a-z]|[A-z]|[0-9])*;
NUM : ('+'|'-')?[0-9]([0-9]*)('.'[0-9][0-9]*)?;
WS : [ \t\r\n\u000C]+ -> skip ;
COMMENT : '/*' .*? '*/' ;
LINE_COMMENT : '//' ~[\r\n]*;
当我 运行 解析器时,我收到以下错误消息:
输入时没有可行的替代方案'if(a==2)begina:=a*2;a:=a+5;end' 不匹配的输入 'begin' 期待 {';', '+', '-', '*', DIV, MOD} 输入 'end'
没有可行的替代方案提前致谢。
问题是您对语句列表的规则:
statements : statement statements | EOF ;
此规则有两个选项:statement
后跟另一个 statements
列表,或 EOF
。唯一的 non-recursive 选项是 EOF
,当您在 block
:
block : BEGIN statements END ;
你永远不会在 block
的中间遇到 EOF
,所以当解析器在你的示例输入中读取 end
之前的行时,它期望的下一件事阅读是另一个 statement
。单词 end
本身不是有效的 statement
,这就是它抛出您所看到的错误的原因。
一个可能的解决方法是将 statements
规则的递归部分设为可选:
statements : statement statements? | EOF ;
这将使您的示例输入能够成功解析。在我看来,更好的选择是完全删除递归:
statements : statement* | EOF ;
最后可以看到EOF
仍然是statements
规则的选项之一。当您在 block
规则的一部分中使用此规则时,这没有多大意义,因为您不应该在 block
的中间找到 EOF
。我要做的是将其移至新的顶级解析器规则:
program : statements EOF ;
statements : statement* ;