1

我是一个完全的词法分析器和解析器新手,所以请耐心等待。最终我希望能够表达 LDAP 样式的查询字符串,例如 '(foo=bar)'、'(!foo=bar)'、'(&(foo=bar)(!zip=zap))' 并有一个最后的树,我可以用它来创建实际的数据库查询(或其他)

所以我想从最简单的形式开始,解析 (foo=bar) 和 (!foo=bar) 之类的表达式,但我已经有一些理解问题。我只想表示字段与值之间用'='分隔,但 ANTLR 似乎一次吃掉了所有字符,因为标识符看起来很像一个值。我该怎么做才能防止这种情况发生?

grammar FilterExpression;

options
{
    language=Java;
    k=2;
}

tokens
{
    NOT='!';
}

term    :   '(' NOT? FIELD '=' VALUE ')';
// lexer
FIELD   :   NAME;
VALUE   :   CDATA;

fragment NAME
    :   ALPHA+;
fragment CDATA
    :   ALPHA*;
fragment ALPHA
    :   ('a'..'z' | 'A'..'Z');
4

2 回答 2

2

好的,你在正确的轨道上。只是你需要改变的几件事。您将不得不在解析器中而不是在词法分析器中表达字段名称字段值,因为词法分析器无法区分这两者之间的区别。拥有多个使用相同片段的 Lexer 表达式使得 Lexer 很难(不可能!)确定您想要其中的哪一个。将这两个(名称和值)的确定移到解析器中会非常容易。要使可选,只需将该解析器术语设为可选(后面带有“?”)。有关使用修改后的语法生成的解析树,请参见下文(希望这是您所追求的)。我还在我的答案底部为您粘贴了修改后的语法。
替代文字 http://img268.imageshack.us/img268/7374/graphw.png

grammar FilterExpression;

options
{
    language=Java;
    k=2;
}

tokens
{
    NOT='!';
}

term    :       '(' NOT? field '=' value? ')';
// lexer
field   :       ID;
value   :       ID;

ID  :   ALPHA+
    ;

fragment ALPHA
    :   ('a'..'z' | 'A'..'Z');
于 2009-07-30T06:18:11.427 回答
0

如果字段和值都是标识符,其中标识符是字母字符的非空字符串(允许值为空,如您的示例中所示),您可以执行以下操作:

term    :       '(' NOT? field '=' value ')';

field : IDENTIFIER ;

value : IDENTIFIER? ;

// lexer
IDENTIFIER : ALPHA+ ;

fragment ALPHA
    :   ('a'..'z' | 'A'..'Z');

由于词法分析器无法从值中区分字段,因此您需要让词法分析器将它们视为相同,并使用解析器根据上下文来区分差异。

于 2009-06-26T14:43:45.340 回答