bison-patches
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]