ANTLR解析字符串丢失字符?

时间:2015-09-30 03:22:03

标签: grammar antlr4

我有以下语法

grammar Lucene;  
/*  
 * Parser Rules  
 */  
query           : orExpr WHITESPACE* NEWLINE? EOF  
                ;  
orExpr          : expr ((ORTOKEN | SPACE)? expr)*   /* or exp */  
                ;  
expr            : LPAREN orExpr RPAREN                  /* grouping */  
                | expr ANDTOKEN expr                    /* and exp */  
                | expr NOTTOKEN expr                    /* not exp */  
                | required  
                | prohibited  
                | proximity  
                | fuzzy  
                | boosted  
                | phrase  
                | term  
                ;  
proximity       : phrase TILDE INT  
                ;  
fuzzy           : term TILDE FLOAT?  
                ;  
boosted         : (term | phrase) ACCENT (FLOAT | INT)  
                ;  
required        : PLUSTOKEN WHITESPACE? term  
                ;  
prohibited      : MINUSTOKEN WHITESPACE? term  
                ;  
term            : (ALPHANUM+ ( '*' | '?' )? ALPHANUM*)  
                ;  
phrase          : '"' ( ~'\\"' | . )*? '"'   
                ;  
/*  
 * Lexer Rules  
 */  
ALPHANUM        : CHARACTER  
                | NUM  
                ;  
CHARACTER       : 'a'..'z'  
                | 'A'..'Z'  
                ;  
FLOAT           : NUM* '.' NUM+  
                ;  
INT             : NUM+  
                ;  
NUM             : '0'..'9'  
                ;  
LPAREN          : '('  
                ;  
RPAREN          : ')'  
                ;  
ANDTOKEN        : ' AND '  
                ;  
NOTTOKEN        : ' NOT '  
                | ' !'  
                ;  
ORTOKEN         : ' OR '  
                ;  
PLUSTOKEN       : '+'  
                ;  
MINUSTOKEN      : '-'  
                ;  
TILDE           : '~'  
                ;  
ACCENT          : '^'  
                ;  
SPACE           : ' '  
                ;  
CR              : '\r'  
                | '\n'  
                ;  
WHITESPACE      : ( SPACE | '\t' ) -> skip ;  
NEWLINE         : ('\r'?'\n'|'\r') -> skip;  

目的是使用短语规则处理字符串文字,但是当字符串包含“。”等字符时或“:”我在检查TestRig时遇到以下错误(使用java org.antlr.v4.gui.TestRig Lucene query -gui):

line 1:15 token recognition error at: '. '    
line 1:28 token recognition error at: ':'    
[@0,0:0='"',<9>,1:0]    
[@1,1:1='P',<4>,1:1]    
[@2,2:2='r',<4>,1:2]    
[@3,3:3='o',<4>,1:3]    
[@4,4:4='v',<4>,1:4]    
[@5,5:5='i',<4>,1:5]    
[@6,6:6='d',<4>,1:6]    
[@7,7:7='e',<4>,1:7]    
[@8,8:8='d',<4>,1:8]    
[@9,9:9=' ',<19>,1:9]    
[@10,10:10='t',<4>,1:10]    
[@11,11:11='e',<4>,1:11]    
[@12,12:12='r',<4>,1:12]    
[@13,13:13='m',<4>,1:13]    
[@14,14:14='s',<4>,1:14]    
[@15,17:17='F',<4>,1:17]    
[@16,18:18='o',<4>,1:18]    
[@17,19:19='r',<4>,1:19]    
[@18,20:20=' ',<19>,1:20]    
[@19,21:21='e',<4>,1:21]    
[@20,22:22='x',<4>,1:22]    
[@21,23:23='a',<4>,1:23]    
[@22,24:24='m',<4>,1:24]    
[@23,25:25='p',<4>,1:25]    
[@24,26:26='l',<4>,1:26]    
[@25,27:27='e',<4>,1:27]    
[@26,29:29=' ',<19>,1:29]    
[@27,30:30='a',<4>,1:30]    
[@28,31:31='t',<4>,1:31]    
[@29,32:32='e',<4>,1:32]    
[@30,33:33='r',<4>,1:33]    
[@31,34:34='m',<4>,1:34]    
[@32,35:35='"',<9>,1:35]    
[@33,38:37='<EOF>',<-1>,2:0]

知道为什么会出现上述错误吗?

当字符丢失时,点后面有字符而不是空格会变得更糟。

2015年10月10日更新

已修复:我修正了更新短语规则的问题(通过@GRosengberg进行了一些推荐的更改,但并非所有语法都没有按预期工作)

phrase  
                : LITERAL  
                ;  

LITERAL  
                : '"' ( '\\"' | .)*? '"'
                ;  

其中给出了期望的结果,也更新了语法以接受其余的规则,后来我改变了初始规则来解决运算符优先级问题,但现在我得到了相互左递归错误。冲突的规则如下:

expr            : orExpr
                | andExpr
                | prohibited
                | required
                | boosted
                | fuzzy
                | spanNear
                | proximity
                | term 
                | phrase
                | groupExpr
                ;

orExpr          : expr ((WS+ | WS+ OR WS+) orExpr)+
                | expr
                ;

andExpr         : expr (WS+ AND WS+ andExpr)+
                | expr (WS+ notExpr)+
                | expr
                ;

notExpr         : NOT WS+ expr
                ;

有关如何解决此问题的任何想法?我已经为orExpr和andExpr分离了规则,因为我使用它们来轻松地识别我正在写的访问者的这些规则。

1 个答案:

答案 0 :(得分:0)

这个有点清理的版本应该有所帮助,但看起来你需要更多的时间来使用文档。强烈建议您使用TDAR。

grammar Lucene;

query   : expr+ EOF ;
expr    : LPAREN orExpr RPAREN  /* grouping */
        | expr ANDTOKEN expr    /* and exp */
        | expr NOTTOKEN expr    /* not exp */
        | expr ORTOKEN expr     /* or exp */
        | required
        | prohibited
        | proximity
        | fuzzy
        | boosted
        | phrase
        | term
        ;

proximity   : phrase TILDE INT ;
fuzzy       : term TILDE FLOAT? ;
boosted     : (term | phrase) ACCENT (FLOAT | INT) ;
required    : PLUSTOKEN term ;
prohibited  : MINUSTOKEN term ;
term        : alphanum+ ( STAR | QMARK )? alphanum* ;
alphanum    : CHARACTER | NUM ;
phrase      : STRING ;

ANDTOKEN    : ' AND ' ;
NOTTOKEN    : ' NOT ' | ' !' ;
ORTOKEN     : ' OR ' ;
FLOAT       : NUM* '.' NUM+ ;
INT         : NUM+ ;
STRING      : '"' .*? '"' ;

WHITESPACE  : [ \t\r\n]+ -> skip;

CHARACTER   : 'a'..'z' | 'A'..'Z' ;
NUM         : '0'..'9' ;
LPAREN      : '(' ;
RPAREN      : ')' ;
PLUSTOKEN   : '+' ;
MINUSTOKEN  : '-' ;
STAR        : '*' ;
QMARK       : '?' ;
BANG        : '!' ;
TILDE       : '~' ;
ACCENT      : '^' ;

简化expr规则以包含or变体 - 可能会遇到左递归问题,并将其分开。

如果将alphanum保留为词法分析器规则(ALPHANUM),则解析器只能看到ALPHANUM标记 - 解析器永远不会看到任何离散的CHARACTER和NUM标记。

同样,由于你在词法分析器中跳过WHITESPACE,解析器永远不会看到这些标记 - 它们不能用于解析器规则。

字符串规则(STRING)的rhs必须是词法规则。对于测试,您可以添加仅引用字符串规则的解析器规则。