Antlr4不匹配输入

时间:2018-09-06 15:08:59

标签: antlr4

首先,我阅读了以下类似问题的解决方案:q1 q2 q3

我仍然不明白为什么收到以下消息:

df[ , ':='(sumVar = sum(Variable)/sum(df$Variable)), by = .(Factor)]

当我尝试匹配以下内容时:

line 1:0 missing 'PROGRAM' at 'PROGRAM'

我的语法:

PROGRAM test
BEGIN
END

根据我的阅读,我认为KEYWORD和PROGRAM之间不匹配,但是完全删除KEYWORD并不能解决问题。

编辑: 删除KEYWORD会显示以下消息:

grammar Wengo; program : PROGRAM id BEGIN pgm_body END ; id : IDENTIFIER ; pgm_body : decl func_declarations ; decl : string_decl decl | var_decl decl | empty ; string_decl : STRING id ASSIGN str SEMICOLON ; str : STRINGLITERAL ; var_decl : var_type id_list SEMICOLON ; var_type : FLOAT | INT ; any_type : var_type | VOID ; id_list : id id_tail ; id_tail : COMA id id_tail | empty ; param_decl_list : param_decl param_decl_tail | empty ; param_decl : var_type id ; param_decl_tail : COMA param_decl param_decl_tail | empty ; func_declarations : func_decl func_declarations | empty ; func_decl : FUNCTION any_type id (param_decl_list) BEGIN func_body END ; func_body : decl stmt_list ; stmt_list : stmt stmt_list | empty ; stmt : base_stmt | if_stmt | loop_stmt ; base_stmt : assign_stmt | read_stmt | write_stmt | control_stmt ; assign_stmt : assign_expr SEMICOLON ; assign_expr : id ASSIGN expr ; read_stmt : READ ( id_list )SEMICOLON ; write_stmt : WRITE ( id_list )SEMICOLON ; return_stmt : RETURN expr SEMICOLON ; expr : expr_prefix factor ; expr_prefix : expr_prefix factor addop | empty ; factor : factor_prefix postfix_expr ; factor_prefix : factor_prefix postfix_expr mulop | empty ; postfix_expr : primary | call_expr ; call_expr : id ( expr_list ) ; expr_list : expr expr_list_tail | empty ; expr_list_tail : COMA expr expr_list_tail | empty ; primary : ( expr ) | id | INTLITERAL | FLOATLITERAL ; addop : ADD | MIN ; mulop : MUL | DIV ; if_stmt : IF ( cond ) decl stmt_list else_part ENDIF ; else_part : ELSE decl stmt_list | empty ; cond : expr compop expr | TRUE | FALSE ; compop : LESS | GREAT | EQUAL | NOTEQUAL | LESSEQ | GREATEQ ; while_stmt : WHILE ( cond ) decl stmt_list ENDWHILE ; control_stmt : return_stmt | CONTINUE SEMICOLON | BREAK SEMICOLON ; loop_stmt : while_stmt | for_stmt ; init_stmt : assign_expr | empty ; incr_stmt : assign_expr | empty ; for_stmt : FOR ( init_stmt SEMICOLON cond SEMICOLON incr_stmt ) decl stmt_list ENDFOR ; COMMENT : '--' ~[\r\n]* -> skip ; WS : [ \t\r\n]+ -> skip ; NEWLINE : [ \n] ; EMPTY : $ ; KEYWORD : PROGRAM|BEGIN|END|FUNCTION|READ|WRITE|IF|ELSE|ENDIF|WHILE|ENDWHILE|RETURN|INT|VOID|STRING|FLOAT|TRUE|FALSE|FOR|ENDFOR|CONTINUE|BREAK ; OPERATOR : ASSIGN|ADD|MIN|MUL|DIV|EQUAL|NOTEQUAL|LESS|GREAT|LBRACKET|RBRACKET|SEMICOLON|COMA|LESSEQ|GREATEQ ; IDENTIFIER : [a-zA-Z][a-zA-Z0-9]* ; INTLITERAL : [0-9]+ ; FLOATLITERAL : [0-9]*'.'[0-9]+ ; STRINGLITERAL : '"' (~[\r\n"] | '""')* '"' ; PROGRAM : 'PROGRAM'; BEGIN : 'BEGIN'; END : 'END'; FUNCTION : 'FUNCTION'; READ : 'READ'; WRITE : 'WRITE'; IF : 'IF'; ELSE : 'ELSE'; ENDIF : 'ENDIF'; WHILE : 'WHILE'; ENDWHILE : 'ENDWHILE'; RETURN : 'RETURN'; INT : 'INT'; VOID : 'VOID'; STRING : 'STRING'; FLOAT : 'FLOAT' ; TRUE : 'TRUE'; FALSE : 'FALSE'; FOR : 'FOR'; ENDFOR : 'ENDFOR'; CONTINUE : 'CONTINUE'; BREAK : 'BREAK'; ASSIGN : ':='; ADD : '+'; MIN : '-'; MUL : '*'; DIV : '/'; EQUAL : '='; NOTEQUAL : '!='; LESS : '<'; GREAT : '>'; LBRACKET : '('; RBRACKET : ')'; SEMICOLON : ';'; COMA : ','; LESSEQ : '<='; GREATEQ : '>=';

当KEYWORD可用时,这是我的grun输出:

line 3:0 mismatched input 'END' expecting {'INT', 'STRING', 'FLOAT', '+'}

这是删除KEYWORD时的输出:

[@0,0:6='PROGRAM',<KEYWORD>,1:0]
[@1,8:11='test',<IDENTIFIER>,1:8]
[@2,13:17='BEGIN',<KEYWORD>,2:0]
[@3,19:21='END',<KEYWORD>,3:0]
[@4,23:22='<EOF>',<EOF>,4:0]
line 1:0 mismatched input 'PROGRAM' expecting 'PROGRAM'
(program PROGRAM test BEGIN END)

1 个答案:

答案 0 :(得分:1)

当您删除KEYWORD规则时,有关“缺少'PROGRAM'”的错误已得到解决(请注意,出于同样的原因,您也应删除OPERATOR规则)。

您现在遇到的错误是完全不相关的。

您当前的问题与empty的定义有关,您没有显示。您已经说过您同时尝试了EMPTY : $ ;EMPTY : ^$ ;(然后大概是empty: EMPTY;),但是都没有编译过,因此它们不会引起您发布的解析错误。无论哪种方式,EMPTY令牌的概念都不起作用。什么时候会生成这样的令牌?在其他令牌之间有一次?在这种情况下,您会收到很多“意外的EMPTY”错误。不,empty规则的全部意义在于它应该成功而不消耗任何令牌。

要实现此目的,您只需定义empty : ;并完全删除EMPTY。另外,您也可以删除empty,然后在当前使用| ;的任何地方使用一个空的替代项(即empty)。两种方法都可以使您的代码正常工作,但是有更好的方法:

您使用empty作为基本等于列表的规则的基本情况。 ANTLR提供重复运算符*(0或更多),+(1或更多)以及?运算符来使事物可选。这些允许您以非递归方式定义列表,而无需使用empty规则。例如,stmt_list可以这样定义:

stmt_list : stmt* ;

id_list这样:

id_list : (id (',' id)*)? ;

无关紧要的是,利用ANTLR 4支持直接左递归这一事实,可以大大简化您的语法,因此您可以摆脱所有不同的表达规则,而只拥有一个左递归规则。

那会给你:

expr : primary
     | id '(' expr_list ')'
     | expr mulop expr
     | expr addop expr
     ;

规则expr_prefixfactorfactor_prefixpostfix_exprcall_expr都可以删除。