ANTLR – 输入错误不匹配

我有一个看起来像是由特定语言的注释和控制语句组成的语法:

语法:

grammar DD; ddlist: (ddstmt| jclcomment)+; ddstmt: dd1 | dd2 | dd3 | dd4 ; dd1: JCLBEGIN ddname DDWORD 'DUMMY'; dd2: JCLBEGIN ddname DDWORD 'DYNAM'; dd3: JCLBEGIN ddname DDWORD NAME'=' ('*'|NAME); dd4: JCLBEGIN ddname DDWORD '*' inlinerec INLINESTMTEND?; inlinerec: (INLINEDATA )+ ; fragment INLINEDATA: (~[\r\n])*; ddname: NAME; jclcomment: JCLCOMMENT+; JCLCOMMENT: COMMENTBEGIN ~[\r\n]*; DDWORD: 'DD'; JCLBEGIN: '//' ; COMMENTBEGIN: '//*' ; INLINESTMTEND: '/*' ; NAME : [AZ#] (ALPHA | NUMBER | SPECIALCHARS)*; NUMBER: [0-9]; ALPHA: [AZ]; SPECIALCHARS: '#' | '@' | '$'; STRING : '\'' (~[\r\n"])* '\'' | '"' (~[\r\n"])* '"' ; WS : [ \r\n] -> channel(HIDDEN); 

我的意见是这样的:

 //SYSIN DD * SORT FIELDS=COPY INCLUDE COND /* //SYSPRINT DD SYSOUT=* //* Comment line #1 //* Comment line #2 //SYSOUT DD SYSOUT=* //CEEDUMP DD SYSOUT=* //* Comment line #3 //SYSUDUMP DD SYSOUT=A 

当我使用AntlrWorks使用输入运行此语法时,我收到以下错误:

 line 2:0 mismatched input 'SORT' expecting INLINEDATA 

如何解决这个错误?

1)空格规则生成许多令牌:

 $ echo $CLASSPATH .:/usr/local/lib/antlr-4.6-complete.jar $ alias grun alias grun='java org.antlr.v4.gui.TestRig' $ grun DD ddlist -tokens jcl.txt [@6,11:12='DD',<'DD'>,1:11] [@7,13:13=' ',,channel=1,1:13] [@8,14:14=' ',,channel=1,1:14] [@9,15:15='*',<'*'>,1:15] [@10,16:16=' ',,channel=1,1:16] [@11,17:17=' ',,channel=1,1:17] [@12,18:18=' ',,channel=1,1:18] [@13,19:19=' ',,channel=1,1:19] [@14,20:20=' ',,channel=1,1:20] [@15,21:21=' ',,channel=1,1:21] [@16,22:22=' ',,channel=1,1:22] 

您可以使用+修饰符(=一个或多个)使用单个标记中的所有连续空格:

 WS : [ \t\r\n]+ -> channel(HIDDEN); [@3,11:12='DD',<'DD'>,1:11] [@4,13:14=' ',,channel=1,1:13] [@5,15:15='*',<'*'>,1:15] [@6,16:54=' \n',,channel=1,1:16] [@7,55:58='SORT',,2:0] 

2)您没有提到编译语法时出现的重要错误消息:

 warning(125): DD.g4:12:12: implicit definition of token INLINEDATA in parser 

在解析器中使用未定义的标记就好像您有一个词法分析器规则:

 INLINEDATA : 'INLINEDATA' ; 

这是一个字符串常量。 因此解析器规则

 dd4: JCLBEGIN ddname DDWORD '*' inlinerec INLINESTMTEND?; 

意思是:我希望输入流是:

 //{a name} DD * 'INLINEDATA' 

但输入是:

 //SYSIN DD * SORT 

因此消息

 line 2:0 mismatched input 'SORT' expecting INLINEDATA 

3)我对这种工作控制声明的语法:

 grammar JCL; /* Parsing JCL, ignoring inline sysin. */ jcl : jcl_card+ // good old punched cards :-) ; jcl_card : dd_statement | COMMENT ; dd_statement : '//' NAME 'DD' file_type ( NL | EOF ) ; file_type : 'DUMMY' | 'DYNAM' | NAME '=' ( '*' | NAME ) | '*' NL inline_sysin ; inline_sysin : NON_JCL_CARD* END_OF_FILE ; NAME : [AZ#] ( LETTER | DIGIT | SPECIAL_CHARS )* ; COMMENT : '//*' .*? ( NL | EOF ) ; END_OF_FILE : '/' {getCharPositionInLine() == 1}? '*' ; NON_JCL_CARD : ~'/' {getCharPositionInLine() == 1}? .*? ( NL | EOF ) ; STRING : '\'' .*? '\'' | '"' .*? '"' ; NL : [\r\n] ; WS : [ \t]+ -> skip ; // or -> channel(HIDDEN) to keep white space tokens fragment DIGIT : [0-9] ; fragment LETTER : [AZ] ; fragment SPECIAL_CHARS : '#' | '@' | '$' ; 

随着输入

 //SYSIN DD * SORT FIELDS=COPY INCLUDE COND any other program input @ $ ! & % /* //SYSPRINT DD SYSOUT=* //* Comment line #1 //* Comment line #2 //SYSOUT DD SYSOUT=* //SYSOUT DD DUMMY //SYSIN DD * /* not end of input /* 

它给

 $ grun JCL jcl -tokens jcl.txt [@0,0:1='//',<'//'>,1:0] [@1,2:6='SYSIN',,1:2] [@2,11:12='DD',<'DD'>,1:11] [@3,15:15='*',<'*'>,1:15] [@4,21:21='\n',,1:21] [@5,22:38='SORT FIELDS=COPY\n',,2:0] [@6,39:51='INCLUDE COND\n',,3:0] [@7,52:85='any other program input @ $ ! & %\n',,4:0] [@8,86:87='/*',,5:0] [@9,106:106='\n',,5:20] ... @17,131:161='//* Comment line #1 \n',,7:0] ... [@31,232:233='//',<'//'>,11:0] [@32,234:238='SYSIN',,11:2] [@33,243:244='DD',<'DD'>,11:11] [@34,247:247='*',<'*'>,11:15] [@35,253:253='\n',,11:21] [@36,254:278=' /* not end of input \n',,12:0] [@37,279:280='/*',,13:0] [@38,281:280='',,13:2] 

尝试使用-gui选项来显示解析树:

 $ grun JCL jcl -gui jcl.txt