[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]