1

我正在为脚本语言编写解析。

我需要识别strings和。integersfloats

我成功地使用规则识别字符串:

[a-zA-Z0-9_]+ {return STRING;}

但我在识别整数和浮点数时遇到问题。这些是我写的(错误的)规则:

["+"|"-"][1-9]{DIGIT}*  { return INTEGER;}
["+"|"-"]["0." | [1-9]{DIGIT}*"."]{DIGIT}+ {return FLOAT;}

我该如何修复它们?

此外,由于“ abc123 ”是有效字符串,我如何确保它被识别为字符串而不是字符串(“ abc”)和整数(“ 123”)的串联?

4

1 回答 1

4

(...)第一个问题:和之间有区别[...]。您的正则表达式没有按照您的想法执行,因为您使用了错误的标点符号。

除此之外:

  1. 没有数字规则识别0.

  2. 两个数字规则都需要一个明确的符号。

  3. 您的 STRING 规则可以识别整数。

所以,开始:

[...]包含一组单独字符或字符范围。它匹配作为集合成员的单个字符。

(...)包含一个正则表达式。括号用于分组,就像在数学中一样。

"..."包含一系列单个字符,并与这些字符完全匹配。

考虑到这一点,让我们看看

["+"|"-"][1-9]{DIGIT}*

第一个括号表达式["+"|"-"]是一组单独的字符或范围。在这种情况下,集合包含:", +, "(同样,它没有效果,因为集合包含每个成员的零个或一个实例)|和范围"- ",它是一个端点是相同字符的范围,因此只有包括该字符,",它已经在集合中。简而言之,这相当于["+|]. 它将匹配这三个字符之一。事实上,它需要这三个字符之一。

第二个括号表达式[1-9]匹配范围内的一个字符1- 9,因此它可能符合您的预期。同样,它只匹配一个字符。

最后,{DIGIT}匹配 name 的扩展DIGIT。我假设您有以下定义:

DIGIT   [0-9]

在你的定义部分的某个地方。(顺便说一句,我注意到您可以只使用字符类[:digit:],这将是明确的,并且您不需要定义它。)它后面是 a *,这意味着它将匹配零个或多个重复{DIGIT}定义。

现在,一个匹配该模式的字符串示例:

|42

还有一些与该模式不匹配的字符串示例:

-7   # The pattern must start with |, + or "
42   # Again, the pattern must start with |, + or "
+0   # The character following the + must be in the range [0-9] 

同样,一旦[...]简化了表达式,您的浮动模式就会变成(每行写出一个单独的部分,以使其更明显):

["+|]      # i.e. the set " + |
["0.|[1-9] # i.e. the set " 0 | [ 1 2 3 4 5 6 7 8 9
{DIGIT}*   # Any number of digits
"."        # A single period
]          # A single ]
{DIGIT}+   # one or more digits

所以这是一个可能的匹配:

"..]3

我将跳过写出解决方案,因为我认为你会从自己做的事情中受益更多。

现在,其他问题:

  1. 一些规则应该匹配0。如果您不想允许前导零,则只需将它作为单独的规则。

  2. 使用可选运算符 ( ?) 表示前面的对象是可选的。例如。"foo"?匹配三个字符f, o, o(按顺序)或匹配空字符串。您可以使用它来使标志可选。

  3. 问题不abc123在于您的问题中的匹配。(F)lex 总是给你尽可能长的匹配,唯一可以匹配起始字符a的规则是字符串规则,所以它会允许字符串规则尽可能长地继续。它将始终匹配所有abc123. 但是,它也将 match 123,您可能希望与您的数字规则匹配。在这里,另一个 (f)lex 匹配标准开始发挥作用:当有两个或多个规则可以匹配完全相同的字符串,并且没有一个规则可以匹配更长的字符串时,(f)lex 选择第一个规则文件。因此,如果您想让数字优先于字符串,您必须在 (f)lex 文件中将数字规则放在比字符串规则更早的位置。

我希望这能给你一些关于如何解决问题的想法。

于 2013-10-09T23:54:11.467 回答