我有一个关于我语法的小问题。 我想解析字符串,如下所示:
"(ICOM LIKE '%bridge%' or ICOM LIKE '%Munich%')"
我最终得到了以下语法(比我所知道的要复杂一点):
//旨在解析一个完整的BQS格式的Query
grammar Logic;
options {
output=AST;
}
tokens {
NOT_LIKE;
}
/*------------------------------------------------------------------
* PARSER RULES
*------------------------------------------------------------------*/
// precedence order is (low to high): or, and, not, [comp_op, geo_op, rel_geo_op, like, not like, exists], ()
parse
: expression EOF -> expression
; // ommit the EOF token
expression
: query
;
query
: term (OR^ term)* // make `or` the root
;
term
: factor (AND^ factor)*
;
factor
: (notexp -> notexp) ( NOT LIKE e=notexp -> ^(NOT_LIKE $factor $e))?
;
notexp
: NOT^ like
| like
;
like // this one has to be completed (a lot)
: atom (LIKE^ atom)*
;
atom
: ID
| | '(' expression ')' -> expression
;
/*------------------------------------------------------------------
* LEXER RULES
*------------------------------------------------------------------*/
// GENERAL OPERATORS:
//NOTLIKE : 'notlike' | 'NOTLIKE'; // whitespaces have been removed
LIKE : 'like' | 'LIKE';
OR : 'or' | 'OR';
AND : 'and' | 'AND';
NOT : 'not' | 'NOT';
//ELEMENTS
CONSTANT_EXPRESSION : DATE | NUMBER | QUOTED_STRING;
ID : (CHARACTER|DIGIT)+;
WHITESPACE : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ { $channel = HIDDEN; } ;
fragment DATE : '\'' YEAR '/' MONTH '/' DAY (' ' HOUR ':' MINUTE ':' SECOND)? '\'';
fragment QUOTED_STRING : '\'' (CHARACTER)+ '\'' ;
//UNITS
fragment CHARACTER : ('a'..'z' | 'A'..'Z'|'.'|'\''|'%'); // FIXME: Careful, should be all ASCII
fragment DIGIT : '0'..'9' ;
fragment DIGIT_SEQ :(DIGIT)+;
fragment DEL : SPACE ',' SPACE ; //Delimiter + may be space behind
fragment NUMBER : (SIGN)? DIGIT_SEQ ('.' (DIGIT_SEQ)?)?; // should be given in decimal degrees, North is 0 and direction is clockwise, range is 0 to 360
fragment SIGN : '+' | '-';
fragment YEAR : DIGIT DIGIT DIGIT DIGIT;
fragment MONTH : DIGIT DIGIT;
fragment DAY : DIGIT DIGIT;
fragment HOUR : DIGIT DIGIT;
fragment MINUTE : DIGIT DIGIT;
fragment SECOND : DIGIT (DIGIT)? ('.' (DIGIT)+)?;
fragment SPACE : (' ')?;// used to increase compatibility
事情是,我在创建 AST 时收到此消息:
line 1:11 no viable alternative at input ''%bridge%''
line 1:35 no viable alternative at input ''%Munich%''
虽然生成的树是正确的(至少就我而言是这样):
那么,有人能给我一些提示,告诉我那里出了什么问题吗?我认为字符包含正确解析此表达式所需的所有额外字符。 . .
谢谢!
像往常一样,一些Java代码来快速测试语法:
import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;
public class Main {
public static void main(String[] args) throws Exception {
// the expression
String src = "(ICOM LIKE '%bridge%' or ICOM LIKE '%Munich%')";
// create a lexer & parser
//LogicLexer lexer = new LogicLexer(new ANTLRStringStream(src));
//LogicParser parser = new LogicParser(new CommonTokenStream(lexer));
LogicLexer lexer = new LogicLexer(new ANTLRStringStream(src));
LogicParser parser = new LogicParser(new CommonTokenStream(lexer));
// invoke the entry point of the parser (the parse() method) and get the AST
CommonTree tree = (CommonTree)parser.parse().getTree();
// print the DOT representation of the AST
DOTTreeGenerator gen = new DOTTreeGenerator();
StringTemplate st = gen.toDOT(tree);
System.out.println(st);
}
}
最佳答案
我看到 3 个问题:
1
您的 atom
规则匹配 epsilon(无):
atom
: ID
| | '(' expression ')' -> expression
;
(注意 | |
中的“虚无”)
导致你的语法有歧义。我想应该是:
atom
: ID
| '(' expression ')' -> expression
;
2
您的 fragment CHARACTER
匹配一个单引号,而这个单引号也表示 fragment QUOTED_STRING
的结尾。
我想 CHARACTER
应该是这样的:
fragment CHARACTER : ('a'..'z' | 'A'..'Z' | '.' | '%');
3
在您的解析器规则中没有任何地方与标记 CONSTANT_EXPRESSION
匹配,因此您发布的 AST 永远不可能由根据您发布的语法生成的解析器创建。我假设您希望像这样在 atom
规则中匹配它:
atom
: ID
| CONSTANT_EXPRESSION
| '(' expression ')' -> expression
;
通过上面概述的更改,我得到了以下 AST,没有任何错误被打印到控制台:
关于java - 输入时没有可行的替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10614659/