[前][次][番号順一覧][スレッド一覧]

ruby-changes:30280

From: nobu <ko1@a...>
Date: Fri, 2 Aug 2013 23:15:06 +0900 (JST)
Subject: [ruby-changes:30280] nobu:r42332 (trunk): parse.y: parse precisely

nobu	2013-08-02 23:14:55 +0900 (Fri, 02 Aug 2013)

  New Revision: 42332

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=42332

  Log:
    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.

  Modified files:
    trunk/ChangeLog
    trunk/bootstraptest/test_literal_suffix.rb
    trunk/parse.y

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 42331)
+++ ChangeLog	(revision 42332)
@@ -1,4 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
-Fri Aug  2 23:14:16 2013  Nobuyoshi Nakada  <nobu@r...>
+Fri Aug  2 23:14:54 2013  Nobuyoshi Nakada  <nobu@r...>
+
+	* 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
 	  numeric rules.
Index: bootstraptest/test_literal_suffix.rb
===================================================================
--- bootstraptest/test_literal_suffix.rb	(revision 42331)
+++ bootstraptest/test_literal_suffix.rb	(revision 42332)
@@ -43,6 +43,8 @@ assert_equal '0+10.0i',         '1e1i' https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_literal_suffix.rb#L43
 assert_equal 'Complex',         '1e1i.class'
 assert_equal '1',               '1if true'
 assert_equal '1',               '1rescue nil'
+assert_equal '10000000000000000001/10000000000000000000',
+             '1.0000000000000000001r'
 
 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}
Index: parse.y
===================================================================
--- parse.y	(revision 42331)
+++ parse.y	(revision 42332)
@@ -5024,7 +5024,9 @@ static int parser_here_document(struct p https://github.com/ruby/ruby/blob/trunk/parse.y#L5024
 # define heredoc_identifier()         parser_heredoc_identifier(parser)
 # 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 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
 # define set_yylval_str(x) (yylval.node = NEW_STR(x))
@@ -6382,51 +6384,54 @@ parser_whole_match_p(struct parser_param https://github.com/ruby/ruby/blob/trunk/parse.y#L6384
 #define NUM_SUFFIX_ALL 3
 
 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();
-    if ((flag & NUM_SUFFIX_R) > 0 && c == 'r') {
-        c = nextc();
-        if (c != 'i' && (ISALNUM(c) || c == '_')) {
-            pushback(c);
-            pushback('r');
-            goto finish;
-        }
+    int c, result = 0;
+    const char *lastp = lex_p;
 
-        if (RB_TYPE_P(v, T_FLOAT)) {
-            v = rb_flt_rationalize(v);
-        }
-        else {
-            v = rb_rational_new(v, INT2FIX(1));
-        }
+    while ((c = nextc()) != -1) {
+	if ((mask & NUM_SUFFIX_I) && c == 'i') {
+	    result |= (mask & NUM_SUFFIX_I);
+	    mask &= ~NUM_SUFFIX_I;
+	    /* 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') {
-        c = nextc();
-        if (ISALNUM(c) || c == '_') {
-            pushback(c);
-            pushback('i');
-            goto finish;
-        }
+    return result;
+}
 
-        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);
-    switch (TYPE(v)) {
-    case T_FIXNUM: case T_BIGNUM:
-        return tINTEGER;
-    case T_FLOAT:
-        return tFLOAT;
-    case T_RATIONAL:
-        return tRATIONAL;
-    case T_COMPLEX:
-        return tIMAGINARY;
-    default:
-        break;
+    return type;
+}
+
+static int
+parser_set_integer_literal(struct parser_params *parser, VALUE v, int suffix)
+{
+    int type = tINTEGER;
+    if (suffix & NUM_SUFFIX_R) {
+	v = rb_rational_new(v, INT2FIX(1));
+	type = tRATIONAL;
     }
-    UNREACHABLE;
+    return set_number_literal(v, type, suffix);
 }
 
 #ifdef RIPPER
@@ -7425,7 +7430,7 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/parse.y#L7430
       case '5': case '6': case '7': case '8': case '9':
 	{
 	    int is_float, seen_point, seen_e, nondigit;
-            VALUE v;
+	    int suffix;
 
 	    is_float = seen_point = seen_e = nondigit = 0;
 	    lex_state = EXPR_END;
@@ -7459,8 +7464,8 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/parse.y#L7464
 			no_digits();
 		    }
 		    else if (nondigit) goto trailing_uc;
-                    v = rb_cstr_to_inum(tok(), 16, FALSE);
-                    return number_literal_suffix(v, NUM_SUFFIX_ALL);
+		    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 */
@@ -7483,8 +7488,8 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/parse.y#L7488
 			no_digits();
 		    }
 		    else if (nondigit) goto trailing_uc;
-                    v = rb_cstr_to_inum(tok(), 2, FALSE);
-                    return number_literal_suffix(v, NUM_SUFFIX_ALL);
+		    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 */
@@ -7507,8 +7512,8 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/parse.y#L7512
 			no_digits();
 		    }
 		    else if (nondigit) goto trailing_uc;
-                    v = rb_cstr_to_inum(tok(), 10, FALSE);
-                    return number_literal_suffix(v, NUM_SUFFIX_ALL);
+		    suffix = number_literal_suffix(NUM_SUFFIX_ALL);
+		    return set_integer_literal(rb_cstr_to_inum(tok(), 10, FALSE), suffix);
 		}
 		if (c == '_') {
 		    /* 0_0 */
@@ -7539,8 +7544,8 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/parse.y#L7544
 			pushback(c);
 			tokfix();
 			if (nondigit) goto trailing_uc;
-                        v = rb_cstr_to_inum(tok(), 8, FALSE);
-                        return number_literal_suffix(v, NUM_SUFFIX_ALL);
+			suffix = number_literal_suffix(NUM_SUFFIX_ALL);
+			return set_integer_literal(rb_cstr_to_inum(tok(), 8, FALSE), suffix);
 		    }
 		    if (nondigit) {
 			pushback(c);
@@ -7556,7 +7561,8 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/parse.y#L7561
 		}
 		else {
 		    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 *parse https://github.com/ruby/ruby/blob/trunk/parse.y#L7587
 			}
 			c = c0;
 		    }
+		    seen_point = toklen();
 		    tokadd('.');
 		    tokadd(c);
 		    is_float++;
-		    seen_point++;
 		    nondigit = 0;
 		    break;
 
@@ -7633,16 +7639,32 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/parse.y#L7639
 	    }
 	    tokfix();
 	    if (is_float) {
-		double d = strtod(tok(), 0);
-		if (errno == ERANGE) {
-		    rb_warningS("Float %s out of range", tok());
-		    errno = 0;
+		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);
+		    *point = '1';
+		    memset(point+1, '0', fraclen);
+		    v = rb_rational_new(v, rb_cstr_to_inum(point, 10, FALSE));
+		}
+		else {
+		    double d = strtod(tok(), 0);
+		    if (errno == ERANGE) {
+			rb_warningS("Float %s out of range", tok());
+			errno = 0;
+		    }
+		    v = DBL2NUM(d);
 		}
-                v = DBL2NUM(d);
-                return number_literal_suffix(v, seen_e ? NUM_SUFFIX_I : NUM_SUFFIX_ALL);
+		return set_number_literal(v, type, suffix);
 	    }
-            v = rb_cstr_to_inum(tok(), 10, FALSE);
-            return number_literal_suffix(v, NUM_SUFFIX_ALL);
+	    suffix = number_literal_suffix(NUM_SUFFIX_ALL);
+	    return set_integer_literal(rb_cstr_to_inum(tok(), 10, FALSE), suffix);
 	}
 
       case ')':

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]