我正在尝试构建一个解释用户输入文本,搜索引擎样式的语法.它将支持AND,OR,NOT和ANDNOT布尔运算符.我几乎所有工作都有效,但是我想添加一个规则,即在带引号的字符串之外的两个相邻关键字被隐含地视为AND子句.例如:
奶酪和饼干=奶酪和饼干
(上下)或(左和右)=(上下)或(左和右)
猫狗"大肚猪"=猫与狗和"大肚猪"
我遇到了最后一个问题,我希望有人可以指出我正确的方向.到目前为止,这是我的*.g文件,请保持良好,我的ANTLR体验不到一个工作日:
grammar SearchEngine;
options { language = CSharp2; output = AST; }
@lexer::namespace { Demo.SearchEngine }
@parser::namespace { Demo.SearchEngine }
LPARENTHESIS : '(';
RPARENTHESIS : ')';
AND : ('A'|'a')('N'|'n')('D'|'d');
OR : ('O'|'o')('R'|'r');
ANDNOT : ('A'|'a')('N'|'n')('D'|'d')('N'|'n')('O'|'o')('T'|'t');
NOT : ('N'|'n')('O'|'o')('T'|'t');
fragment CHARACTER : ('a'..'z'|'A'..'Z'|'0'..'9');
fragment QUOTE : ('"');
fragment SPACE : (' '|'\n'|'\r'|'\t'|'\u000C');
WS : (SPACE) { $channel=HIDDEN; };
PHRASE : (QUOTE)(CHARACTER)+((SPACE)+(CHARACTER)+)+(QUOTE);
WORD : (CHARACTER)+;
startExpression : andExpression;
andExpression : andnotExpression (AND^ andnotExpression)*;
andnotExpression : orExpression (ANDNOT^ orExpression)*;
orExpression : notExpression (OR^ notExpression)*;
notExpression : (NOT^)? atomicExpression;
atomicExpression : PHRASE | WORD | LPARENTHESIS! andExpression RPARENTHESIS!;
Run Code Online (Sandbox Code Playgroud)
由于您的AND规则具有可选的AND关键字,因此您应该创建一个虚构的AND标记,并使用重写规则在树中"注入"该标记.在这种情况下,您无法使用ANTLR的短手^根运算符.你必须使用->重写操作符.
你andExpression应该看起来像:
andExpression
: (andnotExpression -> andnotExpression)
(AND? a=andnotExpression -> ^(AndNode $andExpression $a))*
;
Run Code Online (Sandbox Code Playgroud)
有关这个(可能是神秘的)符号的详细描述,请参见 Terence Parr 的The Definitive ANTLR Reference第173-174页第7章" 重写子规则"一节.
我跑了一个快速测试,看看语法是否用新andExpression规则产生了正确的AST .解析字符串后cat dog "potbelly and pig" and FOO,生成的解析器生成以下AST:
alt text http://img580.imageshack.us/img580/7370/andtree.png
注意,AndNode和Root是虚构的标记.
如果您想知道如何创建上面的AST图片,请参阅此主题:可视化使用ANTLR创建的AST(在.Net环境中)
编辑
当解析既one two three和(one two) three,将创建下列AST:
alt text http://img203.imageshack.us/img203/2558/69551879.png
解析时(one two) OR three,会创建以下AST:
替代文字http://img340.imageshack.us/img340/8779/73390353.png
在所有情况下,这似乎是正确的方式.
| 归档时间: |
|
| 查看次数: |
550 次 |
| 最近记录: |