ruby-changes:34759
From: nobu <ko1@a...>
Date: Thu, 17 Jul 2014 13:30:26 +0900 (JST)
Subject: [ruby-changes:34759] nobu:r46842 (trunk): parse.y: parse_numeric
nobu 2014-07-17 13:30:13 +0900 (Thu, 17 Jul 2014) New Revision: 46842 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=46842 Log: parse.y: parse_numeric * parse.y (parse_numeric): extract from parser_yylex(). Modified files: trunk/parse.y Index: parse.y =================================================================== --- parse.y (revision 46841) +++ parse.y (revision 46842) @@ -6939,6 +6939,245 @@ parser_prepare(struct parser_params *par https://github.com/ruby/ruby/blob/trunk/parse.y#L6939 (ambiguous_operator(op, syn), 0))) static int +parse_numeric(struct parser_params *parser, int c) +{ + int is_float, seen_point, seen_e, nondigit; + int suffix; + + is_float = seen_point = seen_e = nondigit = 0; + lex_state = EXPR_END; + newtok(); + if (c == '-' || c == '+') { + tokadd(c); + c = nextc(); + } + if (c == '0') { +#define no_digits() do {yyerror("numeric literal without digits"); return 0;} while (0) + int start = toklen(); + c = nextc(); + if (c == 'x' || c == 'X') { + /* hexadecimal */ + c = nextc(); + if (c != -1 && ISXDIGIT(c)) { + do { + if (c == '_') { + if (nondigit) break; + nondigit = c; + continue; + } + if (!ISXDIGIT(c)) break; + nondigit = 0; + tokadd(c); + } while ((c = nextc()) != -1); + } + pushback(c); + tokfix(); + if (toklen() == start) { + no_digits(); + } + else if (nondigit) goto trailing_uc; + suffix = number_literal_suffix(NUM_SUFFIX_ALL); + return set_integer_literal(rb_cstr_to_inum(tok(), 16, FALSE), suffix); + } + if (c == 'b' || c == 'B') { + /* binary */ + 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()) != -1); + } + pushback(c); + tokfix(); + if (toklen() == start) { + no_digits(); + } + else if (nondigit) goto trailing_uc; + suffix = number_literal_suffix(NUM_SUFFIX_ALL); + return set_integer_literal(rb_cstr_to_inum(tok(), 2, FALSE), suffix); + } + if (c == 'd' || c == 'D') { + /* decimal */ + c = nextc(); + if (c != -1 && ISDIGIT(c)) { + do { + if (c == '_') { + if (nondigit) break; + nondigit = c; + continue; + } + if (!ISDIGIT(c)) break; + nondigit = 0; + tokadd(c); + } while ((c = nextc()) != -1); + } + pushback(c); + tokfix(); + if (toklen() == start) { + no_digits(); + } + else if (nondigit) goto trailing_uc; + suffix = number_literal_suffix(NUM_SUFFIX_ALL); + return set_integer_literal(rb_cstr_to_inum(tok(), 10, FALSE), suffix); + } + if (c == '_') { + /* 0_0 */ + goto octal_number; + } + if (c == 'o' || c == 'O') { + /* prefixed octal */ + c = nextc(); + if (c == -1 || c == '_' || !ISDIGIT(c)) { + no_digits(); + } + } + if (c >= '0' && c <= '7') { + /* octal */ + octal_number: + do { + if (c == '_') { + if (nondigit) break; + nondigit = c; + continue; + } + if (c < '0' || c > '9') break; + if (c > '7') goto invalid_octal; + nondigit = 0; + tokadd(c); + } while ((c = nextc()) != -1); + if (toklen() > start) { + pushback(c); + tokfix(); + if (nondigit) goto trailing_uc; + suffix = number_literal_suffix(NUM_SUFFIX_ALL); + return set_integer_literal(rb_cstr_to_inum(tok(), 8, FALSE), suffix); + } + if (nondigit) { + pushback(c); + goto trailing_uc; + } + } + if (c > '7' && c <= '9') { + invalid_octal: + yyerror("Invalid octal digit"); + } + else if (c == '.' || c == 'e' || c == 'E') { + tokadd('0'); + } + else { + pushback(c); + suffix = number_literal_suffix(NUM_SUFFIX_ALL); + return set_integer_literal(INT2FIX(0), suffix); + } + } + + for (;;) { + switch (c) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + nondigit = 0; + tokadd(c); + break; + + case '.': + if (nondigit) goto trailing_uc; + if (seen_point || seen_e) { + goto decode_num; + } + else { + int c0 = nextc(); + if (c0 == -1 || !ISDIGIT(c0)) { + pushback(c0); + goto decode_num; + } + c = c0; + } + seen_point = toklen(); + tokadd('.'); + tokadd(c); + is_float++; + nondigit = 0; + break; + + case 'e': + case 'E': + if (nondigit) { + pushback(c); + c = nondigit; + goto decode_num; + } + if (seen_e) { + goto decode_num; + } + nondigit = c; + c = nextc(); + if (c != '-' && c != '+' && !ISDIGIT(c)) { + pushback(c); + nondigit = 0; + goto decode_num; + } + tokadd(nondigit); + seen_e++; + is_float++; + tokadd(c); + nondigit = (c == '-' || c == '+') ? c : 0; + break; + + case '_': /* `_' in number just ignored */ + if (nondigit) goto decode_num; + nondigit = c; + break; + + default: + goto decode_num; + } + c = nextc(); + } + + decode_num: + pushback(c); + if (nondigit) { + char tmp[30]; + trailing_uc: + snprintf(tmp, sizeof(tmp), "trailing `%c' in number", nondigit); + yyerror(tmp); + } + tokfix(); + if (is_float) { + int type = tFLOAT; + VALUE v; + + 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); + v = rb_rational_new(v, rb_int_positive_pow(10, fraclen)); + } + else { + 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); + } + suffix = number_literal_suffix(NUM_SUFFIX_ALL); + return set_integer_literal(rb_cstr_to_inum(tok(), 10, FALSE), suffix); +} + +static int parser_yylex(struct parser_params *parser) { register int c; @@ -7401,8 +7640,7 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/parse.y#L7640 lex_state = EXPR_BEG; pushback(c); if (c != -1 && ISDIGIT(c)) { - c = '+'; - goto start_num; + return parse_numeric(parser, '+'); } return tUPLUS; } @@ -7459,245 +7697,9 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/parse.y#L7697 lex_state = EXPR_DOT; return '.'; - start_num: 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, nondigit; - int suffix; - - is_float = seen_point = seen_e = nondigit = 0; - lex_state = EXPR_END; - newtok(); - if (c == '-' || c == '+') { - tokadd(c); - c = nextc(); - } - if (c == '0') { -#define no_digits() do {yyerror("numeric literal without digits"); return 0;} while (0) - int start = toklen(); - c = nextc(); - if (c == 'x' || c == 'X') { - /* hexadecimal */ - c = nextc(); - if (c != -1 && ISXDIGIT(c)) { - do { - if (c == '_') { - if (nondigit) break; - nondigit = c; - continue; - } - if (!ISXDIGIT(c)) break; - nondigit = 0; - tokadd(c); - } while ((c = nextc()) != -1); - } - pushback(c); - tokfix(); - if (toklen() == start) { - no_digits(); - } - else if (nondigit) goto trailing_uc; - suffix = number_literal_suffix(NUM_SUFFIX_ALL); - return set_integer_literal(rb_cstr_to_inum(tok(), 16, FALSE), suffix); - } - if (c == 'b' || c == 'B') { - /* binary */ - 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()) != -1); - } - pushback(c); - tokfix(); - if (toklen() == start) { - no_digits(); - } - else if (nondigit) goto trailing_uc; - suffix = number_literal_suffix(NUM_SUFFIX_ALL); - return set_integer_literal(rb_cstr_to_inum(tok(), 2, FALSE), suffix); - } - if (c == 'd' || c == 'D') { - /* decimal */ - c = nextc(); - if (c != -1 && ISDIGIT(c)) { - do { - if (c == '_') { - if (nondigit) break; - nondigit = c; - continue; - } - if (!ISDIGIT(c)) break; - nondigit = 0; - tokadd(c); - } while ((c = nextc()) != -1); - } - pushback(c); - tokfix(); - if (toklen() == start) { - no_digits(); - } - else if (nondigit) goto trailing_uc; - suffix = number_literal_suffix(NUM_SUFFIX_ALL); - return set_integer_literal(rb_cstr_to_inum(tok(), 10, FALSE), suffix); - } - if (c == '_') { - /* 0_0 */ - goto octal_number; - } - if (c == 'o' || c == 'O') { - /* prefixed octal */ - c = nextc(); - if (c == -1 || c == '_' || !ISDIGIT(c)) { - no_digits(); - } - } - if (c >= '0' && c <= '7') { - /* octal */ - octal_number: - do { - if (c == '_') { - if (nondigit) break; - nondigit = c; - continue; - } - if (c < '0' || c > '9') break; - if (c > '7') goto invalid_octal; - nondigit = 0; - tokadd(c); - } while ((c = nextc()) != -1); - if (toklen() > start) { - pushback(c); - tokfix(); - if (nondigit) goto trailing_uc; - suffix = number_literal_suffix(NUM_SUFFIX_ALL); - return set_integer_literal(rb_cstr_to_inum(tok(), 8, FALSE), suffix); - } - if (nondigit) { - pushback(c); - goto trailing_uc; - } - } - if (c > '7' && c <= '9') { - invalid_octal: - yyerror("Invalid octal digit"); - } - else if (c == '.' || c == 'e' || c == 'E') { - tokadd('0'); - } - else { - pushback(c); - suffix = number_literal_suffix(NUM_SUFFIX_ALL); - return set_integer_literal(INT2FIX(0), suffix); - } - } - - for (;;) { - switch (c) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - nondigit = 0; - tokadd(c); - break; - - case '.': - if (nondigit) goto trailing_uc; - if (seen_point || seen_e) { - goto decode_num; - } - else { - int c0 = nextc(); - if (c0 == -1 || !ISDIGIT(c0)) { - pushback(c0); - goto decode_num; - } - c = c0; - } - seen_point = toklen(); - tokadd('.'); - tokadd(c); - is_float++; - nondigit = 0; - break; - - case 'e': - case 'E': - if (nondigit) { - pushback(c); - c = nondigit; - goto decode_num; - } - if (seen_e) { - goto decode_num; - } - nondigit = c; - c = nextc(); - if (c != '-' && c != '+' && !ISDIGIT(c)) { - pushback(c); - nondigit = 0; - goto decode_num; - } - tokadd(nondigit); - seen_e++; - is_float++; - tokadd(c); - nondigit = (c == '-' || c == '+') ? c : 0; - break; - - case '_': /* `_' in number just ignored */ - if (nondigit) goto decode_num; - nondigit = c; - break; - - default: - goto decode_num; - } - c = nextc(); - } - - decode_num: - pushback(c); - if (nondigit) { - char tmp[30]; - trailing_uc: - snprintf(tmp, sizeof(tmp), "trailing `%c' in number", nondigit); - yyerror(tmp); - } - tokfix(); - if (is_float) { - int type = tFLOAT; - VALUE v; - - 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); - v = rb_rational_new(v, rb_int_positive_pow(10, fraclen)); - } - else { - 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); - } - suffix = number_literal_suffix(NUM_SUFFIX_ALL); - return set_integer_literal(rb_cstr_to_inum(tok(), 10, FALSE), suffix); - } + return parse_numeric(parser, c); case ')': case ']': -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/