我正在使用 ANTLR 来解析搜索查询输入,例如:
年龄>25
或
名字:“约翰”
树通常看起来像这样:
我想添加对 IN 运算符和数组值的支持,以便能够解析如下查询:
名字 IN [“jane”,“joe”]
我尝试在我的值规则中添加数组的语法规则。
array
: LBRACKET (value (COMMA value)* )? RBRACKET
;
value
: array
| IDENTIFIER
| STRING
| ENCODED_STRING
| NUMBER
| BOOL
;
问题在于解析器将数组本身识别为 ENCODED_STRING。
名字 IN [“约翰”,“简”]
这是我的完整语法文件
grammar Query;
// syntactic rules
input
: query EOF
;
query
: left=query logicalOp=(AND | OR) right=query #opQuery
| LPAREN query RPAREN #priorityQuery
| criteria #atomQuery
;
criteria
: key op value
;
key
: IDENTIFIER
;
array
: LBRACKET (value (COMMA value)* )? RBRACKET
;
value
: array
| IDENTIFIER
| STRING
| ENCODED_STRING
| NUMBER
| BOOL
;
op
: EQ
| GT
| LT
| NOT_EQ
| IN
| NOT_IN
;
// lexical rules
BOOL
: 'true'
| 'false'
;
STRING
: '"' DoubleStringCharacter* '"'
| '\'' SingleStringCharacter* '\''
;
fragment DoubleStringCharacter
: ~["\\\r\n]
| '\\' EscapeSequence
| LineContinuation
;
fragment SingleStringCharacter
: ~['\\\r\n]
| '\\' EscapeSequence
| LineContinuation
;
fragment EscapeSequence
: CharacterEscapeSequence
| HexEscapeSequence
| UnicodeEscapeSequence
;
fragment CharacterEscapeSequence
: SingleEscapeCharacter
| NonEscapeCharacter
;
fragment HexEscapeSequence
: 'x' HexDigit HexDigit
;
fragment UnicodeEscapeSequence
: 'u' HexDigit HexDigit HexDigit HexDigit
;
fragment SingleEscapeCharacter
: ['"\\bfnrtv]
;
fragment NonEscapeCharacter
: ~['"\\bfnrtv0-9xu\r\n]
;
fragment EscapeCharacter
: SingleEscapeCharacter
| DecimalDigit
| [xu]
;
fragment LineContinuation
: '\\' LineTerminatorSequence
;
fragment LineTerminatorSequence
: '\r\n'
| LineTerminator
;
fragment DecimalDigit
: [0-9]
;
fragment HexDigit
: [0-9a-fA-F]
;
fragment OctalDigit
: [0-7]
;
fragment POINT
: '.'
;
AND
: 'AND'
;
OR
: 'OR'
;
NUMBER
: ('0' .. '9') ('0' .. '9')* POINT? ('0' .. '9')*
;
LPAREN
: '('
;
RPAREN
: ')'
;
LBRACKET
: '['
;
RBRACKET
: ']'
;
GT
: '>'
;
LT
: '<'
;
EQ
: ':'
;
IN
: 'IN'
;
NOT_IN
: 'NOT IN'
;
NOT_EQ
: '!'
;
COMMA
: ','
;
IDENTIFIER
: [A-Za-z0-9.]+
;
ENCODED_STRING
: ~([ :<>!()])+
;
LineTerminator
: [\r\n\u2028\u2029] -> channel(HIDDEN)
;
WS
: [ \t\r\n]+ -> skip
;