ruby-changes:54687
From: nobu <ko1@a...>
Date: Tue, 22 Jan 2019 15:25:04 +0900 (JST)
Subject: [ruby-changes:54687] nobu:r66903 (trunk): parse.y: enclose keyword token names by quotes
nobu 2019-01-22 15:24:59 +0900 (Tue, 22 Jan 2019) New Revision: 66903 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=66903 Log: parse.y: enclose keyword token names by quotes * parse.y (rb_yytnamerr): strip enclosing double-quotes, same as the default yytnamerr except for that single-quotes matching back-quotes do not stop stripping. Modified files: trunk/parse.y trunk/test/ruby/test_syntax.rb Index: parse.y =================================================================== --- parse.y (revision 66902) +++ parse.y (revision 66903) @@ -609,6 +609,12 @@ rb_strterm_mark(VALUE obj) https://github.com/ruby/ruby/blob/trunk/parse.y#L609 } #endif +#define yytnamerr(yyres, yystr) (YYSIZE_T)rb_yytnamerr(yyres, yystr) +size_t rb_yytnamerr(char *yyres, const char *yystr); +#ifdef RIPPER +#define yystpcpy Not used +#endif + #define TOKEN2ID(tok) ( \ tTOKEN_LOCAL_BEGIN<(tok)&&(tok)<tTOKEN_LOCAL_END ? TOKEN2LOCALID(tok) : \ tTOKEN_INSTANCE_BEGIN<(tok)&&(tok)<tTOKEN_INSTANCE_END ? TOKEN2INSTANCEID(tok) : \ @@ -776,55 +782,55 @@ static void token_info_warn(struct parse https://github.com/ruby/ruby/blob/trunk/parse.y#L782 } %token <id> - keyword_class "class" - keyword_module "module" - keyword_def "def" - keyword_undef "undef" - keyword_begin "begin" - keyword_rescue "rescue" - keyword_ensure "ensure" - keyword_end "end" - keyword_if "if" - keyword_unless "unless" - keyword_then "then" - keyword_elsif "elsif" - keyword_else "else" - keyword_case "case" - keyword_when "when" - keyword_while "while" - keyword_until "until" - keyword_for "for" - keyword_break "break" - keyword_next "next" - keyword_redo "redo" - keyword_retry "retry" - keyword_in "in" - keyword_do "do" - keyword_do_cond "do (for condition)" - keyword_do_block "do (for block)" - keyword_do_LAMBDA "do (for lambda)" - keyword_return "return" - keyword_yield "yield" - keyword_super "super" - keyword_self "self" - keyword_nil "nil" - keyword_true "true" - keyword_false "false" - keyword_and "and" - keyword_or "or" - keyword_not "not" - modifier_if "if (modifier)" - modifier_unless "unless (modifier)" - modifier_while "while (modifier)" - modifier_until "until (modifier)" - modifier_rescue "rescue (modifier)" - keyword_alias "alias" - keyword_defined "defined?" - keyword_BEGIN "BEGIN" - keyword_END "END" - keyword__LINE__ "__LINE__" - keyword__FILE__ "__FILE__" - keyword__ENCODING__ "__ENCODING__" + keyword_class "`class'" + keyword_module "`module'" + keyword_def "`def'" + keyword_undef "`undef'" + keyword_begin "`begin'" + keyword_rescue "`rescue'" + keyword_ensure "`ensure'" + keyword_end "`end'" + keyword_if "`if'" + keyword_unless "`unless'" + keyword_then "`then'" + keyword_elsif "`elsif'" + keyword_else "`else'" + keyword_case "`case'" + keyword_when "`when'" + keyword_while "`while'" + keyword_until "`until'" + keyword_for "`for'" + keyword_break "`break'" + keyword_next "`next'" + keyword_redo "`redo'" + keyword_retry "`retry'" + keyword_in "`in'" + keyword_do "`do'" + keyword_do_cond "`do' for condition" + keyword_do_block "`do' for block" + keyword_do_LAMBDA "`do' for lambda" + keyword_return "`return'" + keyword_yield "`yield'" + keyword_super "`super'" + keyword_self "`self'" + keyword_nil "`nil'" + keyword_true "`true'" + keyword_false "`false'" + keyword_and "`and'" + keyword_or "`or'" + keyword_not "`not'" + modifier_if "`if' modifier" + modifier_unless "`unless' modifier" + modifier_while "`while' modifier" + modifier_until "`until' modifier" + modifier_rescue "`rescue' modifier" + keyword_alias "`alias'" + keyword_defined "`defined?'" + keyword_BEGIN "`BEGIN'" + keyword_END "`END'" + keyword__LINE__ "`__LINE__'" + keyword__FILE__ "`__FILE__'" + keyword__ENCODING__ "`__ENCODING__'" %token <id> tIDENTIFIER "local variable or method" %token <id> tFID "method" @@ -11177,6 +11183,78 @@ parser_compile_error(struct parser_param https://github.com/ruby/ruby/blob/trunk/parse.y#L11183 p->enc, fmt, ap); va_end(ap); } + +static size_t +count_char(const char *str, int c) +{ + int n = 0; + while (str[n] == c) ++n; + return n; +} + +/* + * strip enclosing double-quotes, same as the default yytnamerr except + * for that single-quotes matching back-quotes do not stop stripping. + * + * "\"`class' keyword\"" => "`class' keyword" + */ +RUBY_FUNC_EXPORTED size_t +rb_yytnamerr(char *yyres, const char *yystr) +{ + if (*yystr == '"') { + size_t yyn = 0, bquote = 0; + const char *yyp = yystr; + + while (*++yyp) { + switch (*yyp) { + case '`': + if (!bquote) { + bquote = count_char(yyp+1, '`') + 1; + if (yyres) memcpy(&yyres[yyn], yyp, bquote); + yyn += bquote; + yyp += bquote - 1; + break; + } + goto default_char; + + case '\'': + if (bquote && count_char(yyp+1, '\'') + 1 == bquote) { + if (yyres) memcpy(yyres + yyn, yyp, bquote); + yyn += bquote; + yyp += bquote - 1; + bquote = 0; + break; + } + goto do_not_strip_quotes; + + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default_char: + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + case '\0': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + } + do_not_strip_quotes: ; + } + + if (!yyres) return strlen(yystr); + + return (YYSIZE_T)(yystpcpy(yyres, yystr) - yyres); +} #endif #ifdef RIPPER Index: test/ruby/test_syntax.rb =================================================================== --- test/ruby/test_syntax.rb (revision 66902) +++ test/ruby/test_syntax.rb (revision 66903) @@ -995,7 +995,7 @@ eom https://github.com/ruby/ruby/blob/trunk/test/ruby/test_syntax.rb#L995 end def test_parenthesised_statement_argument - assert_syntax_error("foo(bar rescue nil)", /unexpected rescue \(modifier\)/) + assert_syntax_error("foo(bar rescue nil)", /unexpected `rescue' modifier/) assert_valid_syntax("foo (bar rescue nil)") end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/