parse.y: parse precisely
* parse.y (parser_number_literal_suffix): return bit set of found suffixes. * parse.y (parser_set_number_literal, parser_set_integer_literal): split from parser_number_literal_suffix to set yyvlal. * parse.y (parser_yylex): parse rational number literal with decimal point precisely. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42332 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
e176b8e1c1
commit
2f57e80640
11
ChangeLog
11
ChangeLog
@ -1,4 +1,13 @@
|
|||||||
Fri Aug 2 23:14:16 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Fri Aug 2 23:14:54 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* parse.y (parser_number_literal_suffix): return bit set of found
|
||||||
|
suffixes.
|
||||||
|
|
||||||
|
* parse.y (parser_set_number_literal, parser_set_integer_literal):
|
||||||
|
split from parser_number_literal_suffix to set yyvlal.
|
||||||
|
|
||||||
|
* parse.y (parser_yylex): parse rational number literal with decimal
|
||||||
|
point precisely.
|
||||||
|
|
||||||
* parse.y (simple_numeric): integrate numeric literals and simplify
|
* parse.y (simple_numeric): integrate numeric literals and simplify
|
||||||
numeric rules.
|
numeric rules.
|
||||||
|
@ -43,6 +43,8 @@ assert_equal '0+10.0i', '1e1i'
|
|||||||
assert_equal 'Complex', '1e1i.class'
|
assert_equal 'Complex', '1e1i.class'
|
||||||
assert_equal '1', '1if true'
|
assert_equal '1', '1if true'
|
||||||
assert_equal '1', '1rescue nil'
|
assert_equal '1', '1rescue nil'
|
||||||
|
assert_equal '10000000000000000001/10000000000000000000',
|
||||||
|
'1.0000000000000000001r'
|
||||||
|
|
||||||
assert_equal 'syntax error, unexpected tIDENTIFIER, expecting end-of-input',
|
assert_equal 'syntax error, unexpected tIDENTIFIER, expecting end-of-input',
|
||||||
%q{begin eval('1ir', nil, '', 0); rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end}
|
%q{begin eval('1ir', nil, '', 0); rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end}
|
||||||
|
138
parse.y
138
parse.y
@ -5024,7 +5024,9 @@ static int parser_here_document(struct parser_params*,NODE*);
|
|||||||
# define heredoc_identifier() parser_heredoc_identifier(parser)
|
# define heredoc_identifier() parser_heredoc_identifier(parser)
|
||||||
# define heredoc_restore(n) parser_heredoc_restore(parser,(n))
|
# define heredoc_restore(n) parser_heredoc_restore(parser,(n))
|
||||||
# define whole_match_p(e,l,i) parser_whole_match_p(parser,(e),(l),(i))
|
# define whole_match_p(e,l,i) parser_whole_match_p(parser,(e),(l),(i))
|
||||||
# define number_literal_suffix(v, f) parser_number_literal_suffix(parser, (v), (f))
|
# define number_literal_suffix(f) parser_number_literal_suffix(parser, (f))
|
||||||
|
# define set_number_literal(v, t, f) parser_set_number_literal(parser, (v), (t), (f))
|
||||||
|
# define set_integer_literal(v, f) parser_set_integer_literal(parser, (v), (f))
|
||||||
|
|
||||||
#ifndef RIPPER
|
#ifndef RIPPER
|
||||||
# define set_yylval_str(x) (yylval.node = NEW_STR(x))
|
# define set_yylval_str(x) (yylval.node = NEW_STR(x))
|
||||||
@ -6382,51 +6384,54 @@ parser_whole_match_p(struct parser_params *parser,
|
|||||||
#define NUM_SUFFIX_ALL 3
|
#define NUM_SUFFIX_ALL 3
|
||||||
|
|
||||||
static int
|
static int
|
||||||
parser_number_literal_suffix(struct parser_params *parser, VALUE v, int const flag)
|
parser_number_literal_suffix(struct parser_params *parser, int mask)
|
||||||
{
|
{
|
||||||
int c = nextc();
|
int c, result = 0;
|
||||||
if ((flag & NUM_SUFFIX_R) > 0 && c == 'r') {
|
const char *lastp = lex_p;
|
||||||
c = nextc();
|
|
||||||
if (c != 'i' && (ISALNUM(c) || c == '_')) {
|
|
||||||
pushback(c);
|
|
||||||
pushback('r');
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RB_TYPE_P(v, T_FLOAT)) {
|
while ((c = nextc()) != -1) {
|
||||||
v = rb_flt_rationalize(v);
|
if ((mask & NUM_SUFFIX_I) && c == 'i') {
|
||||||
}
|
result |= (mask & NUM_SUFFIX_I);
|
||||||
else {
|
mask &= ~NUM_SUFFIX_I;
|
||||||
v = rb_rational_new(v, INT2FIX(1));
|
/* r after i, rational of complex is disallowed */
|
||||||
}
|
mask &= ~NUM_SUFFIX_R;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((mask & NUM_SUFFIX_R) && c == 'r') {
|
||||||
|
result |= (mask & NUM_SUFFIX_R);
|
||||||
|
mask &= ~NUM_SUFFIX_R;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!ISASCII(c) || ISALPHA(c) || c == '_') {
|
||||||
|
lex_p = lastp;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pushback(c);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if ((flag & NUM_SUFFIX_I) > 0 && c == 'i') {
|
return result;
|
||||||
c = nextc();
|
}
|
||||||
if (ISALNUM(c) || c == '_') {
|
|
||||||
pushback(c);
|
|
||||||
pushback('i');
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
v = rb_complex_new(INT2FIX(0), v);
|
static int
|
||||||
|
parser_set_number_literal(struct parser_params *parser, VALUE v, int type, int suffix)
|
||||||
|
{
|
||||||
|
if (suffix & NUM_SUFFIX_I) {
|
||||||
|
v = rb_complex_raw(INT2FIX(0), v);
|
||||||
|
type = tIMAGINARY;
|
||||||
}
|
}
|
||||||
pushback(c);
|
|
||||||
|
|
||||||
finish:
|
|
||||||
set_yylval_literal(v);
|
set_yylval_literal(v);
|
||||||
switch (TYPE(v)) {
|
return type;
|
||||||
case T_FIXNUM: case T_BIGNUM:
|
}
|
||||||
return tINTEGER;
|
|
||||||
case T_FLOAT:
|
static int
|
||||||
return tFLOAT;
|
parser_set_integer_literal(struct parser_params *parser, VALUE v, int suffix)
|
||||||
case T_RATIONAL:
|
{
|
||||||
return tRATIONAL;
|
int type = tINTEGER;
|
||||||
case T_COMPLEX:
|
if (suffix & NUM_SUFFIX_R) {
|
||||||
return tIMAGINARY;
|
v = rb_rational_new(v, INT2FIX(1));
|
||||||
default:
|
type = tRATIONAL;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
UNREACHABLE;
|
return set_number_literal(v, type, suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef RIPPER
|
#ifdef RIPPER
|
||||||
@ -7425,7 +7430,7 @@ parser_yylex(struct parser_params *parser)
|
|||||||
case '5': case '6': case '7': case '8': case '9':
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
{
|
{
|
||||||
int is_float, seen_point, seen_e, nondigit;
|
int is_float, seen_point, seen_e, nondigit;
|
||||||
VALUE v;
|
int suffix;
|
||||||
|
|
||||||
is_float = seen_point = seen_e = nondigit = 0;
|
is_float = seen_point = seen_e = nondigit = 0;
|
||||||
lex_state = EXPR_END;
|
lex_state = EXPR_END;
|
||||||
@ -7459,8 +7464,8 @@ parser_yylex(struct parser_params *parser)
|
|||||||
no_digits();
|
no_digits();
|
||||||
}
|
}
|
||||||
else if (nondigit) goto trailing_uc;
|
else if (nondigit) goto trailing_uc;
|
||||||
v = rb_cstr_to_inum(tok(), 16, FALSE);
|
suffix = number_literal_suffix(NUM_SUFFIX_ALL);
|
||||||
return number_literal_suffix(v, NUM_SUFFIX_ALL);
|
return set_integer_literal(rb_cstr_to_inum(tok(), 16, FALSE), suffix);
|
||||||
}
|
}
|
||||||
if (c == 'b' || c == 'B') {
|
if (c == 'b' || c == 'B') {
|
||||||
/* binary */
|
/* binary */
|
||||||
@ -7483,8 +7488,8 @@ parser_yylex(struct parser_params *parser)
|
|||||||
no_digits();
|
no_digits();
|
||||||
}
|
}
|
||||||
else if (nondigit) goto trailing_uc;
|
else if (nondigit) goto trailing_uc;
|
||||||
v = rb_cstr_to_inum(tok(), 2, FALSE);
|
suffix = number_literal_suffix(NUM_SUFFIX_ALL);
|
||||||
return number_literal_suffix(v, NUM_SUFFIX_ALL);
|
return set_integer_literal(rb_cstr_to_inum(tok(), 2, FALSE), suffix);
|
||||||
}
|
}
|
||||||
if (c == 'd' || c == 'D') {
|
if (c == 'd' || c == 'D') {
|
||||||
/* decimal */
|
/* decimal */
|
||||||
@ -7507,8 +7512,8 @@ parser_yylex(struct parser_params *parser)
|
|||||||
no_digits();
|
no_digits();
|
||||||
}
|
}
|
||||||
else if (nondigit) goto trailing_uc;
|
else if (nondigit) goto trailing_uc;
|
||||||
v = rb_cstr_to_inum(tok(), 10, FALSE);
|
suffix = number_literal_suffix(NUM_SUFFIX_ALL);
|
||||||
return number_literal_suffix(v, NUM_SUFFIX_ALL);
|
return set_integer_literal(rb_cstr_to_inum(tok(), 10, FALSE), suffix);
|
||||||
}
|
}
|
||||||
if (c == '_') {
|
if (c == '_') {
|
||||||
/* 0_0 */
|
/* 0_0 */
|
||||||
@ -7539,8 +7544,8 @@ parser_yylex(struct parser_params *parser)
|
|||||||
pushback(c);
|
pushback(c);
|
||||||
tokfix();
|
tokfix();
|
||||||
if (nondigit) goto trailing_uc;
|
if (nondigit) goto trailing_uc;
|
||||||
v = rb_cstr_to_inum(tok(), 8, FALSE);
|
suffix = number_literal_suffix(NUM_SUFFIX_ALL);
|
||||||
return number_literal_suffix(v, NUM_SUFFIX_ALL);
|
return set_integer_literal(rb_cstr_to_inum(tok(), 8, FALSE), suffix);
|
||||||
}
|
}
|
||||||
if (nondigit) {
|
if (nondigit) {
|
||||||
pushback(c);
|
pushback(c);
|
||||||
@ -7556,7 +7561,8 @@ parser_yylex(struct parser_params *parser)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pushback(c);
|
pushback(c);
|
||||||
return number_literal_suffix(INT2FIX(0), NUM_SUFFIX_ALL);
|
suffix = number_literal_suffix(NUM_SUFFIX_ALL);
|
||||||
|
return set_integer_literal(INT2FIX(0), suffix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7581,10 +7587,10 @@ parser_yylex(struct parser_params *parser)
|
|||||||
}
|
}
|
||||||
c = c0;
|
c = c0;
|
||||||
}
|
}
|
||||||
|
seen_point = toklen();
|
||||||
tokadd('.');
|
tokadd('.');
|
||||||
tokadd(c);
|
tokadd(c);
|
||||||
is_float++;
|
is_float++;
|
||||||
seen_point++;
|
|
||||||
nondigit = 0;
|
nondigit = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -7633,16 +7639,32 @@ parser_yylex(struct parser_params *parser)
|
|||||||
}
|
}
|
||||||
tokfix();
|
tokfix();
|
||||||
if (is_float) {
|
if (is_float) {
|
||||||
double d = strtod(tok(), 0);
|
int type = tFLOAT;
|
||||||
if (errno == ERANGE) {
|
VALUE v;
|
||||||
rb_warningS("Float %s out of range", tok());
|
|
||||||
errno = 0;
|
suffix = number_literal_suffix(seen_e ? NUM_SUFFIX_I : NUM_SUFFIX_ALL);
|
||||||
|
if (suffix & NUM_SUFFIX_R) {
|
||||||
|
char *point = &tok()[seen_point];
|
||||||
|
size_t fraclen = toklen()-seen_point-1;
|
||||||
|
type = tRATIONAL;
|
||||||
|
memmove(point, point+1, fraclen+1);
|
||||||
|
v = rb_cstr_to_inum(tok(), 10, FALSE);
|
||||||
|
*point = '1';
|
||||||
|
memset(point+1, '0', fraclen);
|
||||||
|
v = rb_rational_new(v, rb_cstr_to_inum(point, 10, FALSE));
|
||||||
}
|
}
|
||||||
v = DBL2NUM(d);
|
else {
|
||||||
return number_literal_suffix(v, seen_e ? NUM_SUFFIX_I : NUM_SUFFIX_ALL);
|
double d = strtod(tok(), 0);
|
||||||
|
if (errno == ERANGE) {
|
||||||
|
rb_warningS("Float %s out of range", tok());
|
||||||
|
errno = 0;
|
||||||
|
}
|
||||||
|
v = DBL2NUM(d);
|
||||||
|
}
|
||||||
|
return set_number_literal(v, type, suffix);
|
||||||
}
|
}
|
||||||
v = rb_cstr_to_inum(tok(), 10, FALSE);
|
suffix = number_literal_suffix(NUM_SUFFIX_ALL);
|
||||||
return number_literal_suffix(v, NUM_SUFFIX_ALL);
|
return set_integer_literal(rb_cstr_to_inum(tok(), 10, FALSE), suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
case ')':
|
case ')':
|
||||||
|
Loading…
x
Reference in New Issue
Block a user