代码之家  ›  专栏  ›  技术社区  ›  Taras Velykyy

在antlr4中处理可选令牌的最佳方法是什么

  •  1
  • Taras Velykyy  · 技术社区  · 7 年前

    假设我有以下输入:

    Great University
    Graduated in 2010
    Some University
    09/2009 - 06/2011
    Nice University
    06/2011
    

    我想应付多年的学习。我的语法是这样的:

    education:
        (section)*
        EOF
        ;
    
    section:
        (school | years)+
       ;
    
    degree:     WORD* DEGREE WORD* SEPARATOR;
    years:      WORD* ( (YEAR_START '-')? YEAR_END) WORD* SEPARATOR;
    WS          : [ \t\r]+ -> skip;
    SEPARATOR   : (NEWLINE | COMMA);
    COMMA       : ',';
    NEWLINE     : '\n';
    SCHOOL      : ('university' | 'University' | 'school' | 'School');
    WORD        : [a-zA-Z'()]+;
    YEAR_START  : YEAR;
    YEAR_END    : YEAR;
    YEAR        : (DIGIT DIGIT '/')? [1-2] DIGIT DIGIT DIGIT;
    DIGIT       : [0-9];
    

    我收到以下错误:

    line 1:17 mismatched input '\n' expecting '-'
    line 6:17 mismatched input '\n' expecting '-'
    

    如何通过语法处理可选的开始年份?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Joshua Schwartz CoronA    4 年前

    lexer只能将一种令牌类型分配给一种模式。您希望它为三种令牌类型分配一个年份模式,并在运行时决定哪一种是正确的。这不是ANTLR的工作方式。

    在您的情况下,所有年份(不仅是可选年份)都将被第一条规则捕获,即。 YEAR_START . 这意味着遵循标记化

    "Graduated in 2010" -> WORD WORD YEAR_START
    

    唯一匹配的规则是

     years:      WORD* ( (YEAR_START '-')? YEAR_END) WORD* SEPARATOR;
    

    但缺少“-”。

    如果删除 YEAR\u开始 YEAR_END 规则并将所有引用替换为 YEAR . 可能 YEAR\u开始 年末 目的是区分开始和结束,但为此目的存在标签。

    如果这不起作用,请张贴完整的语法;您发布的内容不包含规则,例如 DEGREE .