bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 5/5] c++: demonstrate custom error messages in the examples


From: Akim Demaille
Subject: [PATCH 5/5] c++: demonstrate custom error messages in the examples
Date: Sun, 12 Sep 2021 12:05:49 +0200

Let's use c++/glr to demonstrate custom error messages in C++ (not
just in glr2.cc).

* examples/c++/glr/c++-types.yy (report_syntax_error): New.
* examples/c++/glr/c++-types.test: Adjust.
* examples/c/bistromathic/parse.y: Comment changes.
* tests/local.at (AT_YYERROR_DEFINE(c++)): Use a nicer way to print
the lookakead's name.
---
 examples/c++/README.md          |  9 +++++++
 examples/c++/glr/README.md      |  3 +++
 examples/c++/glr/c++-types.test |  2 +-
 examples/c++/glr/c++-types.yy   | 43 ++++++++++++++++++++++++++++++---
 examples/c/bistromathic/parse.y |  5 ++--
 tests/local.at                  |  7 ++----
 6 files changed, 58 insertions(+), 11 deletions(-)

diff --git a/examples/c++/README.md b/examples/c++/README.md
index 93cd09d5..dff3783e 100644
--- a/examples/c++/README.md
+++ b/examples/c++/README.md
@@ -39,6 +39,15 @@ examples.
 Extracted from the documentation: [A Complete C++
 
Example](https://www.gnu.org/software/bison/manual/html_node/A-Complete-C_002b_002b-Example.html).
 
+## glr
+
+This example demonstrates the use of GLR parsers to handle (local)
+ambiguities in the C++ language.  See the node "Merging GLR Parses" in
+Bison's documentation.
+
+It uses (Bison) variants to store objects as semantic values.  It also
+demonstrates custom error messages in C++.
+
 <!---
 
 Local Variables:
diff --git a/examples/c++/glr/README.md b/examples/c++/glr/README.md
index 26067c27..ed06a0c6 100644
--- a/examples/c++/glr/README.md
+++ b/examples/c++/glr/README.md
@@ -4,6 +4,9 @@ This example demonstrates the use of GLR parsers to handle 
(local)
 ambiguities in the C++ language.  See the node "Merging GLR Parses" in
 Bison's documentation.
 
+It uses (Bison) variants to store objects as semantic values.  It also
+demonstrates custom error messages in C++.
+
 <!---
 Local Variables:
 fill-column: 76
diff --git a/examples/c++/glr/c++-types.test b/examples/c++/glr/c++-types.test
index 7440ea24..db5be8d7 100644
--- a/examples/c++/glr/c++-types.test
+++ b/examples/c++/glr/c++-types.test
@@ -47,4 +47,4 @@ run 0 "\
 5.0-13: <OR>(<init-declare>(T, y, +(z, q)), =(<cast>(y, T), +(z, q)))
 7.0-15: <error>
 9.0-5: +(z, q)
-err: 7.5: syntax error, unexpected identifier, expecting = or + or )"
+err: 7.5: syntax error on token identifier (expected = or + or ))"
diff --git a/examples/c++/glr/c++-types.yy b/examples/c++/glr/c++-types.yy
index fa8889de..a3131b05 100644
--- a/examples/c++/glr/c++-types.yy
+++ b/examples/c++/glr/c++-types.yy
@@ -27,8 +27,8 @@
 %locations
 %debug
 
-// Nice error messages with details.
-%define parse.error detailed
+// Custom error messages.
+%define parse.error custom
 
 %code requires
 {
@@ -44,9 +44,11 @@
   #include <fstream>
   #include <cstring>
 
+  // Merge two semantic values.
   static Node
   stmt_merge (const Node& x0, const Node& x1);
 
+  // Fetch a token.
   static yy::parser::symbol_type
   yylex ();
 }
@@ -100,13 +102,41 @@ declarator
 std::istream* input = nullptr;
 yy::parser::location_type loc;
 
-// An error reporting function.
+
+/*---------.
+| Parser.  |
+`---------*/
+
+// Generate a custom error message.
+void
+yy::parser::report_syntax_error (const context& ctx) const
+{
+  std::cerr << ctx.location () << ": syntax error";
+  if (!ctx.lookahead ().empty ())
+    std::cerr << " on token " << ctx.lookahead ().name ();
+  {
+    enum { TOKENMAX = 10 };
+    symbol_kind_type expected[TOKENMAX];
+    int n = ctx.expected_tokens (expected, TOKENMAX);
+    if (0 < n)
+      {
+        for (int i = 0; i < n; ++i)
+          std::cerr << (i == 0 ? " (expected " : " or ")
+                    << symbol_name (expected[i]);
+        std::cerr << ')';
+      }
+  }
+  std::cerr << '\n';
+}
+
+// Report the error to the user.
 void
 yy::parser::error (const location_type& l, const std::string& m)
 {
   std::cerr << l << ": " << m << '\n';
 }
 
+// Fetch the next token.
 static yy::parser::symbol_type
 yylex ()
 {
@@ -168,12 +198,19 @@ yylex ()
     }
 }
 
+// Merge two semantic values as an AST including both alternatives.
 static Node
 stmt_merge (const Node& x0, const Node& x1)
 {
   return Nterm ("<OR>", x0, x1);
 }
 
+
+/*-------.
+| Main.  |
+`-------*/
+
+// Parse `file` using parser `parse`.
 int
 process (yy::parser& parse, const std::string& file)
 {
diff --git a/examples/c/bistromathic/parse.y b/examples/c/bistromathic/parse.y
index e06db523..8b1591e6 100644
--- a/examples/c/bistromathic/parse.y
+++ b/examples/c/bistromathic/parse.y
@@ -465,8 +465,9 @@ yyreport_syntax_error (const yypcontext_t *ctx, const 
user_context *uctx)
 }
 
 
-// Called by yyparse on error.
-void yyerror (const YYLTYPE *loc, const user_context *uctx, char const 
*format, ...)
+// Called by yyparse on errors to report the error to the user.
+void
+yyerror (const YYLTYPE *loc, const user_context *uctx, char const *format, ...)
 {
   if (uctx->silent)
     return;
diff --git a/tests/local.at b/tests/local.at
index 170e5da1..1138df47 100644
--- a/tests/local.at
+++ b/tests/local.at
@@ -823,11 +823,8 @@ m4_define([AT_YYERROR_DEFINE(c++)],
   ++*nerrs;]])[]AT_LOCATION_IF([[
   std::cerr << ctx.location () << ": ";]])[
   std::cerr << "syntax error";
-  {
-    symbol_kind_type la = ctx.token ();
-    if (la != symbol_kind::S_YYEMPTY)
-      std::cerr << " on token [" << symbol_name (la) << ']';
-  }
+  if (!ctx.lookahead ().empty ())
+    std::cerr << " on token [" << ctx.lookahead ().name () << ']';
   {
     enum { TOKENMAX = 10 };
     symbol_kind_type expected[TOKENMAX];
-- 
2.32.0




reply via email to

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