ANTLR4 g4 语法在不同的块中读取 key/value 对
ANTLR4 g4 grammar to read key/value pair in different blocks
我是 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
;
但我仍然遇到这个问题:
line 1:0 mismatched input 'BEGIN HEADER\r\n\tCharacterSet ' expecting
{, 'BEGIN HEADER', 'BEGIN DSJOB'} (dsxFile BEGIN
HEADER\r\n\tCharacterSet "CP1252" \r\nEND HEADER\r\nBEGIN
DSJOB\r\n\ttest "val" \r\nEND DSJOB)
谁能解释一下这是什么意思?好像不能跳过\r\t.
感谢大家的帮助!
问题是您的输入没有像您预期的那样被标记化。这是因为词法分析器匹配尽可能多的输入。因此,如果您查看 PNAME
规则:
PNAME : StringCharacters;
fragment StringCharacter
: ~["\]
;
然后您会注意到输入 "BEGIN HEADER\n CharacterSet "
匹配该规则。
错误信息是这样的:
mismatched input 'BEGIN HEADER\r\n\tCharacterSet ' expecting {, 'BEGIN HEADER', 'BEGIN DSJOB'}
说明:找到了标记 'BEGIN HEADER\r\n\tCharacterSet '
,而解析器需要标记 'BEGIN HEADER'
或 'BEGIN DSJOB'
.
之一
您可能需要添加空格、制表符和换行符 class:~["\ \t\r\n]
(但这由您决定)
此外,词法分析器独立于解析器运行(解析器对生成的标记没有影响)。词法分析器只是简单地尝试匹配尽可能多的字符,每当有两个(或更多)规则匹配相同的字符时,首先定义的规则 "wins"。鉴于此逻辑,则从以下规则:
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]+;
当然,您需要对其进行更改以完全满足您的需要,但这只是一个开始。
我是 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
;
但我仍然遇到这个问题:
line 1:0 mismatched input 'BEGIN HEADER\r\n\tCharacterSet ' expecting {, 'BEGIN HEADER', 'BEGIN DSJOB'} (dsxFile BEGIN HEADER\r\n\tCharacterSet "CP1252" \r\nEND HEADER\r\nBEGIN DSJOB\r\n\ttest "val" \r\nEND DSJOB)
谁能解释一下这是什么意思?好像不能跳过\r\t.
感谢大家的帮助!
问题是您的输入没有像您预期的那样被标记化。这是因为词法分析器匹配尽可能多的输入。因此,如果您查看 PNAME
规则:
PNAME : StringCharacters;
fragment StringCharacter
: ~["\]
;
然后您会注意到输入 "BEGIN HEADER\n CharacterSet "
匹配该规则。
错误信息是这样的:
mismatched input 'BEGIN HEADER\r\n\tCharacterSet ' expecting {, 'BEGIN HEADER', 'BEGIN DSJOB'}
说明:找到了标记 'BEGIN HEADER\r\n\tCharacterSet '
,而解析器需要标记 'BEGIN HEADER'
或 'BEGIN DSJOB'
.
您可能需要添加空格、制表符和换行符 class:~["\ \t\r\n]
(但这由您决定)
此外,词法分析器独立于解析器运行(解析器对生成的标记没有影响)。词法分析器只是简单地尝试匹配尽可能多的字符,每当有两个(或更多)规则匹配相同的字符时,首先定义的规则 "wins"。鉴于此逻辑,则从以下规则:
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]+;
当然,您需要对其进行更改以完全满足您的需要,但这只是一个开始。