ANTLR 解析字符串丢失字符?

ANTLR parsing string losing characters?

我有以下语法

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 查询 -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]

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

当点后有字符而不是 space 时,情况会变得更糟,因为字符丢失了。

2015 年 7 月 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 的规则分开,因为我使用它们可以轻松识别我正在编写的访问者的这些规则。

这个稍微清理过的版本应该有所帮助,但看起来您需要更多时间来阅读文档。强烈建议获取 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) 的右侧必须在词法分析器规则中。为了进行测试,您可以添加一个仅引用字符串规则的解析器规则。