我正试图为CAL语言编写一个解析器,但在中出现了这些错误
line 3:12 mismatched input ')' expecting {'(', '+', '-', True, False, Number, ID}
line 8:4 no viable alternative at input 'func'
line 8:10 mismatched input ')' expecting {If, While, Skipp, Begin, ID}
line 8:11 extraneous input ';' expecting End
运行grun cal prog-gui test.cal 时
我的测试.cal:
void func () is
begin
return ();
end
main
begin
func ();
end
我的cal.g4:
grammar cal;
prog: decl_list function_list main Eof;
decl_list: decl SEMI decl_list |;
decl: var_decl | const_decl;
var_decl: Var ID COLON type;
const_decl: Const ID COLON type ASSIGN expression;
function_list: function function_list |;
function: type ID LBR parameter_list RBR Is decl_list Begin statement_block Return LBR expression
| RBR SEMI End;
type: TypeInteger | TypeBoolean | TypeVoid;
parameter_list: nemp_parameter_list |;
nemp_parameter_list: ID COLON type
| ID COLON type COMMA nemp_parameter_list
;
main: Main Begin decl_list statement_block End;
statement_block: LBR statement statement_block RBR |;
statement: ID ASSIGN expression SEMI
| ID LBR arg_list RBR SEMI
| Begin statement_block End
| If condition Begin statement_block End Else Begin statement_block End
| While condition Begin statement_block End
| Skipp SEMI
;
expression: frag binary_arith_op frag
| LBR expression RBR
| ID LBR arg_list RBR
| frag;
binary_arith_op: op=(PLUS | MINUS);
frag: ID | MINUS ID | Number | True | False | binary_arith_op frag
| LBR expression RBR
| ID LBR arg_list RBR;
condition: TILDE condition
| LBR condition RBR
| expression comp_op expression
| condition op=(OR|AND) condition
;
comp_op: EQUAL | NOTEQUAL | LESS | LESSEQUAL | GREATER | GREATEREQUAL;
arg_list: nemp_arg_list |;
nemp_arg_list: ID | ID COMMA nemp_arg_list;
fragment A: 'a' | 'A';
fragment B: 'b' | 'B';
fragment C: 'c' | 'C';
fragment D: 'd' | 'D';
fragment E: 'e' | 'E';
fragment F: 'f' | 'F';
fragment G: 'g' | 'G';
fragment H: 'h' | 'H';
fragment I: 'i' | 'I';
fragment J: 'j' | 'J';
fragment K: 'k' | 'K';
fragment L: 'l' | 'L';
fragment M: 'm' | 'M';
fragment N: 'n' | 'N';
fragment O: 'o' | 'O';
fragment P: 'p' | 'P';
fragment Q: 'q' | 'Q';
fragment R: 'r' | 'R';
fragment S: 's' | 'S';
fragment T: 't' | 'T';
fragment U: 'u' | 'U';
fragment V: 'v' | 'V';
fragment W: 'w' | 'W';
fragment X: 'x' | 'X';
fragment Y: 'y' | 'Y';
fragment Z: 'z' | 'Z';
fragment Digit: [0-9];
fragment Integer: (MINUS? [1-9] Digit*) | '0'+;
COMMA: ',';
SEMI: ';';
COLON: ':';
ASSIGN: ':=';
LBR: '(';
RBR: ')';
PLUS: '+';
MINUS: '-';
TILDE: '~';
OR: '|';
AND: '&';
EQUAL: '=';
NOTEQUAL: '!=';
LESS: '<';
LESSEQUAL: '<=';
GREATER: '>';
GREATEREQUAL: '>=';
Const: C O N S T;
Return: R E T U R N;
TypeInteger: I N T E G E R;
TypeBoolean: B O O L E A N;
TypeVoid: V O I D;
Main: M A I N;
If: I F;
Else: E L S E;
True: T R U E;
False: F A L S E;
While: W H I L E;
Is: I S;
Skipp: S K I P;
Var: V A R;
Begin: B E G I N;
End: E N D;
Number: Digit | Integer;
Letter: [a-zA-Z];
ID: Letter (Letter | Digit | '_')*;
WS: [ tnr]+-> skip;
我真的不确定是什么原因导致了这种情况,即使在做了一点挖掘之后,我认为这可能是测试文件本身的问题,但显然是我的语法规则造成的。你知道是什么原因造成了这种情况吗?
有几件事出了问题:
您使用Eof
,它应该是EOF
:
prog: decl_list function_list main EOF;
function
规则看起来很奇怪:
function: type ID LBR parameter_list RBR Is decl_list Begin statement_block Return LBR expression
| RBR SEMI End;
我认为您应该删除末尾的|
:| RBR SEMI End;
,因为您还想匹配return ();
,所以应该将expression
设置为可选。这可能就是你想要的:
function
: type ID LBR parameter_list RBR Is decl_list Begin statement_block Return LBR expression? RBR SEMI End
;
最后,在您的statement_block规则中:
statement_block: LBR statement statement_block RBR |;
你说每个块都应该用括号括起来,但看看你的输入,事实并非如此。所以你可能想这样做:
statement_block: statement statement_block |;
也可以这样写:
statement_block: statement*;