JavaCC警告的解释和解决方案"正则表达式选择:FOO永远不能匹配为:BAR"?

Gru*_*eck 5 regex parsing javacc

我正在教自己在业余爱好项目中使用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 : "-" > }
Run Code Online (Sandbox Code Playgroud)

使用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
Run Code Online (Sandbox Code Playgroud)

我确定这是一个简单的概念,但我不理解这个警告,在解析器生成和正则表达式中都是新手.

这个警告意味着什么(在新手即可获得的条款中)?

Bar*_*lly 4

我不懂JavaCC,但我是一名编译器工程师。

FLOAT_PAIR规则含糊不清。考虑以下文本:

0.0
Run Code Online (Sandbox Code Playgroud)

FLOAT 0接下来可以是FLOAT .0FLOAT 0.或者后面可以是FLOAT 0; 两者都会产生 FLOAT_PAIR。或者它可以是单个 FLOAT0.0

但更重要的是,您正在以一种永远不可能起作用的方式使用词法分析和组合。考虑这个数字:

12345
Run Code Online (Sandbox Code Playgroud)

这可以被解析为INTEGER 12, INTEGER 345产生一个INTEGER_PAIR. 或者它可以被解析为INTEGER 123, INTEGER 45,另一个INTEGER_PAIR。或者它可能是INTEGER 12345另一个令牌。问题的存在是因为您不需要INTEGER_PAIR( 或FLOAT_PAIR) 的词汇元素之间有空格。

您几乎不应该尝试在词法分析器中处理这样的对。相反,您应该将普通数字(INTEGERFLOAT)作为标记来处理,并在解析器中处理诸如否定和配对之类的事情,其中​​空格已被处理和剥离。

(例如,你将如何处理"----42"?这是大多数编程语言中的有效表达式,它将正确计算多个否定,但您的词法分析器不会处理。)

另外,请注意词法分析器中的个位数整数不会匹配为INTEGER,它们将显示为DIGIT。不过,我不知道 JavaCC 的正确语法可以为您解决这个问题。您想要的不是定义DIGIT为令牌,而只是可以在其他令牌的定义中使用的东西;或者,无论您在规则中使用什么位置,都可以直接嵌入DIGIT( )的定义。[0-9]DIGIT