好的,在来这里之前我已经尝试了一切,但这让我发疯了。
我正在创建一种简单的语言来查询自定义NoSQL数据库中的文档。示例查询如下所示:
VALUE("price: " SUM($price) " Average: " AVG($price)).MATCH($price > 5 OR $price < 100 OR $cost > 30)
这是SQL和MONGODB的聚合查询之间的中间位置(VALUE中的参数连接字符串和聚合,在匹配中有一个布尔匹配)。
问题是,当我解析这个时,我得到一个行1:69无关输入''期望比较,然后是行1:69没有可行的替代输入' “即可。对于行80-82和95-97,这是相同的。
正如您所看到的,问题出在比较器周围('&lt;','&gt;'等)。我一直在寻找没有运气的冲突或含糊不清的语法(诚然,我最近刚刚进入ANTLR)。
这是我的语法:
// Define a grammar called Capsa
grammar Capsa;
eval : VARIABLE | function;
function : functionValue;
functionValue : 'VALUE(' (STRING ' ')* functionNumber (' '(STRING|functionNumber))* ')' (match)?;
match : '.MATCH(' booleanexpression ')';
functionNumber: FUNCTIONNUMBERTYPE'(' value ')';
FUNCTIONNUMBERTYPE: 'SUM'|'AVG'|'MAX'|'MIN'|'FIRST'|'LAST' ;
value
: VARIABLE #Var
| REALNUMBER #Literal
| STRING #Literal
| calcexpression #Calc
| booleanValue #Literal;
/*
** Boolean stuff
*/
AND : '&&' | ' AND ';
OR : '||' | ' OR ';
NOT : '!' | ' NOT ';
booleanexpression : '(' booleanexpression ')' #BooleanParentExpression
| booleanexpression AND booleanexpression #AndExpression
| booleanexpression OR booleanexpression #OrExpression
| NOT booleanexpression #NotExpression
| (value COMPARATOR value) #Comparison
| booleanValue #ComparisonLogic;
booleanValue
: 'true'
| 'false';
/*
** Comparators
*/
fragment GT : '>';
fragment GTE : '>=';
fragment LT : '<';
fragment LTE : '<=';
fragment EQ : '=';
fragment EX : ':' | '==';
COMPARATOR : GT | GTE | LT | LTE | EQ | EX;
/*
** End Comparators
*/
/*
** End Boolean stuff
*/
/*
** Calc
*/
calcexpression
: '(' calcexpression ')' #CalcParentExpression
| calcexpression ('*'|'/') calcexpression #MultOrDiv
| calcexpression ('+'|'-') calcexpression #AddOrSub
| VARIABLE #CalcID
| REALNUMBER #CalcNumber;
/*
** End Calc
*/
fragment ID : [a-zA-Z_][a-zA-Z0-9_]+ ;
VARIABLE : '$'ID;
STRING : '"' (ESC | ~["\\])* '"' ;
fragment CONSTANT : STRING | REALNUMBER;
fragment ESC : '\\' (["\\/bfnrt] | UNICODE) ;
fragment UNICODE : 'u' HEX HEX HEX HEX ;
fragment HEX : [0-9a-fA-F] ;
fragment INT : [0-9]+ ; // no leading zeros
fragment EXP : [Ee] [+\-]? INT ; // \- since - means "range" inside [...]
REALNUMBER
: '-'? INT '.' INT EXP? // 1.35, 1.35E-9, 0.3, -4.5
| '-'? INT EXP // 1e10 -3e4
| '-'? INT // -3, 45
;
WS : [ \t\r\n]+ -> skip ; // skip spaces, tabs, newlines
到目前为止,我发现的唯一解决方案是更改说明的行:
| (value COMPARATOR value) #Comparison
有:
| (value ' '* COMPARATOR ' '* value) #Comparison
但看起来更像是黑客而不是解决方案......
我错过了什么?我很确定这会是一件非常愚蠢的事情......但是我已经花了一整天没有运气......
奖励跟踪:
(这个并不重要) 我也试图在布尔查询中允许calc表达式(例如5 + 3> 6或$ variable + 10&lt; 100),但在这种情况下,完全期待比较器('&gt;','&lt; ',...),当运算符('+',' - ',...)出现时。
答案 0 :(得分:1)
您省略了空格,那么为什么要在语法规则' '
中匹配functionValue
?
删除这些部分,你会得到一个完整的工作语法(在你给出的例子中),包括正确解析计算表达式。
规则现在是:
functionValue : 'VALUE(' (STRING)* functionNumber ((STRING|functionNumber))* ')' (match)?;
享受ANTLR4的乐趣,这是一个非常好的工具。
PS:考虑分割你的解析器语法和词法分析器语法,它会给你两个更好阅读的文件。
他们的标题将是
<强> CapsaParser.g4 强>
parser grammar CapsaParser;
options { tokenVocab = CapsaLexer; }
<强> CapsaLexer.g4 强>
lexer grammar CapsaLexer;