ANTLR4 g4语法用于读取不同块中的键/值对

ANTLR4 g4语法用于读取不同块中的键/值对,antlr4,Antlr4,我是antlr的新手,我试着做简单的语法,但我没能成功。 我想解析此类文件: BEGIN HEADER CharacterSet "CP1252" END HEADER BEGIN DSJOB test "val" END DSJOB BEGIN DSJOB test "val2" END DS 工作 我用的是这种语法: grammar Hello; dsxFile : headerDeclaration? jobDeclaration* E

我是antlr的新手,我试着做简单的语法,但我没能成功。 我想解析此类文件:

BEGIN HEADER
    CharacterSet "CP1252"
END HEADER
BEGIN DSJOB
    test "val"
END DSJOB
BEGIN DSJOB
    test "val2"
END DS
工作

我用的是这种语法:

grammar Hello;
dsxFile             :   headerDeclaration? jobDeclaration* EOF;
headerDeclaration   :   'BEGIN HEADER' param* 'END HEADER';
jobDeclaration      :   'BEGIN DSJOB' subJobDeclaration* param* 'END DSJOB';
subJobDeclaration       :   'BEGIN DSSUBJOB' param* 'END DSSUBJOB';

headParam
    :   (   'CharacterSet'     
        |   'name'  
        ) StringLiteral
    ;

// ANNOTATIONS
param   :   PNAME PVALUE;

PNAME :StringCharacters;
PVALUE :StringCharacters;
// STATEMENTS / BLOCKS
//block
//    :   '{' blockStatement* '}';

// LEXER

// Keywords

ABSTRACT      : 'abstract';
ASSERT        : 'assert';
BOOLEAN       : 'boolean';
BREAK         : 'break';
BYTE          : 'byte';
CASE          : 'case';
CATCH         : 'catch';
CHAR          : 'char';
CLASS         : 'class';
CONST         : 'const';
CONTINUE      : 'continue';
DEFAULT       : 'default';
DO            : 'do';
DOUBLE        : 'double';
ELSE          : 'else';
ENUM          : 'enum';
EXTENDS       : 'extends';
FINAL         : 'final';
FINALLY       : 'finally';
FLOAT         : 'float';
FOR           : 'for';
IF            : 'if';
GOTO          : 'goto';
IMPLEMENTS    : 'implements';
IMPORT        : 'import';
INSTANCEOF    : 'instanceof';
INT           : 'int';
INTERFACE     : 'interface';
LONG          : 'long';
NATIVE        : 'native';
NEW           : 'new';
PACKAGE       : 'package';
PRIVATE       : 'private';
PROTECTED     : 'protected';
PUBLIC        : 'public';
RETURN        : 'return';
SHORT         : 'short';
STATIC        : 'static';
STRICTFP      : 'strictfp';
SUPER         : 'super';
SWITCH        : 'switch';
SYNCHRONIZED  : 'synchronized';
THIS          : 'this';
THROW         : 'throw';
THROWS        : 'throws';
TRANSIENT     : 'transient';
TRY           : 'try';
VOID          : 'void';
VOLATILE      : 'volatile';
WHILE         : 'while';

//  Boolean Literals

BooleanLiteral  :   'true' |   'false';

//  Character Literals


fragment
SingleCharacter
    :   ~['\\] ;
//  String Literals
StringLiteral
    :   '"' StringCharacters? '"'
    ;
fragment
StringCharacters
    :   StringCharacter+
    ;
fragment
StringCharacter
    :   ~["\\]
    ;


// Separators

LPAREN          : '(';
RPAREN          : ')';
LBRACE          : '{';
RBRACE          : '}';
LBRACK          : '[';
RBRACK          : ']';
SEMI            : ';';
COMMA           : ',';
DOT             : '.';

// Operators

ASSIGN          : '=';
GT              : '>';
LT              : '<';
BANG            : '!';
TILDE           : '~';
QUESTION        : '?';
COLON           : ':';
EQUAL           : '==';
LE              : '<=';
GE              : '>=';
NOTEQUAL        : '!=';
AND             : '&&';
OR              : '||';
INC             : '++';
DEC             : '--';
ADD             : '+';
SUB             : '-';
MUL             : '*';
DIV             : '/';
BITAND          : '&';
BITOR           : '|';
CARET           : '^';
MOD             : '%';

ADD_ASSIGN      : '+=';
SUB_ASSIGN      : '-=';
MUL_ASSIGN      : '*=';
DIV_ASSIGN      : '/=';
AND_ASSIGN      : '&=';
OR_ASSIGN       : '|=';
XOR_ASSIGN      : '^=';
MOD_ASSIGN      : '%=';
LSHIFT_ASSIGN   : '<<=';
RSHIFT_ASSIGN   : '>>=';
URSHIFT_ASSIGN  : '>>>=';


//
// Additional symbols not defined in the lexical specification
//

AT : '@';
ELLIPSIS : '...';

//
// Whitespace and comments
//

WS  :  [ \t\r\n\u000C]+ -> skip
    ;

COMMENT
    :   '/*' .*? '*/' -> skip
    ;

LINE_COMMENT
    :   '//' ~[\r\n]* -> skip
;
语法你好; DSX文件:标题声明?职位声明*EOF; HeaderDebration:“开始标头”参数*“结束标头”; jobDeclaration:'BEGIN DSJOB'SubbobDeclaration*param*'END DSJOB'; SubbobDeclaration:'开始DSSUBJOB'参数*'结束DSSUBJOB'; 头参数 :(“字符集” |“姓名” )StringLiteral ; //注释 param:PNAME PVALUE; PNAME:StringCharacters; PVALUE:字符串字符; //语句/块 //挡块 //:“{”块语句*“}”; //雷克瑟 //关键词 摘要:“摘要”; 断言:‘断言’; 布尔:'布尔'; 休息:“休息”; 字节:“字节”; 案例:“案例”; 接球:“接球”; CHAR:‘CHAR’; 阶级:"阶级";; 常数:“常数”; 继续:"继续";; 默认:“默认”; DO:‘DO’; 双:‘双’; ELSE:‘ELSE’; 枚举:“枚举”; 延伸:“延伸”; 决赛:“决赛”; 最后:"最后",; 浮动:“浮动”; 因为‘为了’; 如果:‘如果’; 后藤:‘后藤’; 工具:“工具”; 进口:‘进口’; INSTANCEOF:'INSTANCEOF'; INT:‘INT’; 接口:“接口”; 长:“长”; 本地人:“本地人”; 新:"新";; 包:"包";; 私人:"私人";; 受保护:“受保护”; 公众:"公众";; RETURN:‘RETURN’; 短:“短”; 静态:“静态”; STRICTFP:‘STRICTFP’; 超级:“超级”; 开关:“开关”; SYNCHRONIZED:‘SYNCHRONIZED’; 这个:"这个",; 扔:‘扔’; 投掷:“投掷”; 暂时的:“暂时的”; 试试:‘试试’; 无效:“无效”; 挥发性:“挥发性”; WHILE:‘WHILE’; //布尔文字 BooleanLiteral:'真'|'假'; //字符文字 片段 单字符 : ~['\\] ; //字符串文字 StringLiteral :““‘字符串字符’”” ; 片段 字符串字符 :字符串字符+ ; 片段 字符串字符 : ~["\\] ; //分离器 LPAREN:'('; RPAREN:')'; LBRACE:“{”; RBRACE:'}'; LBRACK:'['; RBRACK:']'; 半:';'; 逗号:','; 点:'; //操作员 分配:'='; GT:“>”; LT:“>>=”; // //词法规范中未定义的其他符号 // 在:“@”; 省略号:“…”; // //空白和注释 // WS:[\t\r\n\u000C]+->跳过 ; 评论 :“/*”.*?“*/”->跳过 ; 行注释 :“/”~[\r\n]*->跳过 ; 但我还是遇到了这个问题:

第1行:0不匹配的输入“BEGIN HEADER\r\n\tCharacterSet”应为 {,'BEGIN HEADER','BEGIN DSJOB'}(DSX文件BEGIN 标头\r\n\t字符集“CP1252”\r\n标头\r\n DSJOB\r\n\t测试“val”\r\n输入DSJOB)

有人能解释一下这是什么意思吗?似乎不能跳过\r\t


感谢大家的帮助!

问题在于,您的输入没有按预期标记化。这是因为lexer匹配尽可能多的输入。因此,如果您查看
PNAME
规则:

PNAME : StringCharacters;

fragment StringCharacter
 : ~["\\]
 ;
然后您会注意到输入的
“beginheader\n CharacterSet”
与该规则匹配

这是错误消息所显示的内容:

不匹配的输入'BEGIN HEADER\r\n\tCharacterSet'应为{,'BEGIN HEADER','BEGIN DSJOB'}

说明:找到了标记
'BEGIN HEADER\r\n\tCharacterSet'
,而解析器需要一个标记
'BEGIN HEADER'
'BEGIN DSJOB'

您可能需要在该类中添加空格、制表符和换行符:
~[“\\\t\r\n]
(但这由您决定)

此外,lexer独立于解析器进行操作(解析器对生成的令牌没有影响)。lexer只是尝试匹配尽可能多的字符,每当有两个(或更多)规则匹配相同的字符时,第一个定义的规则“获胜”。根据此逻辑,然后根据以下规则:

PNAME : StringCharacters;
PVALUE : StringCharacters;
显然,规则
PVALUE
永远不会匹配(仅
PNAME
,因为该规则是首先定义的)

以下是如何解析示例输入:

grammar Hello;

dsxFile            : headerDeclaration? jobDeclaration* EOF;
headerDeclaration  : BEGIN HEADER param* END HEADER;
jobDeclaration     : BEGIN DSJOB subJobDeclaration* param* END DSJOB;
subJobDeclaration  : BEGIN DSSUBJOB param* END DSSUBJOB;
param              : PNAME pvalue;
pvalue             : STRING /* other alternaives here? */;

STRING       : '"' ~["\r\n]* '"';
BEGIN        : 'BEGIN';
END          : 'END';
HEADER       : 'HEADER';
DSJOB        : 'DSJOB';
DSSUBJOB     : 'DSSUBJOB';

WS           : [ \t\r\n\u000C]+ -> skip;
COMMENT      : '/*' .*? '*/'    -> skip;
LINE_COMMENT : '//' ~[\r\n]*    -> skip;

// Be sure to put this rule _after_ the rules BEGIN, END, HEADER, ...
// otherwise this rule will match those keywords instead
PNAME        : ~["\\ \t\r\n]+;


当然,您需要更改它以完全满足您的需要,但这只是一个开始。

请发布一个完整的、有效的语法,该语法会产生您提到的错误。添加完整语法,非常感谢您,所有内容都变得清晰,我将尝试应用此语法。