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

ruby-changes:47234

From: nobu <ko1@a...>
Date: Mon, 17 Jul 2017 09:11:42 +0900 (JST)
Subject: [ruby-changes:47234] nobu:r59349 (trunk): parse.y: refine literal error messages

nobu	2017-07-17 09:11:38 +0900 (Mon, 17 Jul 2017)

  New Revision: 59349

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=59349

  Log:
    parse.y: refine literal error messages
    
    * parse.y (parser_yyerror): strip newline in error source which
      will not be printed, when lex_p has passed it.
    
    * parse.y (parser_tokadd_utf8): unterminated Unicode escape even
      after invalid Unicode escape.
    
    * parse.y (parser_parse_string): show the error source line when
      unterminated literal at end of file.

  Modified files:
    trunk/parse.y
    trunk/test/ruby/test_parse.rb
Index: test/ruby/test_parse.rb
===================================================================
--- test/ruby/test_parse.rb	(revision 59348)
+++ test/ruby/test_parse.rb	(revision 59349)
@@ -489,11 +489,23 @@ class TestParse < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_parse.rb#L489
     e = assert_syntax_error('"\xg1"', /hex escape/)
     assert_equal('   ^', e.message.lines.last, mesg)
 
-    e = assert_syntax_error('"\u{1234"', 'Unicode escape')
-    assert_match('        ^', e.message.lines.last, mesg)
+    e = assert_syntax_error('"\u{1234"', 'unterminated Unicode escape')
+    assert_equal('        ^', e.message.lines.last, mesg)
 
     e = assert_syntax_error('"\u{xxxx}"', 'invalid Unicode escape')
-    assert_match('    ^', e.message.lines.last, mesg)
+    assert_equal('    ^', e.message.lines.last, mesg)
+
+    e = assert_syntax_error('"\u{xxxx', 'Unicode escape')
+    assert_pattern_list([
+                          /.*: invalid Unicode escape\n.*\n/,
+                          /    \^/,
+                          /\n/,
+                          /.*: unterminated Unicode escape\n.*\n/,
+                          /    \^/,
+                          /\n/,
+                          /.*: unterminated string.*\n.*\n/,
+                          /        \^/,
+                        ], e.message)
 
     e = assert_syntax_error('"\M1"', /escape character syntax/)
     assert_equal(' ^~~', e.message.lines.last, mesg)
Index: parse.y
===================================================================
--- parse.y	(revision 59348)
+++ parse.y	(revision 59349)
@@ -5042,15 +5042,15 @@ parser_yyerror(struct parser_params *par https://github.com/ruby/ruby/blob/trunk/parse.y#L5042
     long len;
     int i;
 
-    p = lex_p;
-    lim = p - lex_pbeg > max_line_margin ? p - max_line_margin : lex_pbeg;
-    while ((lim < p) && (*(p-1) != '\n')) p--;
-
     pend = lex_pend;
     if (pend > lex_pbeg && pend[-1] == '\n') {
 	if (--pend > lex_pbeg && pend[-1] == '\r') --pend;
     }
-    pe = lex_p;
+
+    p = pe = lex_p < pend ? lex_p : pend;
+    lim = p - lex_pbeg > max_line_margin ? p - max_line_margin : lex_pbeg;
+    while ((lim < p) && (*(p-1) != '\n')) p--;
+
     lim = pend - pe > max_line_margin ? pe + max_line_margin : pend;
     while ((pe < lim) && (*pe != '\n')) pe++;
 
@@ -5067,20 +5067,22 @@ parser_yyerror(struct parser_params *par https://github.com/ruby/ruby/blob/trunk/parse.y#L5067
 	    if (pe < pend) post = "...";
 	}
 	len = pe - p;
-	i = (int)(lex_p - p);
+	lim = lex_p < pend ? lex_p : pend;
+	i = (int)(lim - p);
 	buf = ALLOCA_N(char, i+2);
 	code = p;
 	caret = p2 = buf;
-	if (p <= parser->tokp) {
-	    while (p < parser->tokp) {
+	pe = (parser->tokp < lim ? parser->tokp : lim);
+	if (p <= pe) {
+	    while (p < pe) {
 		*p2++ = *p++ == '\t' ? '\t' : ' ';
 	    }
 	    *p2++ = '^';
 	    p++;
 	}
-	if (lex_p > p) {
-	    memset(p2, '~', (lex_p - p));
-	    p2 += (lex_p - p);
+	if (lim > p) {
+	    memset(p2, '~', (lim - p));
+	    p2 += (lim - p);
 	}
 	*p2 = '\0';
 	newline = "\n";
@@ -5711,7 +5713,7 @@ parser_tokadd_utf8(struct parser_params https://github.com/ruby/ruby/blob/trunk/parse.y#L5713
 	while (!string_literal || c != close_brace) {
 	    if (regexp_literal) tokadd(last);
 	    if (!parser_tokadd_codepoint(parser, encp, regexp_literal, TRUE)) {
-		return 0;
+		break;
 	    }
 	    while (ISSPACE(c = *lex_p)) {
 		if (++lex_p >= lex_pend) goto unterminated;
@@ -6282,11 +6284,17 @@ parser_parse_string(struct parser_params https://github.com/ruby/ruby/blob/trunk/parse.y#L6284
     if (tokadd_string(func, term, paren, &quote->nd_nest,
 		      &enc) == -1) {
 	if (parser->eofp) {
+#ifndef RIPPER
+# define unterminated_literal(mesg) yyerror(mesg)
+#else
+# define unterminated_literal(mesg) compile_error(PARSER_ARG  mesg)
+#endif
+	    literal_flush(lex_p);
 	    if (func & STR_FUNC_REGEXP) {
-		compile_error(PARSER_ARG "unterminated regexp meets end of file");
+		unterminated_literal("unterminated regexp meets end of file");
 	    }
 	    else {
-		compile_error(PARSER_ARG "unterminated string meets end of file");
+		unterminated_literal("unterminated string meets end of file");
 	    }
 	    quote->nd_func |= STR_FUNC_TERM;
 	}

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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