ANTLR4 - 外来输入,输入时没有可行的替代方案

  • 本文关键字:方案 ANTLR4 antlr4
  • 更新时间 :
  • 英文 :


好吧,在来这里问之前我已经尝试了所有方法,但这让我发疯了。

我正在创建一种简单的语言,用于在自定义 NoSQL 数据库中查询文档。示例查询如下所示:

VALUE("price: " SUM($price) " Average: " AVG($price)).MATCH($price > 5 OR $price < 100 OR $cost > 30)

它是介于SQL和MONGODB的聚合查询之间的东西(VALUE中的参数连接字符串和聚合,匹配中有一个布尔匹配(。

问题是,当我解析它时,我得到的是一行 1:69 无关的输入 ' ' 期望 COMPATOR 后跟一行 1:69 在输入 ' ' 时没有可行的替代方案。第 80-82 行和第 95-97 行也是如此。

如您所见,问题出在比较器("<"、">"等(上。我一直在查找语法中的冲突或歧义,但没有任何运气(诚然,我最近才进入 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 : [ trn]+ -> skip ; // skip spaces, tabs, newlines

到目前为止,我找到的唯一解决方案是更改以下行:

  | (value COMPARATOR value)                    #Comparison

为:

  | (value ' '* COMPARATOR ' '* value)                    #Comparison

但对我来说,看起来更像是一个黑客而不是解决方案......

我错过了什么?我很确定这将是一件非常愚蠢的事情...但我花了一整天的时间都没有运气......

奖励曲目:

(这个不那么重要(我还尝试在布尔查询中允许 calc 表达式(如 5+3> 6 或 $variable+10 <100(,但在这种情况下,当运算符("+"、"-"、...(存在时,完全中断了对比较器(">"、"<"、"...(的期望。

您省略了空格,那么为什么要在语法规则functionValue中匹配' '呢?

删除这些部分,您将获得完整的工作语法(在给定的示例中(,包括计算表达式的正确解析。

现在的规则是:

functionValue : 'VALUE(' (STRING)* functionNumber ((STRING|functionNumber))* ')' (match)?;

玩得开心 ANTLR4,这是一个非常好的工具。

PS:考虑拆分解析器语法和词法分析器语法,它将为您提供两个更好阅读的文件。

他们的标题将是

CapsaParser.g4

parser grammar CapsaParser;
options { tokenVocab = CapsaLexer; }

CapsaLexer.g4

lexer grammar CapsaLexer;

相关内容

  • 没有找到相关文章

最新更新