diff --git a/ChangeLog b/ChangeLog index 1d3a3d02c7..5e2b6d259f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Mon Jan 28 18:33:18 2002 Nobuyoshi Nakada + + * parse.y (yylex): strict check for numbers. + Mon Jan 28 13:29:41 2002 K.Kosako * eval.c (is_defined): defined?(Foo::Baz) should check constants diff --git a/parse.y b/parse.y index 0296f63102..481927ec42 100644 --- a/parse.y +++ b/parse.y @@ -3312,9 +3312,9 @@ yylex() case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { - int is_float, seen_point, seen_e, seen_uc; + int is_float, seen_point, seen_e, nondigit; - is_float = seen_point = seen_e = seen_uc = 0; + is_float = seen_point = seen_e = nondigit = 0; lex_state = EXPR_END; newtok(); if (c == '-' || c == '+') { @@ -3322,46 +3322,53 @@ yylex() c = nextc(); } if (c == '0') { + int start = toklen(); c = nextc(); if (c == 'x' || c == 'X') { /* hexadecimal */ c = nextc(); - do { - if (c == '_') { - seen_uc = 1; - continue; - } - if (!ISXDIGIT(c)) break; - seen_uc = 0; - tokadd(c); - } while (c = nextc()); + if (ISXDIGIT(c)) { + do { + if (c == '_') { + if (nondigit) break; + nondigit = c; + continue; + } + if (!ISXDIGIT(c)) break; + nondigit = 0; + tokadd(c); + } while (c = nextc()); + } pushback(c); tokfix(); - if (toklen() == 0) { + if (toklen() == start) { yyerror("hexadecimal number without hex-digits"); } - else if (seen_uc) goto trailing_uc; + else if (nondigit) goto trailing_uc; yylval.val = rb_cstr2inum(tok(), 16); return tINTEGER; } if (c == 'b' || c == 'B') { /* binary */ c = nextc(); - do { - if (c == '_') { - seen_uc = 1; - continue; - } - if (c != '0'&& c != '1') break; - seen_uc = 0; - tokadd(c); - } while (c = nextc()); + if (c == '0' || c == '1') { + do { + if (c == '_') { + if (nondigit) break; + nondigit = c; + continue; + } + if (c != '0' && c != '1') break; + nondigit = 0; + tokadd(c); + } while (c = nextc()); + } pushback(c); tokfix(); - if (toklen() == 0) { + if (toklen() == start) { yyerror("numeric literal without digits"); } - else if (seen_uc) goto trailing_uc; + else if (nondigit) goto trailing_uc; yylval.val = rb_cstr2inum(tok(), 2); return tINTEGER; } @@ -3369,23 +3376,26 @@ yylex() /* octal */ do { if (c == '_') { - seen_uc = 1; + if (nondigit) break; + nondigit = c; continue; } if (c < '0' || c > '7') break; - seen_uc = 0; + nondigit = 0; tokadd(c); } while (c = nextc()); - pushback(c); - tokfix(); - if (seen_uc) goto trailing_uc; - yylval.val = rb_cstr2inum(tok(), 8); - return tINTEGER; + if (toklen() > start) { + pushback(c); + tokfix(); + if (nondigit) goto trailing_uc; + yylval.val = rb_cstr2inum(tok(), 8); + return tINTEGER; + } } if (c > '7' && c <= '9') { yyerror("Illegal octal digit"); } - else if (c == '.') { + else if (c == '.' || c == 'e' || c == 'E') { tokadd('0'); } else { @@ -3399,12 +3409,12 @@ yylex() switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - seen_uc = 0; + nondigit = 0; tokadd(c); break; case '.': - if (seen_uc) goto trailing_uc; + if (nondigit) goto trailing_uc; if (seen_point || seen_e) { goto decode_num; } @@ -3420,27 +3430,32 @@ yylex() tokadd(c); is_float++; seen_point++; - seen_uc = 0; + nondigit = 0; break; case 'e': case 'E': + if (nondigit) { + pushback(c); + c = nondigit; + goto decode_num; + } if (seen_e) { goto decode_num; } tokadd(c); seen_e++; is_float++; - while ((c = nextc()) == '_') - seen_uc = 1; - if (c == '-' || c == '+') - tokadd(c); - else - continue; + nondigit = c; + c = nextc(); + if (c != '-' && c != '+') continue; + tokadd(c); + nondigit = c; break; case '_': /* `_' in number just ignored */ - seen_uc = 1; + if (nondigit) goto decode_num; + nondigit = c; break; default: @@ -3452,9 +3467,11 @@ yylex() decode_num: pushback(c); tokfix(); - if (seen_uc) { + if (nondigit) { + char tmp[30]; trailing_uc: - yyerror("trailing `_' in number"); + sprintf(tmp, "trailing `%c' in number", nondigit); + yyerror(tmp); } if (is_float) { double d = strtod(tok(), 0);