1

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

对于这个语法:

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="dsa@fdsf.ds"} OR internalStatus={status="New"}],comments={type="fds"}[(internalStatus={status="Owned"} AND ownerEmail2={email="dsa@fds.ds"}) 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

有人可以给我任何线索,为什么会失败?我尝试以多种方式重写它,但错误仍然相同。

4

1 回答 1

1

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

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

WS : ' ' {skip();};

然后在NOT

NOT : WS* 'NOT' WS*;

它也会导致NOT令牌被跳过。

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

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

(也从解析器规则中删除它们:skip来自词法分析器的所有 ped 标记在解析器规则中永远不可用!)

于 2012-09-11T07:49:45.953 回答