假设我正在构建一个编译器,并且希望词法分析器能够识别C语言的整数,例如,我可以指定整数应在–2,147,483,648和2,147,483,647之间,即长整数可以是64位吗?我觉得我的问题很愚蠢,但我想知道这是否可行...谢谢
最佳答案
简短答案
是的,可以这样做,但您不应该这样做!
剧透警报:您最好使用strtol
,我要告诉您为什么长答案。
长答案
可以使用怪异的regexp(最差的一个是regexp,其中包含MIN和MAX之间的所有整数的列表)来完成此操作,但是您不想这样做。
这是因为这样的任务将意味着对regexp进行大量处理,而该测试可以用您喜欢的语言进行很少的处理(将以下内容视为伪代码):
if (str_to_int(s) > CMIN && str_to_int(s) < CMAX)
好吧,实际上您可能会告诉我“但是,如果它是一个整数,它将溢出!”。但是有一些技术可以检测到这一点:
How to detect integer overflow?
他们都没有使用正则表达式!
但是无论如何,当C标准库中已经有一个可以为您完成此工作的函数时,您就不必麻烦那么大了:
strtol
函数!引用手册:strtol()函数返回转换结果,除非该值下溢或上溢。如果发生下溢,strtol()返回LONG_MIN。如果发生溢出,strtol()返回LONG_MAX。在这两种情况下,errno都设置为ERANGE。对于strtoll()完全相同(使用LLONG_MIN和LLONG_MAX代替LONG_MIN和LONG_MAX)。
为什么会如此庞大?这是因为正则表达式是看着字符流的自动机。有比赛时,您沿自动机移动。基本上,您需要:
匹配任何10个字符的字符串,或者仅以
-
开头的字符串匹配11个字符串只包含数字,
如果它以
2
开头,则只能跟随0
或1
,如果它以
2
开头,然后是1
,则只能跟随0
,1
,2
,3
或4
如果它以
2
开头,然后是1
然后是4
,则只能跟随1
,2
,3
,4
……
如果它以
7
开头,后跟…并以2
结尾,但是如果它以7
开头,然后是-
,则必须以2
结尾(所以基本上必须将所有先前的条件复制到另一个以该条件结尾的子图中)对于其他任何字符,这都是匹配项。
看起来有点像以下内容:
^(
(
\d|\d\d|\d\d\d|\d\d\d\d|\d\d\d\d\d|\d\d\d\d\d\d|
\d\d\d\d\d\d\d|\d\d\d\d\d\d\d\d|\d\d\d\d\d\d\d\d\d|
[0-2][0-1][0-4][0-7][0-4][0-8][0-3][0-6][0-4][0-8]
)|
-(
\d|\d\d|\d\d\d|\d\d\d\d|\d\d\d\d\d|\d\d\d\d\d\d|
\d\d\d\d\d\d\d|\d\d\d\d\d\d\d\d|\d\d\d\d\d\d\d\d\d|
[0-2][0-1][0-4][0-7][0-4][0-8][0-3][0-6][0-4][0-7]
)
)$
它由以下自动机直观地表示(单击图像进行播放):
我不确定这样做的正确性,因为我可能错过了一些极端的案例,但是我希望我能弄清楚它与用您喜欢的语言进行比较时的效果。如果您实际上解析了如此巨大的自动机,它将:
消耗CPU时间
燃烧电,
燃烧(燃料|煤|天然气|铀),
污染地球
杀死海豹
所有这些,而不是做某事所能做的事情,而这是使用正则表达式做同一件事的复杂性的1/100。
因此,如果您不希望由于编程错误而杀死小海豹,请不要对尚未设计好的内容使用正则表达式。
资源资源
为了更好地理解什么是自动机,正则表达式是如何工作的,何时使用它是一个好主意以及何时将其密封住,我只能建议您看以下课程:
http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-045j-automata-computability-and-complexity-spring-2011/lecture-notes/MIT6_045JS11_lec04.pdf
http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-005-elements-of-software-construction-fall-2011/lecture-notes/MIT6_005F11_lec05.pdf
http://www.saylor.org/site/wp-content/uploads/2012/01/CS304-2.1-MIT.pdf
关于该主题的另一个答案:How to find all possible regex matches in python?
关于
6
边缘情况的好答案:Does strtol("-2147483648", 0, 0) overflow if LONG_MAX is 2147483647?这是@ Andie2302的答案的可视化效果:
-\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]|-0
)\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]|-0
)\b
通过其匹配的自动机:
还是不服气?
高温超导
关于c - 是否有正则表达式生成某种编程语言的所有整数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28933020/