2012-09-10 61 views
1

我知道这已经被讨论了几千次,但我仍然无法弄清楚为什么遵循语法失败。在解释器中一切正常,没有任何错误或警告。但是,当运行生成的代码时,我会得到不匹配的输入,如下所示。Antlr 3.4.0生成解析器和解释器中不匹配的输入

对于这个语法:

grammar xxx; 

options { 
    language = Java; 
    output = AST; 
} 

@members { 
    @Override 
    public String getErrorMessage(RecognitionException e, 
    String[] tokenNames) 
    { 
     List stack = getRuleInvocationStack(e, this.getClass().getName()); 
     String msg = null; 
     if (e instanceof NoViableAltException) { 
      NoViableAltException nvae = (NoViableAltException)e; 
      msg = " no viable alt; token="+e.token+ 
      " (decision="+nvae.decisionNumber+ 
      " state "+nvae.stateNumber+")"+ 
      " decision=<<"+nvae.grammarDecisionDescription+">>"; 
     } 
     else { 
      msg = super.getErrorMessage(e, tokenNames); 
     } 
     return stack+" "+msg; 
    } 

    @Override 
    public String getTokenErrorDisplay(Token t) { 
     return t.toString(); 
    } 
} 

obj 
     : first=subscription 
     (COMMA other=subscription)* 
     ; 

subscription 
     : ID 
     (EQUALS arguments_in_brackets)? 
     filters 
     ; 

arguments_in_brackets 
     : LOPAREN arguments ROPAREN 
     ; 

arguments 
     : (arguments_body) 
     ; 

arguments_body 
     : argument (arguments_more)? 
     ; 

arguments_more 
     : SEMICOLON arguments_body 
     ; 

argument 
    : id_equals argument_body 
    ; 

argument_body 
    : STRING 
    | INT 
    | FLOAT 
    ; 

filters 
     : LSPAREN expression RSPAREN 
     ; 

expression 
     : or 
     ; 

or 
    : first=and 
    (OR^ second=and)* 
    ; 

and  : first=atom 
    (AND^ second=atom)* 
    ; 

atom 
    : filter 
    | atom_expression 
    ; 

atom_expression 
    : LCPAREN 
    expression 
    RCPAREN 
    ; 

filter 
    : id_equals arguments_in_brackets 
    ; 

id_equals 
    : WS* ID WS* EQUALS WS* 
    ; 

COMMA: WS* ',' WS*; 
LCPAREN : WS* '(' WS*; 
RCPAREN : WS* ')' WS*; 
LSPAREN : WS* '[' WS*; 
RSPAREN : WS* ']' WS*; 
LOPAREN : WS* '{' WS*; 
ROPAREN : WS* '}' WS*; 
AND: WS* 'AND' WS*; 
OR: WS* 'OR' WS*; 
NOT: WS* 'NOT' WS*; 
EQUALS: WS* '=' WS*; 
SEMICOLON: WS* ';' WS*; 

ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* 
    ; 

INT : '0'..'9'+ 
    ; 

FLOAT 
    : ('0'..'9')+ '.' ('0'..'9')* EXPONENT? 
    | '.' ('0'..'9')+ EXPONENT? 
    | ('0'..'9')+ EXPONENT 
    ; 

// : '"' (ESC_SEQ | ~('\\'|'"'))* '"' 
// : '"' (~'"')* '"' 
STRING 
    : '"' (~'"')* '"' 
    ; 

fragment 
EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ; 

fragment 
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ; 

fragment 
ESC_SEQ 
    : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\') 
    | UNICODE_ESC 
    | OCTAL_ESC 
    ; 

fragment 
OCTAL_ESC 
    : '\\' ('0'..'3') ('0'..'7') ('0'..'7') 
    | '\\' ('0'..'7') ('0'..'7') 
    | '\\' ('0'..'7') 
    ; 

fragment 
UNICODE_ESC 
    : '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT 
    ; 

NEWLINE: '\r'? '\n' {skip();} ; 

WS:  (' '|'\t')+ {skip();} ; 

而且此输入:

status={name="Waiting";val=5}[ownerEmail1={email="[email protected]"} OR internalStatus={status="New"}],comments={type="fds"}[(internalStatus={status="Owned"} AND ownerEmail2={email="[email protected]"}) OR (role={type="Contributor"} AND status={status="Closed"})] 

我越来越:

line 1:67 [obj, subscription, filters, expression, or, and, atom, filter, arguments_in_brackets] mismatched input [@18,67:80='internalStatus',<11>,1:67] expecting ROPAREN 
line 1:157 [obj, subscription, filters, expression, or, and, atom, atom_expression, expression, or, and, atom, filter, arguments_in_brackets] mismatched input [@42,157:167='ownerEmail2',<11>,1:157] expecting ROPAREN 

能有人给我任何线索这是为什么失败,请?我试图用很多方式重写它,但错误仍然是一样的。

回答

1

问题是,您在其他词法分析器规则中使用WS标记,因此会跳过这些标记。这会导致词法分析器完全丢弃这些标记,因此不能用于解析器规则。

所以,如果你有这样一个规则:

WS : ' ' {skip();}; 

,然后在NOT使用这样的规则:

NOT : WS* 'NOT' WS*; 

它会导致NOT令牌一并跳过。

如果您已经跳过这些WS字符,你不需要它们包括在其他词法规则:只要删除所有WS*其他规则:

... 
NOT : 'NOT'; 
... 

(也来自解析器中删除规则:无论如何,词法分析器规则中的所有skip单词令牌都不可用!)

+0

你完全正确,非常感谢Bart。 – user1394066

+0

@ user1394066,不客气。忘了提及这一点:从不过分依赖解释器:它忽略了几乎所有的嵌入代码(这就是为什么'skip()'在大多数情况下不会在解释器中调用,而且它似乎工作!)。 –

+0

对,这解释了解释和生成代码中的不同结果,再次非常感谢。 – user1394066