我正在使用antlr4语法文件,我想编写自己的jsonpath语法。
我想出了这个
grammar ObjectPath;
objectPath : dnot;
dnot : ROOT expr ('.' expr)
| EOF
;
expr : select #selectExpr
| ID #idExpr
;
select : ID '[]' #selectAll
| ID '[' INT ']' #selectIndex
| ID '[' INT (',' INT)* ']' #selectIndexes
| ID '[' INT ':' INT ']' #selectRange
| ID '[' INT ':]' #selectFrom
| ID '[:' INT ']' #selectUntil
| ID '[-' INT ':]' #selectLast
| ID '[?(' query ')]' #selectQuery
;
query : expr (AND|OR) expr # andOr
| ALL # all
| QPREF ID # prop
| QPREF ID GT INT # gt
| QPREF ID LT INT # lt
| QPREF ID EQ INT # eq
| QPREF ID GTE INT # gte
| QPREF ID LTE INT # lte
;
/** Lexer **/
ROOT : '$.' ;
QPREF : '@.' ;
ID : [a-zA-Z][a-zA-Z0-9]* ;
INT : '0' | [1-9][0-9]* ;
AND : '&&' ;
OR : '||' ;
GT : '>' ;
LT : '<' ;
EQ : '==' ;
GTE : '>=' ;
LTE : '<=' ;
ALL : '*' ;
在一个简单的表达式上运行它之后
CharStream input = CharStreams.fromString("$.name");
ObjectPathLexer lexer = new ObjectPathLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
ObjectPathParser parser = new ObjectPathParser(tokens);
ParseTree parseTree = parser.dnot();
ObjectPathDefaultVisitor visitor = ...
System.out.println(visitor.visit(parseTree));
System.out.println(parseTree.toStringTree(parser));
输出正常,这意味着实际上是从json中检索到“名称”,但是有一个警告我无法解释:
line 1:6 mismatched input '<EOF>' expecting '.'
我已阅读到我需要显式地将EOF规则添加到我的开始规则(dnot
)中,但这似乎不起作用。
任何想法我该怎么办?
答案 0 :(得分:4)
您的输入$.name
无法用您的规则进行解析:
dnot : ROOT expr ('.' expr)
| EOF
;
$.name
产生2个令牌:
ROOT
ID
但是您的第一个选择ROOT expr ('.' expr)
期望2个表达式之间用.
分隔。也许您打算将第二个expr设为可选,例如:
dnot : ROOT expr ('.' expr)*
| EOF
;
通常在启动规则的末尾添加EOF
,以强制解析器使用所有令牌。就像您现在所做的那样,解析器成功解析了ROOT expr
,但随后无法进一步解析,并产生了您看到的警告(期望为'。')。
由于objectPath
似乎是您的开始规则,所以我认为这是您想要做的:
objectPath : dnot EOF;
dnot : ROOT expr ('.' expr)?
;
此外,像这样的标记[]
,'[?('
等看起来也是可疑的。我对对象路径不是很熟悉,但是通过将这些字符相互粘合,像这样的输入[ ]
([
和]
用空格隔开)将不会与{ {1}}。因此,如果[]
有效,我可以这样写:
foo[ ]
并跳过词法分析器中的空格:
select : ID '[' ']' #selectAll
| ...