1

仍在研究 Antlr,我搜索了一些我在文档中找不到的东西。

这是一个可以检测字符串中的“非”模式的解析器:

 factor : 'not'^ primary| primary;
 (and some other lines).

但是如果我想在我的 primary 之后检测一个表达式怎么办?例如

B exists

如何定义一个解析器规则在我的表达式的其余部分进行搜索?我通过类比尝试了这个,但直到现在才让它工作。

 exists : primary 'exists'^ | primary;

根据我在表达中存在的位置,我得到了

line 1:44 extraneous input 'exists' expecting ')'

或者

line 1:3 mismatched input 'exists' expecting ')'
line 1:22 missing EOF at ')'

错误

谢谢 !

编辑:

我的语法和你的一样,但有一件事。这是我的代码:

// Aiming at parsing a complete BQS formed Query
grammar Logic;

options {
    backtrack=true;
    output=AST;
}

/*------------------------------------------------------------------
 * PARSER RULES
 *------------------------------------------------------------------*/

 parse  
    : expression EOF -> expression
    ; // ommit the EOF token

 expression
    : query
    ;       

 query  
    : term (OR^ term)*    // make `or` the root
    ;

 term   
    : factor (AND^ factor)*
    ;

 factor 
    : NOT^ primary 
    | primary
    ;


 primary // this one has to be completed (a lot)
    : atom (LIKE^ atom)* // right expressions have to be indicated
    | atom (EXISTS^)?
    ;

 atom   
    : ID 
    | '('! expression ')'! // omit both ( and )
    ;

/*------------------------------------------------------------------
 * LEXER RULES
 *------------------------------------------------------------------*/
// GENERAL OPERATORS: 
NOTLIKE :   'notlike'; // whitespaces have been removed
LIKE    :   'like';
EXISTS  :   'exists';

OR          :   'or';
AND         :   'and';
NOT         :   'not';

//ELEMENTS 
ID          :   (CHARACTER)+;   

WHITESPACE : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+    { $channel = HIDDEN; } ;

所以问题显然来自这里。

我虽然在这里有一个严重的问题。在删除所有 or 和 not 之后,我希望我的主要形式是:

A like B

或者

A exists

我的代码有什么问题?我认为这正是我的主要规则所说的?

我真的很想找到一种方法来调试自己,因为:

line 1:3 mismatched input 'like' expecting ')'  

真的不言自明

非常感谢您的帮助,我真的很难理解 antlr 文档网站:s。

4

1 回答 1

3

我怀疑你在你的EOF一个解析器规则中放错了一个。您发布的规则似乎没有太大问题:至少,不会导致您发布的错误。

对于(可能的)未来问题(不仅是 ANTLR 问题),我强烈建议您发布“自包含”的语法(或示例代码)。换句话说:您发布了一个语法,某人可以轻松地在不修改它(!)的情况下在他们自己的机器上运行,这样他们就可以准确地看到您所看到的。现在它只是猜测你的其他规则是什么样的。

以下:

exists
 : atom (Exists^)?
 ;

就像一个魅力,你可以测试自己:

grammar T;

options {
  output=AST;
}

parse
 : expr EOF -> expr
 ;

expr
  :  orexp
  ;

orexp
  :  andexp (Or^ andexp)*
  ;

andexp
  :  not (And^ not)*
  ;

not
 : Not^ exists
 | exists
 ;

exists
 : atom (Exists^)?
 ;

atom
 : Num
 | Id
 | '(' expr ')' -> expr
 ;

Or     : 'or';
And    : 'and';
Exists : 'exists';
Not    : 'not';
Num    : '0'..'9'+;
Id     :  ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
Space  : ' ' {skip();};

输入:

(A or B) and (not C or D exists) or not E exists

产生以下 AST:

在此处输入图像描述

编辑

primary您的规则的备选方案 1 和备选方案 2 :

 primary
  : atom (LIKE^ atom)* // alternative 1
  | atom (EXISTS^)?    // alternative 2
  ;

匹配单个atom. 这是解析器无法正确解析您的输入的原因(并且需要您添加backtrack=true;,应该避免!)。

我没有测试它,但我很确定如果你backtrack=true;从选项块中删除它会起作用,并重写primary如下:

primary
 : atom ( (LIKE^ atom)* // alternative 1
        | EXISTS^       // alternative 2
        )
 ;

现在替代 1 仅匹配单个atom,并且没有歧义(至少,不在规则中)。

于 2012-05-09T18:07:32.067 回答