是否有一个正则表达式来生成某种编程语言的所有整数

时间:2015-03-08 23:13:07

标签: c regex compiler-construction integer

假设我正在构建一个编译器,我希望词法分析器识别C语言的整数,我可以指定例如整数应该在-2,147,483,648和2,147,483,647之间,长整数可以是64位吗?我觉得我的问题很愚蠢,但我想知道它是否可行......谢谢

2 个答案:

答案 0 :(得分:5)

简短回答

是的可以完成,但你那样做!

剧透警告:您最好使用strtol,我会在 long 答案中告诉您原因。

答案很长

使用奇怪的regexp(最糟糕的一个是带有MIN和MAX之间所有整数列表的正则表达式) 可以完成它,但你想要做这样的事情。

这是因为这样的任务意味着对正则表达式进行大量处理,而该测试可以用您喜欢的语言进行很少的处理(将以下内容视为伪代码):

if (str_to_int(s) > CMIN && str_to_int(s) < CMAX)

嗯,实际上你可能会告诉我&#34; 但是如果它是一个int,它会溢出!&#34;。但是有一些技术可以检测到:

并且他们都没有使用正则表达式!

但是,无论如何,当C标准库中已经为您完成这项工作时,您不需要遇到太多麻烦: strtol 功能!引用手册:

  

strtol()函数返回转换结果,除非该值会下溢或溢出。如果发生下溢,strtol()将返回LONG_MIN。如果发生溢出,strtol()将返回LONG_MAX。在这两种情况下,errno都设置为ERANGE。对于strtoll()(LLONG_MIN和LLONG_MAX而不是LONG_MIN和LONG_MAX)也是如此。

为什么它会很大?这是因为正则表达式是一个查看字符流的自动机。当匹配时,您沿着自动机移动。基本上,您需要:

  • 匹配任意10个字符的字符串,或仅当它以-
  • 开头时才匹配
  • 仅包含数字,
  • 如果以2开头,则只能跟01
  • 如果以2开头,后跟1,则只能跟012,{{1 }或3
  • 如果它以4开头,后跟2,然后是1,则只能跟4123 ... 4
  • ...
  • 如果它以7开头,则以...结尾,并以2结尾,但如果它以7开头,然后是-,则需要以2结束(所以基本上你必须将所有先前的条件复制到另一个以该结尾的子图中)
  • ,对于任何其他角色,它都是匹配。

这看起来有点像:

6

由以下自动机直观表示(点击要播放的图像):

Regular expression visualization

我不确定会有多正确,因为我可能错过了边缘情况,但我希望我明确表示它与用你最喜欢的语言做的比较。如果你真的解析了这么大的自动机,它会:

  • 刻录CPU时间,
  • 燃烧电力,
  • 燃烧(燃料|燃煤| gaz |铀),
  • 污染地球,
  • 杀死一个小海豹

所有这些都不是做一些可以在使用正则表达式做同样事情的复杂性的1/100的操作中完成的事情。

cute baby seal

因此,如果您因为编程错误而不想杀死小印章,请不要使用regexp来处理它没有被设计的东西。


资源

为了更好地理解自动机是什么,正则表达式是如何工作的,何时使用它是个好主意,当它是一个小密封杀死它时,我只能建议你看看以下课程:< / p>


这里是@ Andie2302答案的可视化:

strtol

通过匹配的自动机:

Regular expression visualization, click on me to play with me!

还是不相信?

HTH

答案 1 :(得分:1)

这个正则表达式应该有效:

-\b(?:214748364[0-8]|21474836[0-3][0-9]|2147483[0-5][0-9]{2}|214748[0-2][0-9]{3}|21474[0-7][0-9]{4}|2147[0-3][0-9]{5}|214[0-6][0-9]{6}|21[0-3][0-9]{7}|20[0-9]{8}|1[0-9]{9}|[1-9][0-9]{1,8}|[0-9])\b|\b(?:214748364[0-7]|21474836[0-3][0-9]|2147483[0-5][0-9]{2}|214748[0-2][0-9]{3}|21474[0-7][0-9]{4}|2147[0-3][0-9]{5}|214[0-6][0-9]{6}|21[0-3][0-9]{7}|20[0-9]{8}|1[0-9]{9}|[1-9][0-9]{1,8}|[0-9])\b