Regex 在lex/flex中标记化int与float
为了好玩,我在教自己一点flex/bison。我正在为1975年版本的MS Extended BASIC(扩展为“has strings”)编写一个解释器。不过有一个问题让我有点困惑 可以通过查找Regex 在lex/flex中标记化int与float,regex,lex,Regex,Lex,为了好玩,我在教自己一点flex/bison。我正在为1975年版本的MS Extended BASIC(扩展为“has strings”)编写一个解释器。不过有一个问题让我有点困惑 可以通过查找或E(等)来识别浮动,然后故障转移到int,否则。所以我做了这个 [0-9]*[0-9.][0-9]*([Ee][-+]?[0-9]+)? { yylval.d = atof(yytext); return FLOA
或E
(等)来识别浮动,然后故障转移到int,否则。所以我做了这个
[0-9]*[0-9.][0-9]*([Ee][-+]?[0-9]+)? {
yylval.d = atof(yytext);
return FLOAT;
}
[0-9]+ {
yylval.i = atoi(yytext);
return INT;
}
yylval联合中的子字段是.d表示double,.i表示int,.s表示string
但也可能需要使用浮点,因为数字太大,无法存储在int中,在本例中,int是16位有符号的
在正则表达式中有这样做的方法吗?或者我必须在与if关联的c端代码中执行此操作吗?对于许多编程语言,整数和浮点数的文本是相同的。例如,Java语言规范(以及其他一些规范)包含internet和浮点文本的语法规则。在这些规则中,
0
不作为浮点文本进行验证。这是我看到的你目前方法的主要问题
解析时,不应使用atoi或atof,因为它们不会检查错误。改用strtoul和strtod
整数的操作应为:
if strtoul succeeds:
if the number is less than 0x8000:
llval.i = number
return INT
strtod must succeed
llval.d = number
return FLOAT
如果希望integer优先于float(因此看起来像integer的文本就是integer),那么需要将integer模式放在第一位。(匹配最长的模式始终获胜,但如果两个模式都匹配相同的最长前缀,则第一个模式获胜。)因此,您的基本轮廓是:
integer-pattern { /* integer rule */ }
float-pattern { /* float rule */ }
您的浮点规则看起来合理,但请注意,它将匹配单个
,后面可能跟一个指数。很少有语言认为一个孤独<代码> .<代码>作为一个浮点常数(文字通常被写为<代码> 0代码/代码>:))所以你可能想把它变成像之类的东西。
[0-9]*([0-9]\.?|\.[0-9])[0-9]*([Ee][-+]?[0-9]+)
要使用正则表达式匹配适合16位有符号int
的非负整数,可以使用以下模式:
0*([12]?[0-9]{1,4}|3(2(7(6[0-7]|[0-5][0-9])|[0-6][0-9]{2})|[0-1][0-9]{3}))
(F) lex将生成高效的代码来实现这个正则表达式,但这并不一定是个好主意
注:
09
。有些语言(如C)认为这是一个无效的八进制文字,但我不认为Basic有这种限制。-
开头的文本使用单独的模式来轻松处理正负限制之间的差异,但在整数文本中包含符号不适合表达式解析器,因为它对a-1
产生了错误的词法分析。(如果-32768
是一个有效的整数文本,这也有点奇怪,-32768
被分析为一个浮点表达式,其计算结果为-32768.0
),这里真的没有好的解决方案,除非您的语言包含无符号整数文本(如C),在这种情况下,您可以将0到32767之间的文字作为有符号整数进行分析;从32768到65535为无符号整数;和65536及以上作为浮点抱歉,我看到我要进行的编辑未保存。我正在根据1975年版的牵牛星基本手册编写一个MS BASIC解释器。你说丑陋,但我说工作=美丽!最终,我在C端解决了这个问题,通过原子化它,检查限制,然后返回TOK_FP,或者如果它在限制范围内,返回TOK_INT并用原子化重新解析。@maury:这似乎比需要做的工作更多。每一个16位整数可以精确地表示为一个单精度浮点(事实上,最多23位的整数可以精确地表示);如果数字与整数模式匹配并且在正确的范围内,您可以将其转换为
int
,而不会丢失精度。事实证明,flex定义了INT16_MIN和INT16_MAX,因此我将它们用于边界检查。现在一切都像冠军一样工作。请注意,atof
和atoi
不执行错误检测;对于无法表示的值,行为未定义。@Kaz-注意Kaz的有效点。