1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66903 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2019-01-22 06:24:59 +00:00
parent 5e7d03531e
commit 59a6215af6
2 changed files with 128 additions and 50 deletions

176
parse.y
View file

@ -609,6 +609,12 @@ rb_strterm_mark(VALUE obj)
} }
#endif #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) ( \ #define TOKEN2ID(tok) ( \
tTOKEN_LOCAL_BEGIN<(tok)&&(tok)<tTOKEN_LOCAL_END ? TOKEN2LOCALID(tok) : \ tTOKEN_LOCAL_BEGIN<(tok)&&(tok)<tTOKEN_LOCAL_END ? TOKEN2LOCALID(tok) : \
tTOKEN_INSTANCE_BEGIN<(tok)&&(tok)<tTOKEN_INSTANCE_END ? TOKEN2INSTANCEID(tok) : \ tTOKEN_INSTANCE_BEGIN<(tok)&&(tok)<tTOKEN_INSTANCE_END ? TOKEN2INSTANCEID(tok) : \
@ -776,55 +782,55 @@ static void token_info_warn(struct parser_params *p, const char *token, token_in
} }
%token <id> %token <id>
keyword_class "class" keyword_class "`class'"
keyword_module "module" keyword_module "`module'"
keyword_def "def" keyword_def "`def'"
keyword_undef "undef" keyword_undef "`undef'"
keyword_begin "begin" keyword_begin "`begin'"
keyword_rescue "rescue" keyword_rescue "`rescue'"
keyword_ensure "ensure" keyword_ensure "`ensure'"
keyword_end "end" keyword_end "`end'"
keyword_if "if" keyword_if "`if'"
keyword_unless "unless" keyword_unless "`unless'"
keyword_then "then" keyword_then "`then'"
keyword_elsif "elsif" keyword_elsif "`elsif'"
keyword_else "else" keyword_else "`else'"
keyword_case "case" keyword_case "`case'"
keyword_when "when" keyword_when "`when'"
keyword_while "while" keyword_while "`while'"
keyword_until "until" keyword_until "`until'"
keyword_for "for" keyword_for "`for'"
keyword_break "break" keyword_break "`break'"
keyword_next "next" keyword_next "`next'"
keyword_redo "redo" keyword_redo "`redo'"
keyword_retry "retry" keyword_retry "`retry'"
keyword_in "in" keyword_in "`in'"
keyword_do "do" keyword_do "`do'"
keyword_do_cond "do (for condition)" keyword_do_cond "`do' for condition"
keyword_do_block "do (for block)" keyword_do_block "`do' for block"
keyword_do_LAMBDA "do (for lambda)" keyword_do_LAMBDA "`do' for lambda"
keyword_return "return" keyword_return "`return'"
keyword_yield "yield" keyword_yield "`yield'"
keyword_super "super" keyword_super "`super'"
keyword_self "self" keyword_self "`self'"
keyword_nil "nil" keyword_nil "`nil'"
keyword_true "true" keyword_true "`true'"
keyword_false "false" keyword_false "`false'"
keyword_and "and" keyword_and "`and'"
keyword_or "or" keyword_or "`or'"
keyword_not "not" keyword_not "`not'"
modifier_if "if (modifier)" modifier_if "`if' modifier"
modifier_unless "unless (modifier)" modifier_unless "`unless' modifier"
modifier_while "while (modifier)" modifier_while "`while' modifier"
modifier_until "until (modifier)" modifier_until "`until' modifier"
modifier_rescue "rescue (modifier)" modifier_rescue "`rescue' modifier"
keyword_alias "alias" keyword_alias "`alias'"
keyword_defined "defined?" keyword_defined "`defined?'"
keyword_BEGIN "BEGIN" keyword_BEGIN "`BEGIN'"
keyword_END "END" keyword_END "`END'"
keyword__LINE__ "__LINE__" keyword__LINE__ "`__LINE__'"
keyword__FILE__ "__FILE__" keyword__FILE__ "`__FILE__'"
keyword__ENCODING__ "__ENCODING__" keyword__ENCODING__ "`__ENCODING__'"
%token <id> tIDENTIFIER "local variable or method" %token <id> tIDENTIFIER "local variable or method"
%token <id> tFID "method" %token <id> tFID "method"
@ -11177,6 +11183,78 @@ parser_compile_error(struct parser_params *p, const char *fmt, ...)
p->enc, fmt, ap); p->enc, fmt, ap);
va_end(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 #endif
#ifdef RIPPER #ifdef RIPPER

View file

@ -995,7 +995,7 @@ eom
end end
def test_parenthesised_statement_argument 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)") assert_valid_syntax("foo (bar rescue nil)")
end end