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

ruby-changes:39965

From: nagachika <ko1@a...>
Date: Tue, 6 Oct 2015 01:47:31 +0900 (JST)
Subject: [ruby-changes:39965] nagachika:r52046 (ruby_2_2): merge revision(s) 50409, 51616, 51617, 51624: [Backport #10653] [Backport #11456]

nagachika	2015-10-06 01:47:24 +0900 (Tue, 06 Oct 2015)

  New Revision: 52046

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

  Log:
    merge revision(s) 50409,51616,51617,51624: [Backport #10653] [Backport #11456]
    
    parse.y: %-string cannot be a label
    
    * parse.y (parser_yylex): %-string cannot be a label even if
      terminated by single/double quotes.
    * parse.y: fix syntax error at do-block after a conditional
      operator.  separate label-allowed and after-a-label states from
      others as bit flags.  [ruby-dev:48790] [Bug #10653]
    
    * parse.y (IS_BEG): include labeled argument state, which was
      EXPR_LABELARG.  [ruby-dev:49221] [Bug #11456]

  Modified directories:
    branches/ruby_2_2/
  Modified files:
    branches/ruby_2_2/ChangeLog
    branches/ruby_2_2/parse.y
    branches/ruby_2_2/test/ruby/test_syntax.rb
    branches/ruby_2_2/version.h
Index: ruby_2_2/ChangeLog
===================================================================
--- ruby_2_2/ChangeLog	(revision 52045)
+++ ruby_2_2/ChangeLog	(revision 52046)
@@ -1,3 +1,14 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_2/ChangeLog#L1
+Tue Oct  6 01:29:02 2015  Nobuyoshi Nakada  <nobu@r...>
+
+	* parse.y (IS_BEG): include labeled argument state, which was
+	  EXPR_LABELARG.  [ruby-dev:49221] [Bug #11456]
+
+Tue Oct  6 01:29:02 2015  Nobuyoshi Nakada  <nobu@r...>
+
+	* parse.y: fix syntax error at do-block after a conditional
+	  operator.  separate label-allowed and after-a-label states from
+	  others as bit flags.  [ruby-dev:48790] [Bug #10653]
+
 Mon Oct  5 03:29:23 2015  Tanaka Akira  <akr@f...>
 
 	* enum.c (nmin_filter): Fix limit value.
Index: ruby_2_2/parse.y
===================================================================
--- ruby_2_2/parse.y	(revision 52045)
+++ ruby_2_2/parse.y	(revision 52046)
@@ -59,8 +59,8 @@ enum lex_state_bits { https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L59
     EXPR_FNAME_bit,		/* ignore newline, no reserved words. */
     EXPR_DOT_bit,		/* right after `.' or `::', no reserved words. */
     EXPR_CLASS_bit,		/* immediate after `class', no here document. */
-    EXPR_VALUE_bit,		/* alike EXPR_BEG but label is disallowed. */
-    EXPR_LABELARG_bit,		/* ignore significant, +/- is a sign. */
+    EXPR_LABEL_bit,		/* flag bit, label is allowed. */
+    EXPR_LABELED_bit,		/* flag bit, just after a label. */
     EXPR_MAX_STATE
 };
 /* examine combinations */
@@ -76,14 +76,17 @@ enum lex_state_e { https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L76
     DEF_EXPR(FNAME),
     DEF_EXPR(DOT),
     DEF_EXPR(CLASS),
-    DEF_EXPR(VALUE),
-    DEF_EXPR(LABELARG),
-    EXPR_BEG_ANY  =  (EXPR_BEG | EXPR_VALUE | EXPR_MID | EXPR_CLASS | EXPR_LABELARG),
+    DEF_EXPR(LABEL),
+    DEF_EXPR(LABELED),
+    EXPR_VALUE = EXPR_BEG,
+    EXPR_BEG_ANY  =  (EXPR_BEG | EXPR_MID | EXPR_CLASS),
     EXPR_ARG_ANY  =  (EXPR_ARG | EXPR_CMDARG),
     EXPR_END_ANY  =  (EXPR_END | EXPR_ENDARG | EXPR_ENDFN)
 };
 #define IS_lex_state_for(x, ls)	((x) & (ls))
+#define IS_lex_state_all_for(x, ls) (((x) & (ls)) == (ls))
 #define IS_lex_state(ls)	IS_lex_state_for(lex_state, (ls))
+#define IS_lex_state_all(ls)	IS_lex_state_all_for(lex_state, (ls))
 
 #if PARSER_DEBUG
 static const char *lex_state_name(enum lex_state_e state);
@@ -2357,24 +2360,14 @@ arg		: lhs '=' arg https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L2360
 			$$ = dispatch1(defined, $4);
 		    %*/
 		    }
-		| arg '?'
-		    {
-			$<val>$ = cond_stack;
-			cond_stack = 0;
-			COND_PUSH(1);
-		    }
-		  arg opt_nl ':'
-		    {
-			cond_stack = $<val>3;
-		    }
-		  arg
+		| arg '?' arg opt_nl ':' arg
 		    {
 		    /*%%%*/
 			value_expr($1);
-			$$ = NEW_IF(cond($1), $4, $8);
+			$$ = NEW_IF(cond($1), $3, $6);
 			fixpos($$, $1);
 		    /*%
-			$$ = dispatch3(ifop, $1, $4, $8);
+			$$ = dispatch3(ifop, $1, $3, $6);
 		    %*/
 		    }
 		| primary
@@ -3040,7 +3033,7 @@ primary		: literal https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L3033
 		| k_def singleton dot_or_colon {lex_state = EXPR_FNAME;} fname
 		    {
 			in_single++;
-			lex_state = EXPR_ENDFN; /* force for args */
+			lex_state = EXPR_ENDFN|EXPR_LABEL; /* force for args */
 			local_push(0);
 			$<id>$ = current_arg;
 			current_arg = 0;
@@ -4521,6 +4514,7 @@ f_arglist	: '(' f_args rparen https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L4514
 		|   {
 			$<num>$ = parser->parser_in_kwarg;
 			parser->parser_in_kwarg = 1;
+			lex_state |= EXPR_LABEL; /* force for args */
 		    }
 		    f_args term
 		    {
@@ -5701,8 +5695,10 @@ rb_parser_compile_file_path(volatile VAL https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L5695
 #define STR_FUNC_QWORDS 0x08
 #define STR_FUNC_SYMBOL 0x10
 #define STR_FUNC_INDENT 0x20
+#define STR_FUNC_LABEL  0x40
 
 enum string_type {
+    str_label  = STR_FUNC_LABEL,
     str_squote = (0),
     str_dquote = (STR_FUNC_EXPAND),
     str_xquote = (STR_FUNC_EXPAND),
@@ -7136,9 +7132,11 @@ parser_prepare(struct parser_params *par https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L7132
 
 #define IS_ARG() IS_lex_state(EXPR_ARG_ANY)
 #define IS_END() IS_lex_state(EXPR_END_ANY)
-#define IS_BEG() IS_lex_state(EXPR_BEG_ANY)
+#define IS_BEG() (IS_lex_state(EXPR_BEG_ANY) || IS_lex_state_all(EXPR_ARG|EXPR_LABELED))
 #define IS_SPCARG(c) (IS_ARG() && space_seen && !ISSPACE(c))
-#define IS_LABEL_POSSIBLE() ((IS_lex_state(EXPR_BEG | EXPR_ENDFN) && !cmd_state) || IS_ARG())
+#define IS_LABEL_POSSIBLE() (\
+	(IS_lex_state(EXPR_LABEL|EXPR_ENDFN) && !cmd_state) || \
+	IS_ARG())
 #define IS_LABEL_SUFFIX(n) (peek_n(':',(n)) && !peek_n(':', (n)+1))
 #define IS_AFTER_OPERATOR() IS_lex_state(EXPR_FNAME | EXPR_DOT)
 
@@ -7809,7 +7807,7 @@ parse_ident(struct parser_params *parser https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L7807
 
     if (IS_LABEL_POSSIBLE()) {
 	if (IS_LABEL_SUFFIX(0)) {
-	    lex_state = EXPR_LABELARG;
+	    lex_state = EXPR_ARG|EXPR_LABELED;
 	    nextc();
 	    set_yylval_name(TOK_INTERN());
 	    return tLABEL;
@@ -7843,11 +7841,11 @@ parse_ident(struct parser_params *parser https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L7841
 		    return keyword_do_block;
 		return keyword_do;
 	    }
-	    if (IS_lex_state_for(state, (EXPR_BEG | EXPR_VALUE | EXPR_LABELARG)))
+	    if (IS_lex_state_for(state, (EXPR_BEG | EXPR_LABELED)))
 		return kw->id[0];
 	    else {
 		if (kw->id[0] != kw->id[1])
-		    lex_state = EXPR_BEG;
+		    lex_state = EXPR_BEG | EXPR_LABEL;
 		return kw->id[1];
 	    }
 	}
@@ -7878,6 +7876,7 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L7876
     register int c;
     int space_seen = 0;
     int cmd_state;
+    int label;
     enum lex_state_e last_state;
 #ifdef RIPPER
     int fallthru = FALSE;
@@ -7894,7 +7893,7 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L7893
 	}
 	else {
 	    token = parse_string(lex_strterm);
-	    if (token == tSTRING_END && (peek_n('\'', -1) || peek_n('"', -1))) {
+	    if ((token == tSTRING_END) && (lex_strterm->nd_func & STR_FUNC_LABEL)) {
 		if (((IS_lex_state(EXPR_BEG | EXPR_ENDFN) && !COND_P()) || IS_ARG()) &&
 		    IS_LABEL_SUFFIX(0)) {
 		    nextc();
@@ -7904,7 +7903,7 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L7903
 	    if (token == tSTRING_END || token == tREGEXP_END || token == tLABEL_END) {
 		rb_gc_force_recycle((VALUE)lex_strterm);
 		lex_strterm = 0;
-		lex_state = token == tLABEL_END ? EXPR_LABELARG : EXPR_END;
+		lex_state = token == tLABEL_END ? EXPR_BEG|EXPR_LABEL : EXPR_END;
 	    }
 	}
 	return token;
@@ -7954,14 +7953,16 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L7953
 #endif
 	/* fall through */
       case '\n':
-	if (IS_lex_state(EXPR_BEG | EXPR_VALUE | EXPR_CLASS | EXPR_FNAME | EXPR_DOT | EXPR_LABELARG)) {
+	c = (IS_lex_state(EXPR_BEG|EXPR_CLASS|EXPR_FNAME|EXPR_DOT) &&
+	     !IS_lex_state(EXPR_LABELED));
+	if (c || IS_lex_state_all(EXPR_ARG|EXPR_LABELED)) {
 #ifdef RIPPER
             if (!fallthru) {
                 ripper_dispatch_scan_event(parser, tIGNORED_NL);
             }
             fallthru = FALSE;
 #endif
-	    if (IS_lex_state(EXPR_LABELARG) && parser->parser_in_kwarg) {
+	    if (!c && parser->parser_in_kwarg) {
 		goto normal_newline;
 	    }
 	    goto retry;
@@ -8175,7 +8176,8 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L8176
 	return '>';
 
       case '"':
-	lex_strterm = NEW_STRTERM(str_dquote, '"', 0);
+	label = (IS_LABEL_POSSIBLE() ? str_label : 0);
+	lex_strterm = NEW_STRTERM(str_dquote | label, '"', 0);
 	return tSTRING_BEG;
 
       case '`':
@@ -8194,7 +8196,8 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L8196
 	return tXSTRING_BEG;
 
       case '\'':
-	lex_strterm = NEW_STRTERM(str_squote, '\'', 0);
+	label = (IS_LABEL_POSSIBLE() ? str_label : 0);
+	lex_strterm = NEW_STRTERM(str_squote | label, '\'', 0);
 	return tSTRING_BEG;
 
       case '?':
@@ -8247,7 +8250,7 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L8250
 	    lex_state = EXPR_BEG;
 	    return tOP_ASGN;
 	}
-	lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG;
+	lex_state = IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG|EXPR_LABEL;
 	pushback(c);
 	return '|';
 
@@ -8377,7 +8380,7 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L8380
 	return tSYMBEG;
 
       case '/':
-	if (IS_lex_state(EXPR_BEG_ANY)) {
+	if (IS_BEG()) {
 	    lex_strterm = NEW_STRTERM(str_regexp, '/', 0);
 	    return tREGEXP_BEG;
 	}
@@ -8412,7 +8415,7 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L8415
 	return ';';
 
       case ',':
-	lex_state = EXPR_BEG;
+	lex_state = EXPR_BEG|EXPR_LABEL;
 	return ',';
 
       case '~':
@@ -8437,7 +8440,7 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L8440
 	paren_nest++;
 	COND_PUSH(0);
 	CMDARG_PUSH(0);
-	lex_state = EXPR_BEG;
+	lex_state = EXPR_BEG|EXPR_LABEL;
 	return c;
 
       case '[':
@@ -8452,15 +8455,16 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L8455
 		return tAREF;
 	    }
 	    pushback(c);
+	    lex_state |= EXPR_LABEL;
 	    return '[';
 	}
 	else if (IS_BEG()) {
 	    c = tLBRACK;
 	}
-	else if (IS_ARG() && space_seen) {
+	else if (IS_ARG() && (space_seen || IS_lex_state(EXPR_LABELED))) {
 	    c = tLBRACK;
 	}
-	lex_state = EXPR_BEG;
+	lex_state = EXPR_BEG|EXPR_LABEL;
 	COND_PUSH(0);
 	CMDARG_PUSH(0);
 	return c;
@@ -8475,7 +8479,9 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L8479
 	    CMDARG_PUSH(0);
 	    return tLAMBEG;
 	}
-	if (IS_ARG() || IS_lex_state(EXPR_END | EXPR_ENDFN))
+	if (IS_lex_state(EXPR_LABELED))
+	    c = tLBRACE;      /* hash */
+	else if (IS_lex_state(EXPR_ARG_ANY | EXPR_END | EXPR_ENDFN))
 	    c = '{';          /* block (primary) */
 	else if (IS_lex_state(EXPR_ENDARG))
 	    c = tLBRACE_ARG;  /* block (expr) */
@@ -8484,6 +8490,7 @@ parser_yylex(struct parser_params *parse https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L8490
 	COND_PUSH(0);
 	CMDARG_PUSH(0);
 	lex_state = EXPR_BEG;
+	if (c != tLBRACE_ARG) lex_state |= EXPR_LABEL;
 	if (c != tLBRACE) command_start = TRUE;
 	return c;
 
@@ -8977,7 +8984,6 @@ lex_state_name(enum lex_state_e state) https://github.com/ruby/ruby/blob/trunk/ruby_2_2/parse.y#L8984
     static const char names[][12] = {
 	"EXPR_BEG",    "EXPR_END",    "EXPR_ENDARG", "EXPR_ENDFN",  "EXPR_ARG",
 	"EXPR_CMDARG", "EXPR_MID",    "EXPR_FNAME",  "EXPR_DOT",    "EXPR_CLASS",
-	"EXPR_VALUE",
     };
 
     if ((unsigned)state & ~(~0u << EXPR_MAX_STATE))
Index: ruby_2_2/version.h
===================================================================
--- ruby_2_2/version.h	(revision 52045)
+++ ruby_2_2/version.h	(revision 52046)
@@ -1,10 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ruby_2_2/version.h#L1
 #define RUBY_VERSION "2.2.4"
-#define RUBY_RELEASE_DATE "2015-10-05"
-#define RUBY_PATCHLEVEL 179
+#define RUBY_RELEASE_DATE "2015-10-06"
+#define RUBY_PATCHLEVEL 180
 
 #define RUBY_RELEASE_YEAR 2015
 #define RUBY_RELEASE_MONTH 10
-#define RUBY_RELEASE_DAY 5
+#define RUBY_RELEASE_DAY 6
 
 #include "ruby/version.h"
 
Index: ruby_2_2/test/ruby/test_syntax.rb
===================================================================
--- ruby_2_2/test/ruby/test_syntax.rb	(revision 52045)
+++ ruby_2_2/test/ruby/test_syntax.rb	(revision 52046)
@@ -295,6 +295,27 @@ WARN https://github.com/ruby/ruby/blob/trunk/ruby_2_2/test/ruby/test_syntax.rb#L295
     assert_not_label(:foo, 'class Foo < not_label:foo; end', bug6347)
   end
 
+  def test_no_label_with_percent
+    assert_syntax_error('{%"a": 1}', /unexpected ':'/)
+    assert_syntax_error("{%'a': 1}", /unexpected ':'/)
+    assert_syntax_error('{%Q"a": 1}', /unexpected ':'/)
+    assert_syntax_error("{%Q'a': 1}", /unexpected ':'/)
+    assert_syntax_error('{%q"a": 1}', /unexpected ':'/)
+    assert_syntax_error("{%q'a': 1}", /unexpected ':'/)
+  end
+
+  def test_block_after_cond
+    bug10653 = '[ruby-dev:48790] [Bug #10653]'
+    assert_valid_syntax("false ? raise {} : tap {}", bug10653)
+    assert_valid_syntax("false ? raise do end : tap do end", bug10653)
+  end
+
+  def test_paren_after_label
+    bug11456 = '[ruby-dev:49221] [Bug #11456]'
+    assert_valid_syntax("{foo: (1 rescue 0)}", bug11456)
+    assert_valid_syntax("{foo: /=/}", bug11456)
+  end
+
   def test_duplicated_arg
     assert_syntax_error("def foo(a, a) end", /duplicated argument name/)
     assert_nothing_raised { def foo(_, _) end }

Property changes on: ruby_2_2
___________________________________________________________________
Modified: svn:mergeinfo
   Merged /trunk:r50409,51616-51617,51624


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

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