diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-07-17 00:11:38 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-07-17 00:11:38 +0000 |
commit | 0a04e9f42777fc9beb3b866034d6b52a0606ef83 (patch) | |
tree | 9509af81484fa953240e12d88fc527b8f6d8e56d | |
parent | 3ae53aa5f8eb9664690e07857db60b21500fd07d (diff) | |
download | ruby-0a04e9f42777fc9beb3b866034d6b52a0606ef83.tar.gz |
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.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59349 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | parse.y | 36 | ||||
-rw-r--r-- | test/ruby/test_parse.rb | 18 |
2 files changed, 37 insertions, 17 deletions
@@ -5042,15 +5042,15 @@ parser_yyerror(struct parser_params *parser, const char *msg) 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 *parser, const char *msg) 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 *parser, rb_encoding **encp, 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 *parser, NODE *quote) if (tokadd_string(func, term, paren, "e->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; } diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index 7ce236679c..982f91dc52 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -489,11 +489,23 @@ class TestParse < Test::Unit::TestCase 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) |