代码之家  ›  专栏  ›  技术社区  ›  Jason

Antlr4语法意外错误(C++目标)

  •  1
  • Jason  · 技术社区  · 6 年前

    我使用的是Antlr 4.7.1的C++目标,某些输入字符串会触发意外错误。

    不按原样使用语法文件分析的字符串:

    keys abc-def;
    

    给出的错误:

    Line(1:5) Error(mismatched input 'abc-def' expecting {KEY_NAME_PATTERN, STRING_LITERAL})
    

    奇怪的是,如果我在语法文件中交换KEY\u NAME\u IDENTIFIER和KEY\u NAME\u PATTERN的规则位置,那么上面的字符串解析为ok,但下面的字符串现在失败了(没有交换规则位置就通过了):

    get key abc-def;
    

    所以我怀疑Antlr中有一个bug,但我不能百分之百确定。

    语法文件:

    grammar ModelKeyValue;
    
    start : keyvalue_statements ;
    
    keyvalue_statements: ( del_statement | get_statement | set_statement | keys_statement ) ';'
        ;
    
    del_statement:
        KEYWORD_DEL key_name
        ;
    
    get_statement:
        KEYWORD_GET key_name
        ;
    
    set_statement:
        KEYWORD_SET key_name literal_value
        ;
    
    keys_statement:
        KEYWORD_KEYS key_name_pattern
        ;
    
    keyword:
        KEYWORD_DEL
        | KEYWORD_GET
        | KEYWORD_SET
        | KEYWORD_KEYS
        ;
    
    key_name:
        KEY_NAME_IDENTIFIER
        | STRING_LITERAL
        ;
    
    key_name_pattern:
        KEY_NAME_PATTERN
        | STRING_LITERAL
        ;
    
    literal_value:
        STRING_LITERAL
        ;
    
    KEYWORD_DEL: D E L;
    KEYWORD_GET: G E T;
    KEYWORD_SET: S E T;
    KEYWORD_KEYS: K E Y S;
    
    KEY_NAME_IDENTIFIER: ([a-z]|[A-Z]|[0-9]|'!'|'@'|'#'|'$'|':'|'-')+;
    
    KEY_NAME_PATTERN: ([a-z]|[A-Z]|[0-9]|'!'|'@'|'#'|'$'|':'|'-'|'_'|'%')+;
    
    STRING_LITERAL:
        '\'' ( ~'\'' | '\'\'' )* '\''
        | '"' ('\\' ~('\r' | '\n') | ~('\\' | '"'| '\r' | '\n'))* '"'
        ;
    
    fragment A: [aA];
    fragment B: [bB];
    fragment C: [cC];
    fragment D: [dD];
    fragment E: [eE];
    fragment F: [fF];
    fragment G: [gG];
    fragment H: [hH];
    fragment I: [iI];
    fragment J: [jJ];
    fragment K: [kK];
    fragment L: [lL];
    fragment M: [mM];
    fragment N: [nN];
    fragment O: [oO];
    fragment P: [pP];
    fragment Q: [qQ];
    fragment R: [rR];
    fragment S: [sS];
    fragment T: [tT];
    fragment U: [uU];
    fragment V: [vV];
    fragment W: [wW];
    fragment X: [xX];
    fragment Y: [yY];
    fragment Z: [zZ];
    
    WS: [ \t\r\n]+ -> skip ;
    

    如果有人可以验证此问题或建议解决方案,这将非常有帮助,谢谢。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Bart Kiers    6 年前

    不,这不是一个bug。您误解了标记化的工作方式。它是这样的:每当有2个(或更多)规则匹配相同数量的字符时,如 KEY_NAME_IDENTIFIER KEY_NAME_PATTERN 对于输入 keys abc-def; ,首先定义的规则为“wins”。lexer不会“监听”解析器(就像无扫描解析器一样)。这是无法避免的。

    要修复它,只需包括 KEY\u NAME\u标识符 在您的 key_name_pattern 生产:

    key_name_pattern
     : KEY_NAME_IDENTIFIER
     | KEY_NAME_PATTERN
     | STRING_LITERAL
     ;