Regex 在lex/flex中标记化int与float

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

为了好玩,我在教自己一点flex/bison。我正在为1975年版本的MS Extended BASIC(扩展为“has strings”)编写一个解释器。不过有一个问题让我有点困惑

可以通过查找
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有这种限制。

  • 该模式无法识别32768,因为它太大,不能是正整数。但是,它不太大,不能是一个负整数<代码>-32768就可以了。在解析整型文字时,这始终是一个关键问题。如果您只是对整数文本进行词法分析,则可以通过对以
    -
    开头的文本使用单独的模式来轻松处理正负限制之间的差异,但在整数文本中包含符号不适合表达式解析器,因为它对
    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的有效点。