From e63df5319855c1b4ebba0498a466c3806dedba99 Mon Sep 17 00:00:00 2001 From: nobu Date: Tue, 20 Apr 2010 03:24:59 +0000 Subject: [PATCH] * parse.y (lex_state_e, IS_END, IS_SPCARG, parser_yylex): separate the state after vcall. [ruby-core:29578] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27414 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 +++++ parse.y | 21 +++++++++++---------- test/ruby/test_parse.rb | 24 ++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/ChangeLog b/ChangeLog index c21ea2f723..0df7c03c9d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Tue Apr 20 12:24:57 2010 Nobuyoshi Nakada + + * parse.y (lex_state_e, IS_END, IS_SPCARG, parser_yylex): separate + the state after vcall. [ruby-core:29578] + Tue Apr 20 01:03:00 2010 Yusuke Endoh * bootstraptest/test_fork.rb: add a test for [ruby-core:28924]. diff --git a/parse.y b/parse.y index 36d9d75eff..76ed6ca4f0 100644 --- a/parse.y +++ b/parse.y @@ -67,7 +67,9 @@ enum lex_state_e { EXPR_FNAME, /* ignore newline, no reserved words. */ EXPR_DOT, /* right after `.' or `::', no reserved words. */ EXPR_CLASS, /* immediate after `class', no here document. */ - EXPR_VALUE /* alike EXPR_BEG but label is disallowed. */ + EXPR_VALUE, /* alike EXPR_BEG but label is disallowed. */ + EXPR_VCALL, /* immediate after vcall */ + EXPR_MAX_STATE }; typedef VALUE stack_type; @@ -6413,9 +6415,9 @@ parser_prepare(struct parser_params *parser) } #define IS_ARG() (lex_state == EXPR_ARG || lex_state == EXPR_CMDARG) -#define IS_END() (lex_state == EXPR_END || lex_state == EXPR_ENDARG) +#define IS_END() (lex_state == EXPR_END || lex_state == EXPR_ENDARG || lex_state == EXPR_VCALL) #define IS_BEG() (lex_state == EXPR_BEG || lex_state == EXPR_MID || lex_state == EXPR_VALUE || lex_state == EXPR_CLASS) -#define IS_SPCARG(c) (IS_ARG() && space_seen && !ISSPACE(c)) +#define IS_SPCARG(c) ((IS_ARG() || lex_state == EXPR_VCALL) && space_seen && !ISSPACE(c)) static int parser_yylex(struct parser_params *parser) @@ -6660,8 +6662,7 @@ parser_yylex(struct parser_params *parser) if (c == '<' && lex_state != EXPR_DOT && lex_state != EXPR_CLASS && - !IS_END() && - (!IS_ARG() || space_seen)) { + (!(IS_ARG() || IS_END()) || space_seen)) { int token = heredoc_identifier(); if (token) return token; } @@ -6736,11 +6737,11 @@ parser_yylex(struct parser_params *parser) return tSTRING_BEG; case '?': - if (IS_END()) { + c = nextc(); + if (IS_END() && (!space_seen || ISSPACE(c))) { lex_state = EXPR_VALUE; return '?'; } - c = nextc(); if (c == -1) { compile_error(PARSER_ARG "incomplete character syntax"); return 0; @@ -7316,7 +7317,7 @@ parser_yylex(struct parser_params *parser) CMDARG_PUSH(0); return tLAMBEG; } - if (IS_ARG() || lex_state == EXPR_END) + if (IS_ARG() || lex_state == EXPR_END || lex_state == EXPR_VCALL) c = '{'; /* block (primary) */ else if (lex_state == EXPR_ENDARG) c = tLBRACE_ARG; /* block (expr) */ @@ -7624,7 +7625,7 @@ parser_yylex(struct parser_params *parser) } if ((lex_state == EXPR_BEG && !cmd_state) || - IS_ARG()) { + IS_ARG() || lex_state == EXPR_VCALL) { if (peek(':') && !(lex_p + 1 < lex_pend && lex_p[1] == ':')) { lex_state = EXPR_BEG; nextc(); @@ -7687,7 +7688,7 @@ parser_yylex(struct parser_params *parser) set_yylval_name(ident); if (last_state != EXPR_DOT && is_local_id(ident) && lvar_defined(ident)) { - lex_state = EXPR_END; + lex_state = EXPR_VCALL; } } return result; diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index 49ecfc56ed..aa664ebd44 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -823,4 +823,28 @@ x = __ENCODING__ c.instance_eval { remove_class_variable(:@var) } end end + + def result(arg = nil, &pro) + pro || arg + end + + def test_method_and_lvar + result = nil + bug3163 = '[ruby-core:29578]' + assert_equal(%[bug3163], (result %[bug3163]), bug3163) + assert_equal(/bug3163/x, (result /bug3163/x), bug3163) + pro = proc {} + assert_equal(pro, (result &pro), bug3163) + assert_equal(bug3163, (result *bug3163), bug3163) + f = g = nil + assert_raise(SyntaxError, bug3163) {eval("result ?f : g")} + assert_equal("123\n", eval("result < 1}, (result a: 1)) + end end