mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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
This commit is contained in:
parent
b17efb6874
commit
28695a8fff
2 changed files with 37 additions and 17 deletions
36
parse.y
36
parse.y
|
@ -5042,15 +5042,15 @@ parser_yyerror(struct parser_params *parser, const char *msg)
|
||||||
long len;
|
long len;
|
||||||
int i;
|
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;
|
pend = lex_pend;
|
||||||
if (pend > lex_pbeg && pend[-1] == '\n') {
|
if (pend > lex_pbeg && pend[-1] == '\n') {
|
||||||
if (--pend > lex_pbeg && pend[-1] == '\r') --pend;
|
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;
|
lim = pend - pe > max_line_margin ? pe + max_line_margin : pend;
|
||||||
while ((pe < lim) && (*pe != '\n')) pe++;
|
while ((pe < lim) && (*pe != '\n')) pe++;
|
||||||
|
|
||||||
|
@ -5067,20 +5067,22 @@ parser_yyerror(struct parser_params *parser, const char *msg)
|
||||||
if (pe < pend) post = "...";
|
if (pe < pend) post = "...";
|
||||||
}
|
}
|
||||||
len = pe - p;
|
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);
|
buf = ALLOCA_N(char, i+2);
|
||||||
code = p;
|
code = p;
|
||||||
caret = p2 = buf;
|
caret = p2 = buf;
|
||||||
if (p <= parser->tokp) {
|
pe = (parser->tokp < lim ? parser->tokp : lim);
|
||||||
while (p < parser->tokp) {
|
if (p <= pe) {
|
||||||
|
while (p < pe) {
|
||||||
*p2++ = *p++ == '\t' ? '\t' : ' ';
|
*p2++ = *p++ == '\t' ? '\t' : ' ';
|
||||||
}
|
}
|
||||||
*p2++ = '^';
|
*p2++ = '^';
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
if (lex_p > p) {
|
if (lim > p) {
|
||||||
memset(p2, '~', (lex_p - p));
|
memset(p2, '~', (lim - p));
|
||||||
p2 += (lex_p - p);
|
p2 += (lim - p);
|
||||||
}
|
}
|
||||||
*p2 = '\0';
|
*p2 = '\0';
|
||||||
newline = "\n";
|
newline = "\n";
|
||||||
|
@ -5711,7 +5713,7 @@ parser_tokadd_utf8(struct parser_params *parser, rb_encoding **encp,
|
||||||
while (!string_literal || c != close_brace) {
|
while (!string_literal || c != close_brace) {
|
||||||
if (regexp_literal) tokadd(last);
|
if (regexp_literal) tokadd(last);
|
||||||
if (!parser_tokadd_codepoint(parser, encp, regexp_literal, TRUE)) {
|
if (!parser_tokadd_codepoint(parser, encp, regexp_literal, TRUE)) {
|
||||||
return 0;
|
break;
|
||||||
}
|
}
|
||||||
while (ISSPACE(c = *lex_p)) {
|
while (ISSPACE(c = *lex_p)) {
|
||||||
if (++lex_p >= lex_pend) goto unterminated;
|
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,
|
if (tokadd_string(func, term, paren, "e->nd_nest,
|
||||||
&enc) == -1) {
|
&enc) == -1) {
|
||||||
if (parser->eofp) {
|
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) {
|
if (func & STR_FUNC_REGEXP) {
|
||||||
compile_error(PARSER_ARG "unterminated regexp meets end of file");
|
unterminated_literal("unterminated regexp meets end of file");
|
||||||
}
|
}
|
||||||
else {
|
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;
|
quote->nd_func |= STR_FUNC_TERM;
|
||||||
}
|
}
|
||||||
|
|
|
@ -489,11 +489,23 @@ class TestParse < Test::Unit::TestCase
|
||||||
e = assert_syntax_error('"\xg1"', /hex escape/)
|
e = assert_syntax_error('"\xg1"', /hex escape/)
|
||||||
assert_equal(' ^', e.message.lines.last, mesg)
|
assert_equal(' ^', e.message.lines.last, mesg)
|
||||||
|
|
||||||
e = assert_syntax_error('"\u{1234"', 'Unicode escape')
|
e = assert_syntax_error('"\u{1234"', 'unterminated Unicode escape')
|
||||||
assert_match(' ^', e.message.lines.last, mesg)
|
assert_equal(' ^', e.message.lines.last, mesg)
|
||||||
|
|
||||||
e = assert_syntax_error('"\u{xxxx}"', 'invalid Unicode escape')
|
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/)
|
e = assert_syntax_error('"\M1"', /escape character syntax/)
|
||||||
assert_equal(' ^~~', e.message.lines.last, mesg)
|
assert_equal(' ^~~', e.message.lines.last, mesg)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue