首页 > 解决方案 > 正则表达式意外模式匹配

问题描述

我正在尝试使用 C-Bison 和 Flex 创建语法解析器。在 Flex 中,我有一个正则表达式,它根据以下内容匹配整数:

  1. 必须以 1-9 范围内的任意数字开头,后跟 0-9 范围内的任意数字。(例如,正确:1,12,11024 | 错误:012)

  2. 可以签名(例如+2,-5)

  3. 数字 0 后面不能跟任何数字 (0-9),也不能有符号。(例如,正确:0 | 不正确:012,+0,-0)

这是我为执行匹配而创建的正则表达式: [^+-]0[^0-9]|[+-]?[1-9][0-9]*

这是我正在测试的表达式: (1 + 1 + 10)

比赛:

1
1
10)

这是我的问题,为什么它匹配'10)'?

我使用上述表达式而不是更简单的表达式 (0|[+-]?[1-9][0-9]*) 的原因是解析器无法识别不正确的表达式,例如 012。

问题似乎只发生在“)”之前的数字“0”之前。但是,如果 '0' 前面有两个或多个数字(例如 100),则 ')' 不匹配。

我知道如果我从正则表达式中删除 [^0-9] 它与')'不匹配。

标签: cregexbisonflex-lexer

解决方案


它匹配,10(因为1匹配[^+-]0匹配0(匹配[^0-9]

我使用上述表达式而不是更简单的表达式 (0|[+-]?[1-9][0-9]*) 的原因是解析器无法识别不正确的表达式,例如 012。

怎么会这样?使用上面的正则表达式,012将被识别为两个标记:012. 这不会导致您的解析器出错吗?

诚然,这不会产生非常好的错误消息,因此更好的方法可能是仅用[0-9]+作正则表达式,然后使用该操作来检查前导零。这种方式012将是一个单一的标记,词法分析器可能会产生关于前导零的错误或警告(我在这里假设您实际上想要禁止前导零 - 不要将它们用于八进制文字)。

除了检查操作,您还可以保留您的正则表达式,然后为带有前导零的整数添加另一个(如0[0-9]+ { warn("Leading zero"); return INT; }),但我会在操作中进行检查,因为它很容易检查并且它保留了正则表达式简短而简单。

PS:如果你制作了整数标记-+一部分,类似的东西2+3将被视为整数2,然后是整数+3,而不是整数2,并且3中间有一个+标记。因此,通常最好不要将符号作为整数标记的一部分,而是在解析器中允许前缀+和运算符。-


推荐阅读