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/