mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
parse.y: fix block after conditional
* 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] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51617 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
23352f62a7
commit
94b1db5d67
3 changed files with 49 additions and 22 deletions
|
@ -1,3 +1,9 @@
|
|||
Mon Aug 17 20:56:36 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* 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 Aug 17 11:57:36 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* io.c (rb_io_each_codepoint): raise an exception at incomplete
|
||||
|
|
59
parse.y
59
parse.y
|
@ -62,8 +62,8 @@ enum lex_state_bits {
|
|||
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 */
|
||||
|
@ -79,14 +79,17 @@ enum lex_state_e {
|
|||
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);
|
||||
|
@ -3016,7 +3019,7 @@ primary : literal
|
|||
{
|
||||
$<num>4 = in_single;
|
||||
in_single = 1;
|
||||
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;
|
||||
|
@ -4487,6 +4490,7 @@ f_arglist : '(' f_args rparen
|
|||
| {
|
||||
$<num>$ = parser->in_kwarg;
|
||||
parser->in_kwarg = 1;
|
||||
lex_state |= EXPR_LABEL; /* force for args */
|
||||
}
|
||||
f_args term
|
||||
{
|
||||
|
@ -5670,6 +5674,7 @@ rb_parser_compile_file_path(VALUE vparser, VALUE fname, VALUE file, int start)
|
|||
#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),
|
||||
|
@ -7105,7 +7110,9 @@ parser_prepare(struct parser_params *parser)
|
|||
#define IS_END() IS_lex_state(EXPR_END_ANY)
|
||||
#define IS_BEG() IS_lex_state(EXPR_BEG_ANY)
|
||||
#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)
|
||||
|
||||
|
@ -7781,7 +7788,7 @@ parse_ident(struct parser_params *parser, int c, int cmd_state)
|
|||
|
||||
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;
|
||||
|
@ -7815,11 +7822,11 @@ parse_ident(struct parser_params *parser, int c, int cmd_state)
|
|||
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];
|
||||
}
|
||||
}
|
||||
|
@ -7850,6 +7857,7 @@ parser_yylex(struct parser_params *parser)
|
|||
register int c;
|
||||
int space_seen = 0;
|
||||
int cmd_state;
|
||||
int label;
|
||||
enum lex_state_e last_state;
|
||||
#ifdef RIPPER
|
||||
int fallthru = FALSE;
|
||||
|
@ -7876,7 +7884,7 @@ parser_yylex(struct parser_params *parser)
|
|||
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;
|
||||
|
@ -7926,14 +7934,16 @@ parser_yylex(struct parser_params *parser)
|
|||
#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->in_kwarg) {
|
||||
if (!c && parser->in_kwarg) {
|
||||
goto normal_newline;
|
||||
}
|
||||
goto retry;
|
||||
|
@ -8147,7 +8157,8 @@ parser_yylex(struct parser_params *parser)
|
|||
return '>';
|
||||
|
||||
case '"':
|
||||
lex_strterm = NEW_STRTERM(str_dquote|STR_FUNC_LABEL, '"', 0);
|
||||
label = (IS_LABEL_POSSIBLE() ? str_label : 0);
|
||||
lex_strterm = NEW_STRTERM(str_dquote | label, '"', 0);
|
||||
return tSTRING_BEG;
|
||||
|
||||
case '`':
|
||||
|
@ -8166,7 +8177,8 @@ parser_yylex(struct parser_params *parser)
|
|||
return tXSTRING_BEG;
|
||||
|
||||
case '\'':
|
||||
lex_strterm = NEW_STRTERM(str_squote|STR_FUNC_LABEL, '\'', 0);
|
||||
label = (IS_LABEL_POSSIBLE() ? str_label : 0);
|
||||
lex_strterm = NEW_STRTERM(str_squote | label, '\'', 0);
|
||||
return tSTRING_BEG;
|
||||
|
||||
case '?':
|
||||
|
@ -8219,7 +8231,7 @@ parser_yylex(struct parser_params *parser)
|
|||
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 '|';
|
||||
|
||||
|
@ -8384,7 +8396,7 @@ parser_yylex(struct parser_params *parser)
|
|||
return ';';
|
||||
|
||||
case ',':
|
||||
lex_state = EXPR_BEG;
|
||||
lex_state = EXPR_BEG|EXPR_LABEL;
|
||||
return ',';
|
||||
|
||||
case '~':
|
||||
|
@ -8409,7 +8421,7 @@ parser_yylex(struct parser_params *parser)
|
|||
paren_nest++;
|
||||
COND_PUSH(0);
|
||||
CMDARG_PUSH(0);
|
||||
lex_state = EXPR_BEG;
|
||||
lex_state = EXPR_BEG|EXPR_LABEL;
|
||||
return c;
|
||||
|
||||
case '[':
|
||||
|
@ -8424,15 +8436,16 @@ parser_yylex(struct parser_params *parser)
|
|||
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;
|
||||
|
@ -8447,7 +8460,9 @@ parser_yylex(struct parser_params *parser)
|
|||
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) */
|
||||
|
@ -8456,6 +8471,7 @@ parser_yylex(struct parser_params *parser)
|
|||
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;
|
||||
|
||||
|
@ -8942,7 +8958,6 @@ lex_state_name(enum lex_state_e state)
|
|||
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))
|
||||
|
|
|
@ -304,6 +304,12 @@ WARN
|
|||
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_duplicated_arg
|
||||
assert_syntax_error("def foo(a, a) end", /duplicated argument name/)
|
||||
assert_nothing_raised { def foo(_, _) end }
|
||||
|
|
Loading…
Reference in a new issue