ANTLR解析键值列表

时间:2018-03-20 14:44:25

标签: parsing antlr antlr4

我是ANTLR的新手,我正在尝试解析像

这样的东西

参考:标题:(别的)blah ref other

并获取类似

的列表
  1. KEY = ref VALUE = something
  2. KEY = title VALUE =其他
  3. KEY = null VALUE = blah
  4. KEY = null VALUE = ref //与项目1键相同的参考字符串
  5. KEY = null VALUE = other
  6. 我的语法是

    searchCriteriaList 
        locals[List<object> s = new List<object>()]
               : t+=criteriaBean (WS t+=criteriaBean)* { $s.addAll($t); }
               ;
    
    criteriaBean : (KEY ':' WS* expression)
                 | expression ;
    
    expression  : '(' WORD (WS WORD)* ')'
                | WORD ;
    
    /*
     * Lexer Rules
     */
    
    fragment A  : ('A'|'a') ;
    fragment B  : ('B'|'b') ;
    fragment C  : ('C'|'c') ;
    fragment D  : ('D'|'d') ;
    fragment E  : ('E'|'e') ;
    fragment F  : ('F'|'f') ;
    fragment G  : ('G'|'g') ;
    fragment H  : ('H'|'h') ;
    fragment I  : ('I'|'i') ;
    fragment J  : ('J'|'j') ;
    fragment K  : ('K'|'k') ;
    fragment L  : ('L'|'l') ;
    fragment M  : ('M'|'m') ;
    fragment N  : ('N'|'n') ;
    fragment O  : ('O'|'o') ;
    fragment P  : ('P'|'p') ;
    fragment Q  : ('Q'|'q') ;
    fragment R  : ('R'|'r') ;
    fragment S  : ('S'|'s') ;
    fragment T  : ('T'|'t') ;
    fragment U  : ('U'|'u') ;
    fragment V  : ('V'|'v') ;
    fragment W  : ('W'|'w') ;
    fragment X  : ('X'|'x') ;
    fragment Y  : ('Y'|'y') ;
    fragment Z  : ('Z'|'z') ;
    
    
    fragment LOWERCASE  : [a-z] ;
    fragment UPPERCASE  : [A-Z] ;
    
    TITLE   : T I T L E ;
    MESSAGE : M E S S A G E ;
    REF     : R E F ;
    
    KEY     : TITLE | MESSAGE | REF ;
    WORD    : (LOWERCASE | UPPERCASE | '_')+ ;
    WS      : [ \t\u000C\r\n] ;
    

    当我尝试解析字符串时,我得到2个异常,而在addAll方法中,我得到3个元素而不是5个元素。 有人能指出我正确的方向吗?我做错了什么?

    谢谢, 小号

    PS:我得到的例外是:

    Exception of type 'Antlr4.Runtime.InputMismatchException' was thrown.
    InputStream: {ref:something title:(something else) blah ref other }
    OffendingToken: {[@0,0:2='ref',<5>,1:0]}
    

1 个答案:

答案 0 :(得分:0)

词法分析器在构造标记时尝试匹配尽可能多的字符。当2个或更多lexer规则匹配相同的字符时,首先定义的规则为“wins”。考虑到这一点,永远不会创建KEY令牌,因为TITLEMESSAGEREF定义在它之上:

TITLE   : T I T L E ;
MESSAGE : M E S S A G E ;
REF     : R E F ;

KEY     : TITLE | MESSAGE | REF ;
WORD    : (LOWERCASE | UPPERCASE | '_')+ ;

因此,输入ref始终成为REF令牌,永远不会成为KEYWORD 。您需要做的是从KEY创建一个解析器规则。

此外,由于您希望WORD也匹配您的关键字,因此您不应该这样做:

expression
 : '(' WORD (WS WORD)* ')'
 | WORD 
 ;

但是这样的话:

expression
 : '(' word (WS word)* ')'
 | word 
 ;

word
 : key
 | WORD
 ;

key
 : TITLE
 | MESSAGE
 | REF
 ;

哦,这个:

fragment Z  : ('Z'|'z') ;

可以改写为:

fragment Z  : [Zz] ;

是否有一个特殊原因导致您使用WS令牌乱丢您的解析器规则?你可以在标记化过程中删除它们:

WS      : [ \t\u000C\r\n] -> skip;