ANTLR 语法行 1:6 不匹配的输入 '<EOF>' 期待 '.'
ANTLR Grammar line 1:6 mismatched input '<EOF>' expecting '.'
我在玩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));
输出正常,这意味着 "name" 实际上是从 json 中检索到的,但是有一个我无法解释的警告:
line 1:6 mismatched input '<EOF>' expecting '.'
我读到我需要在我的起始规则中明确添加一个 EOF 规则 (dnot
),但这似乎不起作用。
知道我能做什么吗?
您的输入 $.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)?
;
另外,[]
、'[?('
等标记看起来很可疑。我不太熟悉对象路径,但是通过将这些字符相互粘合,这样的输入 [ ]
([
和 ]
由 space 分隔)不会匹配 []
。所以如果 foo[ ]
是有效的,我会这样写:
select : ID '[' ']' #selectAll
| ...
并跳过词法分析器中的 spaces:
SPACES : [ \t\r\n]+ -> skip;
我在玩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));
输出正常,这意味着 "name" 实际上是从 json 中检索到的,但是有一个我无法解释的警告:
line 1:6 mismatched input '<EOF>' expecting '.'
我读到我需要在我的起始规则中明确添加一个 EOF 规则 (dnot
),但这似乎不起作用。
知道我能做什么吗?
您的输入 $.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)?
;
另外,[]
、'[?('
等标记看起来很可疑。我不太熟悉对象路径,但是通过将这些字符相互粘合,这样的输入 [ ]
([
和 ]
由 space 分隔)不会匹配 []
。所以如果 foo[ ]
是有效的,我会这样写:
select : ID '[' ']' #selectAll
| ...
并跳过词法分析器中的 spaces:
SPACES : [ \t\r\n]+ -> skip;