编写Lex规则来解析Integer和Float

时间:2013-10-09 12:50:58

标签: parsing lex

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

我需要识别stringsintegersfloats

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

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

但是我在识别Integers和Floats时遇到了问题。这些是我写的(错误的)规则:

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

我该如何修复它们?

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

1 个答案:

答案 0 :(得分:4)

第一个问题:(...)[...]之间存在差异。你的正则表达式不符合你的想法,因为你使用了错误的标点符号。

除此之外:

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

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

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

  4. 所以,开始:

    [...]包含单个字符或字符范围的。它匹配单个字符,它是集合的成员。

    (...)包含正则表达式。括号用于分组,如数学中那样。

    "..."包含单个字符的序列,并且恰好与这些字符匹配。

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

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

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

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

    最后,{DIGIT}匹配名称DIGIT的扩展。我假设你有这个定义:

    DIGIT   [0-9]
    

    在定义部分的某处。 (顺便说一句,我注意到你可能刚刚使用了明确的字符类[:digit:],你不需要定义它。)接下来是*,这意味着它会匹配{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的所有内容。但是,它也会匹配123,您可能希望将其与数字规则匹配。这里,其他(f)lex匹配标准发挥作用:当有两个或更多规则可以完全匹配相同的字符串,并且没有规则可以匹配更长的字符串时,(f)lex首先选择规则在文件中。因此,如果您希望将数字优先于字符串,则必须将数字规则放在(f)lex文件中,而不是字符串规则。

    4. 我希望能为您提供有关如何解决问题的一些想法。