代码之家  ›  专栏  ›  技术社区  ›  Grundlefleck anujkk

javacc警告“正则表达式选择:foo永远不能匹配为:bar”的解释和解决方案?

  •  5
  • Grundlefleck anujkk  · 技术社区  · 15 年前

    我正在教自己在业余项目中使用javacc,并有一个简单的语法来为其编写语法分析器。解析器的一部分包括以下内容:

    TOKEN : { < DIGIT : (["0"-"9"]) > }
    TOKEN : { < INTEGER : (<DIGIT>)+ > }
    TOKEN : { < INTEGER_PAIR : (<INTEGER>){2} > }
    TOKEN : { < FLOAT : (<NEGATE>)? <INTEGER> | (<NEGATE>)? <INTEGER>  "." <INTEGER>  | (<NEGATE>)? <INTEGER> "." | (<NEGATE>)? "." <INTEGER> > } 
    TOKEN : { < FLOAT_PAIR : (<FLOAT>){2} > }
    TOKEN : { < NUMBER_PAIR : <FLOAT_PAIR> | <INTEGER_PAIR> > }
    TOKEN : { < NEGATE : "-" > }
    

    使用javacc编译时,我得到输出:

    Warning: Regular Expression choice : FLOAT_PAIR can never be matched as : NUMBER_PAIR
    
    Warning: Regular Expression choice : INTEGER_PAIR can never be matched as : NUMBER_PAIR
    

    我确信这是一个简单的概念,但我不理解警告,因为我是解析器生成和正则表达式的新手。

    这个警告是什么意思(在新手中,你可以得到条件)?

    4 回复  |  直到 15 年前
        1
  •  4
  •   Barry Kelly    15 年前

    我不认识Javacc,但我是一名编译工程师。

    这个 FLOAT_PAIR 规则不明确。请考虑以下文本:

    0.0
    

    这可能是 FLOAT 0 然后 FLOAT .0 或者可能是 FLOAT 0. 然后 浮标0 ;两者都会导致float_对。或者是一个浮球 0.0 .

    更重要的是,尽管如此,你使用的词法分析和作文的方式是不可能奏效的。考虑这个数字:

    12345
    

    这可以被解析为 INTEGER 12, INTEGER 345 导致一个 INTEGER_PAIR . 或者它可以被解析为 INTEGER 123, INTEGER 45 另一个 整数对 . 或者它可能是 INTEGER 12345 ,另一个标记。这个问题的存在是因为您不需要在 整数对 (或) 浮子对 )

    在lexer中,您几乎不应该尝试处理这样的对。相反,您应该处理普通数字( INTEGER FLOAT )作为标记,并在解析器中处理诸如否定和配对之类的事情,在解析器中处理和剥离了空白。

    (例如,您将如何处理 "----42" ?在大多数编程语言中,这是一个有效的表达式,可以正确地计算多个负数,但不能由lexer处理。)

    另外,请注意,lexer中的单个数字整数将不匹配为 整数 ,它们将以 DIGIT . 不过,我不知道Javacc的正确语法可以为您修复这个问题。你想要的是定义 数字 不是作为令牌,而是简单地在其他令牌的定义中使用;或者,嵌入 数字 ( [0-9] )无论您在何处使用 数字 在你的规则中。

        2
  •  0
  •   Uri    15 年前

    我没有使用javacc,但数字对可能不明确。

    我认为问题归结于这样一个事实:同样精确的东西可以与float_对和integer_对同时匹配,因为float可以与integer匹配。

    但这只是一个从未见过javacc语法的猜测:)

        3
  •  0
  •   sth    15 年前

    这可能意味着每一个 FLOAT_PAIR 你只会得到一个 浮子对 令牌,从来没有 NUMBER_PAIR 令牌。这个 浮子对 规则已经与所有输入匹配,Javacc不会尝试查找进一步的匹配规则。那是我的解释,但我不认识贾瓦克,所以拿它来加点盐吧。

    也许你可以指定 数字对 是主要产品,您不希望获得任何其他令牌作为结果。

        4
  •  0
  •   Grundlefleck anujkk    15 年前

    由于巴里·凯利的回答,我想到的解决方案是:

        SKIP : { < #TO_SKIP : " " | "\t" > }
        TOKEN : { < #DIGIT : (["0"-"9"]) > }
        TOKEN : { < #DIGITS : (<DIGIT>)+ > }
        TOKEN : { < INTEGER : <DIGITS> > }
        TOKEN : { < INTEGER_PAIR : (<INTEGER>) (<TO_SKIP>)+ (<INTEGER>) > }
        TOKEN : { < FLOAT : (<NEGATE>)?<DIGITS>"."<DIGITS> | (<NEGATE>)?"."<DIGITS> > } 
        TOKEN : { < FLOAT_PAIR : (<FLOAT>) (<TO_SKIP>)+ (<FLOAT>) > }
        TOKEN : { < #NUMBER : <FLOAT> | <INTEGER> > }
        TOKEN : { < NUMBER_PAIR : (<NUMBER>) (<TO_SKIP>)+ (<NUMBER>) >}
        TOKEN : { < NEGATE : "-" > }
    

    我完全忘了包括用于分隔两个令牌的空间,我还使用了“”符号,它停止了令牌的匹配,并且只在其他令牌的定义中使用。以上由javacc编译,没有警告或错误。

    然而,正如巴里所指出的,有理由不这么做。