antlr4在点网“不匹配输入 '开始' 期待{ ';', '+', ' - ', '*',DIV,MOD}

问题描述:

我使用antlr4在C#antlr4在点网“不匹配输入 '开始' 期待{ ';', '+', ' - ', '*',DIV,MOD}

一切工作正常。除了当我使用“块”一切都疯了

例如,这是我输入代码:

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]*; 

时我运行解析器我得到以下错误信息:

没有可行的替代在输入'如果(a == 2)begina:= a * 2; a:= a + 5;结束' 不匹配的输入'开始'期待{';','+',' - ','*',DIV,MOD} 在输入'结束'时没有可行的替代方案

在此先感谢。

的问题是你的语句列表规则:

statements : statement statements | EOF ; 

此规则有两个选择:一个statement其次是statements,或EOF另一个列表。唯一的非递归选项是EOF,当你使用这个在您的规则在block成为了一个问题:

block : BEGIN statements END ; 

你永远不能遇到EOFblock的中间,所以当解析器读取在您的示例输入中的end之前,它预计读取的另一个内容是另一个statement。单词end本身并不是有效的statement,这就是为什么它会抛出您所看到的错误。

一个可能的解决办法是让你的statements规则可选的递归部分:

statements : statement statements? | EOF ; 

这将使你的样品输入到成功解析。在我看来,一个更好的选择是完全去掉递归:

statements : statement* | EOF ; 

最后,你可以看到EOF仍然为statements规则的选项之一。当您在block规则的一部分中使用此规则时,这并没有多大意义,因为您应该在block的中间找不到EOF。我会做的是将此移至新的*解析器规则:

program : statements EOF ; 
statements : statement* ;