ANTLR 解析键值列表
ANTLR parse key value list
我是 ANTLR 的新手,我正在尝试解析类似
的东西
ref:something title:(别的东西) blah ref other
并获得一个像
这样的列表
- KEY = ref VALUE = something
- KEY = 标题 VALUE = 其他内容
- KEY = null VALUE = blah
- KEY = null VALUE = ref // 与项目 1 键相同的 ref 字符串
- KEY = null VALUE = 其他
我的语法是
searchCriteriaList
locals[List<object> s = new List<object>()]
: t+=criteriaBean (WS t+=criteriaBean)* { $s.addAll($t); }
;
criteriaBean : (KEY ':' WS* expression)
| expression ;
expression : '(' WORD (WS WORD)* ')'
| WORD ;
/*
* Lexer Rules
*/
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 LOWERCASE : [a-z] ;
fragment UPPERCASE : [A-Z] ;
TITLE : T I T L E ;
MESSAGE : M E S S A G E ;
REF : R E F ;
KEY : TITLE | MESSAGE | REF ;
WORD : (LOWERCASE | UPPERCASE | '_')+ ;
WS : [ \t\u000C\r\n] ;
当我尝试解析字符串时出现 2 个异常,并且在 addAll 方法中我最终得到 3 个元素而不是 5 个。
有人能指出我正确的方向吗?我做错了什么?
谢谢,
S
PS:我得到的异常是:
Exception of type 'Antlr4.Runtime.InputMismatchException' was thrown.
InputStream: {ref:something title:(something else) blah ref other }
OffendingToken: {[@0,0:2='ref',<5>,1:0]}
词法分析器在构造标记时尝试匹配尽可能多的字符。当 2 个或多个 lexer 规则匹配相同的字符时,第一个定义的规则 "wins"。考虑到这一点,将永远不会创建 KEY
令牌,因为 TITLE
、MESSAGE
和 REF
是在其上方定义的:
TITLE : T I T L E ;
MESSAGE : M E S S A G E ;
REF : R E F ;
KEY : TITLE | MESSAGE | REF ;
WORD : (LOWERCASE | UPPERCASE | '_')+ ;
所以输入ref
将总是成为REF
标记,从不成为KEY
或 WORD
。您需要做的是从 KEY
创建一个解析器规则。
此外,由于您希望 WORD
也匹配您的关键字,因此您不应该这样做:
expression
: '(' WORD (WS WORD)* ')'
| WORD
;
而是这样的:
expression
: '(' word (WS word)* ')'
| word
;
word
: key
| WORD
;
key
: TITLE
| MESSAGE
| REF
;
哦,还有这个:
fragment Z : ('Z'|'z') ;
可以改写为:
fragment Z : [Zz] ;
您在解析器规则中乱放 WS
标记是否有特殊原因?您可以在标记化期间删除它们:
WS : [ \t\u000C\r\n] -> skip;
我是 ANTLR 的新手,我正在尝试解析类似
的东西ref:something title:(别的东西) blah ref other
并获得一个像
这样的列表- KEY = ref VALUE = something
- KEY = 标题 VALUE = 其他内容
- KEY = null VALUE = blah
- KEY = null VALUE = ref // 与项目 1 键相同的 ref 字符串
- KEY = null VALUE = 其他
我的语法是
searchCriteriaList
locals[List<object> s = new List<object>()]
: t+=criteriaBean (WS t+=criteriaBean)* { $s.addAll($t); }
;
criteriaBean : (KEY ':' WS* expression)
| expression ;
expression : '(' WORD (WS WORD)* ')'
| WORD ;
/*
* Lexer Rules
*/
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 LOWERCASE : [a-z] ;
fragment UPPERCASE : [A-Z] ;
TITLE : T I T L E ;
MESSAGE : M E S S A G E ;
REF : R E F ;
KEY : TITLE | MESSAGE | REF ;
WORD : (LOWERCASE | UPPERCASE | '_')+ ;
WS : [ \t\u000C\r\n] ;
当我尝试解析字符串时出现 2 个异常,并且在 addAll 方法中我最终得到 3 个元素而不是 5 个。 有人能指出我正确的方向吗?我做错了什么?
谢谢, S
PS:我得到的异常是:
Exception of type 'Antlr4.Runtime.InputMismatchException' was thrown.
InputStream: {ref:something title:(something else) blah ref other }
OffendingToken: {[@0,0:2='ref',<5>,1:0]}
词法分析器在构造标记时尝试匹配尽可能多的字符。当 2 个或多个 lexer 规则匹配相同的字符时,第一个定义的规则 "wins"。考虑到这一点,将永远不会创建 KEY
令牌,因为 TITLE
、MESSAGE
和 REF
是在其上方定义的:
TITLE : T I T L E ;
MESSAGE : M E S S A G E ;
REF : R E F ;
KEY : TITLE | MESSAGE | REF ;
WORD : (LOWERCASE | UPPERCASE | '_')+ ;
所以输入ref
将总是成为REF
标记,从不成为KEY
或 WORD
。您需要做的是从 KEY
创建一个解析器规则。
此外,由于您希望 WORD
也匹配您的关键字,因此您不应该这样做:
expression
: '(' WORD (WS WORD)* ')'
| WORD
;
而是这样的:
expression
: '(' word (WS word)* ')'
| word
;
word
: key
| WORD
;
key
: TITLE
| MESSAGE
| REF
;
哦,还有这个:
fragment Z : ('Z'|'z') ;
可以改写为:
fragment Z : [Zz] ;
您在解析器规则中乱放 WS
标记是否有特殊原因?您可以在标记化期间删除它们:
WS : [ \t\u000C\r\n] -> skip;