summaryrefslogtreecommitdiff
path: root/parse.y
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-01-28 09:33:56 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-01-28 09:33:56 +0000
commit8a95f7f981c5e25ca26de2b112c4979627a72a02 (patch)
tree3d254785019c4df7b363528307069a65d7c83f77 /parse.y
parent4f38c453b4fccfbc529909781c2c1659f256697b (diff)
* parse.y (yylex): strict check for numbers.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2024 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'parse.y')
-rw-r--r--parse.y105
1 files changed, 61 insertions, 44 deletions
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);