mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
c++: demonstrate custom error messages in the examples
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.
This commit is contained in:
@@ -39,6 +39,15 @@ examples.
|
|||||||
Extracted from the documentation: [A Complete C++
|
Extracted from the documentation: [A Complete C++
|
||||||
Example](https://www.gnu.org/software/bison/manual/html_node/A-Complete-C_002b_002b-Example.html).
|
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:
|
Local Variables:
|
||||||
|
|||||||
@@ -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
|
ambiguities in the C++ language. See the node "Merging GLR Parses" in
|
||||||
Bison's documentation.
|
Bison's documentation.
|
||||||
|
|
||||||
|
It uses (Bison) variants to store objects as semantic values. It also
|
||||||
|
demonstrates custom error messages in C++.
|
||||||
|
|
||||||
<!---
|
<!---
|
||||||
Local Variables:
|
Local Variables:
|
||||||
fill-column: 76
|
fill-column: 76
|
||||||
|
|||||||
@@ -47,4 +47,4 @@ run 0 "\
|
|||||||
5.0-13: <OR>(<init-declare>(T, y, +(z, q)), =(<cast>(y, T), +(z, q)))
|
5.0-13: <OR>(<init-declare>(T, y, +(z, q)), =(<cast>(y, T), +(z, q)))
|
||||||
7.0-15: <error>
|
7.0-15: <error>
|
||||||
9.0-5: +(z, q)
|
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 ))"
|
||||||
|
|||||||
@@ -27,8 +27,8 @@
|
|||||||
%locations
|
%locations
|
||||||
%debug
|
%debug
|
||||||
|
|
||||||
// Nice error messages with details.
|
// Custom error messages.
|
||||||
%define parse.error detailed
|
%define parse.error custom
|
||||||
|
|
||||||
%code requires
|
%code requires
|
||||||
{
|
{
|
||||||
@@ -44,9 +44,11 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
// Merge two semantic values.
|
||||||
static Node
|
static Node
|
||||||
stmt_merge (const Node& x0, const Node& x1);
|
stmt_merge (const Node& x0, const Node& x1);
|
||||||
|
|
||||||
|
// Fetch a token.
|
||||||
static yy::parser::symbol_type
|
static yy::parser::symbol_type
|
||||||
yylex ();
|
yylex ();
|
||||||
}
|
}
|
||||||
@@ -100,13 +102,41 @@ declarator
|
|||||||
std::istream* input = nullptr;
|
std::istream* input = nullptr;
|
||||||
yy::parser::location_type loc;
|
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
|
void
|
||||||
yy::parser::error (const location_type& l, const std::string& m)
|
yy::parser::error (const location_type& l, const std::string& m)
|
||||||
{
|
{
|
||||||
std::cerr << l << ": " << m << '\n';
|
std::cerr << l << ": " << m << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch the next token.
|
||||||
static yy::parser::symbol_type
|
static yy::parser::symbol_type
|
||||||
yylex ()
|
yylex ()
|
||||||
{
|
{
|
||||||
@@ -168,12 +198,19 @@ yylex ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge two semantic values as an AST including both alternatives.
|
||||||
static Node
|
static Node
|
||||||
stmt_merge (const Node& x0, const Node& x1)
|
stmt_merge (const Node& x0, const Node& x1)
|
||||||
{
|
{
|
||||||
return Nterm ("<OR>", x0, x1);
|
return Nterm ("<OR>", x0, x1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-------.
|
||||||
|
| Main. |
|
||||||
|
`-------*/
|
||||||
|
|
||||||
|
// Parse `file` using parser `parse`.
|
||||||
int
|
int
|
||||||
process (yy::parser& parse, const std::string& file)
|
process (yy::parser& parse, const std::string& file)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -465,8 +465,9 @@ yyreport_syntax_error (const yypcontext_t *ctx, const user_context *uctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Called by yyparse on error.
|
// Called by yyparse on errors to report the error to the user.
|
||||||
void yyerror (const YYLTYPE *loc, const user_context *uctx, char const *format, ...)
|
void
|
||||||
|
yyerror (const YYLTYPE *loc, const user_context *uctx, char const *format, ...)
|
||||||
{
|
{
|
||||||
if (uctx->silent)
|
if (uctx->silent)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -823,11 +823,8 @@ void
|
|||||||
++*nerrs;]])[]AT_LOCATION_IF([[
|
++*nerrs;]])[]AT_LOCATION_IF([[
|
||||||
std::cerr << ctx.location () << ": ";]])[
|
std::cerr << ctx.location () << ": ";]])[
|
||||||
std::cerr << "syntax error";
|
std::cerr << "syntax error";
|
||||||
{
|
if (!ctx.lookahead ().empty ())
|
||||||
symbol_kind_type la = ctx.token ();
|
std::cerr << " on token [" << ctx.lookahead ().name () << ']';
|
||||||
if (la != symbol_kind::S_YYEMPTY)
|
|
||||||
std::cerr << " on token [" << symbol_name (la) << ']';
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
enum { TOKENMAX = 10 };
|
enum { TOKENMAX = 10 };
|
||||||
symbol_kind_type expected[TOKENMAX];
|
symbol_kind_type expected[TOKENMAX];
|
||||||
|
|||||||
Reference in New Issue
Block a user