[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 4/4] bistromathic: demonstrate caret-diagnostics
From: |
Akim Demaille |
Subject: |
[PATCH 4/4] bistromathic: demonstrate caret-diagnostics |
Date: |
Sat, 11 Jul 2020 18:08:19 +0200 |
* 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.
---
NEWS | 11 ++++++
TODO | 2 -
examples/c/README.md | 11 +++++-
examples/c/bistromathic/README.md | 11 +++++-
examples/c/bistromathic/bistromathic.test | 46 ++++++++++++++++++++---
examples/c/bistromathic/parse.y | 18 +++++++--
6 files changed, 86 insertions(+), 13 deletions(-)
diff --git a/NEWS b/NEWS
index 04a7c264..38cf60c8 100644
--- a/NEWS
+++ b/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]
diff --git a/TODO b/TODO
index 38853a95..59c08564 100644
--- a/TODO
+++ b/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
diff --git a/examples/c/README.md b/examples/c/README.md
index 7d2cb2ac..aa7461f8 100644
--- a/examples/c/README.md
+++ b/examples/c/README.md
@@ -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.
diff --git a/examples/c/bistromathic/README.md
b/examples/c/bistromathic/README.md
index 6b66299e..5147cea4 100644
--- a/examples/c/bistromathic/README.md
+++ b/examples/c/bistromathic/README.md
@@ -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.
diff --git a/examples/c/bistromathic/bistromathic.test
b/examples/c/bistromathic/bistromathic.test
index 74e8db9c..b0a30365 100755
--- a/examples/c/bistromathic/bistromathic.test
+++ b/examples/c/bistromathic/bistromathic.test
@@ -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: | ^
'
diff --git a/examples/c/bistromathic/parse.y b/examples/c/bistromathic/parse.y
index 0dca4ae0..718ec904 100644
--- a/examples/c/bistromathic/parse.y
+++ b/examples/c/bistromathic/parse.y
@@ -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 ();
--
2.27.0