mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 20:33:03 +00:00
bistromathic: demonstrate caret-diagnostics
* examples/c/bistromathic/parse.y (user_context): We need the current line. (yyreport_syntax_error): Quote the guilty line, with squiggles. * examples/c/bistromathic/bistromathic.test: Adjust.
This commit is contained in:
11
NEWS
11
NEWS
@@ -2,6 +2,17 @@ GNU Bison NEWS
|
||||
|
||||
* Noteworthy changes in release ?.? (????-??-??) [?]
|
||||
|
||||
** Documentation
|
||||
|
||||
*** Examples
|
||||
|
||||
The bistromathic demonstrates %param and how to quote sources in the error
|
||||
messages:
|
||||
|
||||
> 123 456
|
||||
1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number
|
||||
1 | 123 456
|
||||
| ^~~
|
||||
|
||||
* Noteworthy changes in release 3.6.91 (2020-07-09) [beta]
|
||||
|
||||
|
||||
2
TODO
2
TODO
@@ -36,8 +36,6 @@ Unless we play it dumb (little structure).
|
||||
- How about not evaluating incomplete lines when the text is not finished
|
||||
(as shells do).
|
||||
|
||||
- Caret diagnostics
|
||||
|
||||
** Questions
|
||||
*** Java
|
||||
- Should i18n be part of the Lexer? Currently it's a static method of
|
||||
|
||||
@@ -53,7 +53,9 @@ push-parser model.
|
||||
This example demonstrates best practices when using Bison.
|
||||
- Its hand-written scanner tracks locations.
|
||||
- Its interface is pure.
|
||||
- It uses the `error` token to get error recovery.
|
||||
- It uses %params to pass user information to the parser and scanner.
|
||||
- Its scanner uses the `error` token to signal lexical errors and enter
|
||||
error recovery.
|
||||
- Its interface is "incremental", well suited for interaction: it uses the
|
||||
push-parser API to feed the parser with the incoming tokens.
|
||||
- It features an interactive command line with completion based on the
|
||||
@@ -62,6 +64,13 @@ This example demonstrates best practices when using Bison.
|
||||
messages.
|
||||
- It uses a custom syntax error with location, lookahead correction and
|
||||
token internationalization.
|
||||
- Error messages quote the source with squiggles that underline the error:
|
||||
```
|
||||
> 123 456
|
||||
1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number
|
||||
1 | 123 456
|
||||
| ^~~
|
||||
```
|
||||
- It supports debug traces with semantic values.
|
||||
- It uses named references instead of the traditional $1, $2, etc.
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
This example demonstrates best practices when using Bison.
|
||||
- Its hand-written scanner tracks locations.
|
||||
- Its interface is pure.
|
||||
- It uses the `error` token to get error recovery.
|
||||
- It uses %params to pass user information to the parser and scanner.
|
||||
- Its scanner uses the `error` token to signal lexical errors and enter
|
||||
error recovery.
|
||||
- Its interface is "incremental", well suited for interaction: it uses the
|
||||
push-parser API to feed the parser with the incoming tokens.
|
||||
- It features an interactive command line with completion based on the
|
||||
@@ -11,6 +13,13 @@ This example demonstrates best practices when using Bison.
|
||||
messages.
|
||||
- It uses a custom syntax error with location, lookahead correction and
|
||||
token internationalization.
|
||||
- Error messages quote the source with squiggles that underline the error:
|
||||
```
|
||||
> 123 456
|
||||
1.5-7: syntax error: expected end of file or + or - or * or / or ^ before number
|
||||
1 | 123 456
|
||||
| ^~~
|
||||
```
|
||||
- It supports debug traces with semantic values.
|
||||
- It uses named references instead of the traditional $1, $2, etc.
|
||||
|
||||
|
||||
@@ -101,14 +101,28 @@ cat >input <<EOF
|
||||
EOF
|
||||
run 0 '> *
|
||||
> ''
|
||||
err: 1.1: syntax error: expected end of file or - or ( or exit or number or function etc., before *'
|
||||
err: 1.1: syntax error: expected end of file or - or ( or exit or number or function etc., before *
|
||||
err: 1 | *
|
||||
err: | ^'
|
||||
|
||||
# Underline long errors.
|
||||
cat >input <<EOF
|
||||
123 123456
|
||||
EOF
|
||||
run 0 '> 123 123456
|
||||
> ''
|
||||
err: 1.5-10: syntax error: expected end of file or + or - or * or / or ^ before number
|
||||
err: 1 | 123 123456
|
||||
err: | ^~~~~~'
|
||||
|
||||
cat >input <<EOF
|
||||
1 + 2 * * 3
|
||||
EOF
|
||||
run 0 '> 1 + 2 * * 3
|
||||
> ''
|
||||
err: 1.9: syntax error: expected - or ( or number or function or variable before *'
|
||||
err: 1.9: syntax error: expected - or ( or number or function or variable before *
|
||||
err: 1 | 1 + 2 * * 3
|
||||
err: | ^'
|
||||
|
||||
cat >input <<EOF
|
||||
1 / 0
|
||||
@@ -132,8 +146,14 @@ run 0 '> ((1 ++ 2) ** 3)
|
||||
1332
|
||||
> ''
|
||||
err: 1.6: syntax error: expected - or ( or number or function or variable before +
|
||||
err: 1 | ((1 ++ 2) ** 3)
|
||||
err: | ^
|
||||
err: 2.5: syntax error: expected - or ( or number or function or variable before +
|
||||
err: 2.16: syntax error: expected - or ( or number or function or variable before *'
|
||||
err: 2 | (1 ++ 2) + (3 ** 4)
|
||||
err: | ^
|
||||
err: 2.16: syntax error: expected - or ( or number or function or variable before *
|
||||
err: 2 | (1 ++ 2) + (3 ** 4)
|
||||
err: | ^'
|
||||
|
||||
# The rule "( error )" should work even if there are no tokens between "(" and ")".
|
||||
cat >input <<EOF
|
||||
@@ -142,7 +162,9 @@ EOF
|
||||
run 0 '> ()
|
||||
666
|
||||
> ''
|
||||
err: 1.2: syntax error: expected - or ( or number or function or variable before )'
|
||||
err: 1.2: syntax error: expected - or ( or number or function or variable before )
|
||||
err: 1 | ()
|
||||
err: | ^'
|
||||
|
||||
|
||||
cat >input <<EOF
|
||||
@@ -189,6 +211,8 @@ err: LAC: checking lookahead function: S5
|
||||
err: LAC: checking lookahead variable: S6
|
||||
err: LAC: checking lookahead NEG: Err
|
||||
err: 1.2: syntax error: expected - or ( or number or function or variable before +
|
||||
err: 1 | (+_)
|
||||
err: | ^
|
||||
err: LAC: initial context discarded due to error recovery
|
||||
err: Shifting token error (1.2: )
|
||||
err: Entering state 10
|
||||
@@ -286,7 +310,9 @@ run 0 '> (1+
|
||||
( - atan cos exp ln number sin sqrt
|
||||
> (1+
|
||||
> ''
|
||||
err: 1.4: syntax error: expected - or ( or number or function or variable before end of file'
|
||||
err: 1.4: syntax error: expected - or ( or number or function or variable before end of file
|
||||
err: 1 | (1+
|
||||
err: | ^'
|
||||
|
||||
# Check the completion of a word.
|
||||
sed -e 's/\\t/ /g' >input <<EOF
|
||||
@@ -294,7 +320,9 @@ sed -e 's/\\t/ /g' >input <<EOF
|
||||
EOF
|
||||
run 0 '> (atan ( ''
|
||||
> ''
|
||||
err: 1.9: syntax error: expected - or ( or number or function or variable before end of file'
|
||||
err: 1.9: syntax error: expected - or ( or number or function or variable before end of file
|
||||
err: 1 | (atan ( ''
|
||||
err: | ^'
|
||||
|
||||
# Check the completion at the very beginning.
|
||||
sed -e 's/\\t/ /g' >input <<EOF
|
||||
@@ -314,6 +342,8 @@ EOF
|
||||
run -n 0 '> 1++ ''
|
||||
> ''
|
||||
err: 1.3: syntax error: expected - or ( or number or function or variable before +
|
||||
err: 1 | 1++ ''
|
||||
err: | ^
|
||||
'
|
||||
|
||||
# And even when the error was recovered from.
|
||||
@@ -323,5 +353,9 @@ EOF
|
||||
run -n 0 '> (1++2) + 3 + ''
|
||||
> ''
|
||||
err: 1.4: syntax error: expected - or ( or number or function or variable before +
|
||||
err: 1 | (1++2) + 3 + ''
|
||||
err: | ^
|
||||
err: 1.15: syntax error: expected - or ( or number or function or variable before end of file
|
||||
err: 1 | (1++2) + 3 + ''
|
||||
err: | ^
|
||||
'
|
||||
|
||||
@@ -71,6 +71,8 @@
|
||||
{
|
||||
// Whether to not emit error messages.
|
||||
int silent;
|
||||
// The current input line.
|
||||
const char *line;
|
||||
} user_context;
|
||||
}
|
||||
|
||||
@@ -396,11 +398,12 @@ yyreport_syntax_error (const yypcontext_t *ctx, const user_context *uctx)
|
||||
argsize = ARGS_MAX;
|
||||
const char *format = error_format_string (1 + argsize + too_many_expected_tokens);
|
||||
|
||||
const YYLTYPE *loc = yypcontext_location (ctx);
|
||||
while (*format)
|
||||
// %@: location.
|
||||
if (format[0] == '%' && format[1] == '@')
|
||||
{
|
||||
YY_LOCATION_PRINT (stderr, *yypcontext_location (ctx));
|
||||
YY_LOCATION_PRINT (stderr, *loc);
|
||||
format += 2;
|
||||
}
|
||||
// %u: unexpected token.
|
||||
@@ -425,6 +428,15 @@ yyreport_syntax_error (const yypcontext_t *ctx, const user_context *uctx)
|
||||
++format;
|
||||
}
|
||||
fputc ('\n', stderr);
|
||||
|
||||
// Quote the source line.
|
||||
{
|
||||
fprintf (stderr, "%5d | %s\n", loc->first_line, uctx->line);
|
||||
fprintf (stderr, "%5s | %*s", "", loc->first_column, "^");
|
||||
for (int i = loc->last_column - loc->first_column - 1; 0 < i; --i)
|
||||
putc ('~', stderr);
|
||||
putc ('\n', stderr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -470,7 +482,7 @@ xstrndup (const char *string, size_t n)
|
||||
static int
|
||||
process_line (YYLTYPE *lloc, const char *line)
|
||||
{
|
||||
user_context uctx = {0};
|
||||
user_context uctx = {0, line};
|
||||
yypstate *ps = yypstate_new ();
|
||||
int status = 0;
|
||||
do {
|
||||
@@ -491,7 +503,7 @@ expected_tokens (const char *input,
|
||||
int *tokens, int ntokens)
|
||||
{
|
||||
YYDPRINTF ((stderr, "expected_tokens (\"%s\")", input));
|
||||
user_context uctx = {1};
|
||||
user_context uctx = {1, input};
|
||||
|
||||
// Parse the current state of the line.
|
||||
yypstate *ps = yypstate_new ();
|
||||
|
||||
Reference in New Issue
Block a user