Skip to content

Commit 2142e59

Browse files
committed
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.
1 parent a750724 commit 2142e59

File tree

6 files changed

+58
-11
lines changed

6 files changed

+58
-11
lines changed

examples/c++/README.md

+9
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@ examples.
3939
Extracted from the documentation: [A Complete C++
4040
Example](https://www.gnu.org/software/bison/manual/html_node/A-Complete-C_002b_002b-Example.html).
4141

42+
## glr
43+
44+
This example demonstrates the use of GLR parsers to handle (local)
45+
ambiguities in the C++ language. See the node "Merging GLR Parses" in
46+
Bison's documentation.
47+
48+
It uses (Bison) variants to store objects as semantic values. It also
49+
demonstrates custom error messages in C++.
50+
4251
<!---
4352
4453
Local Variables:

examples/c++/glr/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ This example demonstrates the use of GLR parsers to handle (local)
44
ambiguities in the C++ language. See the node "Merging GLR Parses" in
55
Bison's documentation.
66

7+
It uses (Bison) variants to store objects as semantic values. It also
8+
demonstrates custom error messages in C++.
9+
710
<!---
811
Local Variables:
912
fill-column: 76

examples/c++/glr/c++-types.test

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,4 @@ run 0 "\
4747
5.0-13: <OR>(<init-declare>(T, y, +(z, q)), =(<cast>(y, T), +(z, q)))
4848
7.0-15: <error>
4949
9.0-5: +(z, q)
50-
err: 7.5: syntax error, unexpected identifier, expecting = or + or )"
50+
err: 7.5: syntax error on token identifier (expected = or + or ))"

examples/c++/glr/c++-types.yy

+40-3
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
%locations
2828
%debug
2929

30-
// Nice error messages with details.
31-
%define parse.error detailed
30+
// Custom error messages.
31+
%define parse.error custom
3232

3333
%code requires
3434
{
@@ -44,9 +44,11 @@
4444
#include <fstream>
4545
#include <cstring>
4646

47+
// Merge two semantic values.
4748
static Node
4849
stmt_merge (const Node& x0, const Node& x1);
4950

51+
// Fetch a token.
5052
static yy::parser::symbol_type
5153
yylex ();
5254
}
@@ -100,13 +102,41 @@ declarator
100102
std::istream* input = nullptr;
101103
yy::parser::location_type loc;
102104

103-
// An error reporting function.
105+
106+
/*---------.
107+
| Parser. |
108+
`---------*/
109+
110+
// Generate a custom error message.
111+
void
112+
yy::parser::report_syntax_error (const context& ctx) const
113+
{
114+
std::cerr << ctx.location () << ": syntax error";
115+
if (!ctx.lookahead ().empty ())
116+
std::cerr << " on token " << ctx.lookahead ().name ();
117+
{
118+
enum { TOKENMAX = 10 };
119+
symbol_kind_type expected[TOKENMAX];
120+
int n = ctx.expected_tokens (expected, TOKENMAX);
121+
if (0 < n)
122+
{
123+
for (int i = 0; i < n; ++i)
124+
std::cerr << (i == 0 ? " (expected " : " or ")
125+
<< symbol_name (expected[i]);
126+
std::cerr << ')';
127+
}
128+
}
129+
std::cerr << '\n';
130+
}
131+
132+
// Report the error to the user.
104133
void
105134
yy::parser::error (const location_type& l, const std::string& m)
106135
{
107136
std::cerr << l << ": " << m << '\n';
108137
}
109138

139+
// Fetch the next token.
110140
static yy::parser::symbol_type
111141
yylex ()
112142
{
@@ -168,12 +198,19 @@ yylex ()
168198
}
169199
}
170200

201+
// Merge two semantic values as an AST including both alternatives.
171202
static Node
172203
stmt_merge (const Node& x0, const Node& x1)
173204
{
174205
return Nterm ("<OR>", x0, x1);
175206
}
176207

208+
209+
/*-------.
210+
| Main. |
211+
`-------*/
212+
213+
// Parse `file` using parser `parse`.
177214
int
178215
process (yy::parser& parse, const std::string& file)
179216
{

examples/c/bistromathic/parse.y

+3-2
Original file line numberDiff line numberDiff line change
@@ -465,8 +465,9 @@ yyreport_syntax_error (const yypcontext_t *ctx, const user_context *uctx)
465465
}
466466

467467

468-
// Called by yyparse on error.
469-
void yyerror (const YYLTYPE *loc, const user_context *uctx, char const *format, ...)
468+
// Called by yyparse on errors to report the error to the user.
469+
void
470+
yyerror (const YYLTYPE *loc, const user_context *uctx, char const *format, ...)
470471
{
471472
if (uctx->silent)
472473
return;

tests/local.at

+2-5
Original file line numberDiff line numberDiff line change
@@ -823,11 +823,8 @@ void
823823
++*nerrs;]])[]AT_LOCATION_IF([[
824824
std::cerr << ctx.location () << ": ";]])[
825825
std::cerr << "syntax error";
826-
{
827-
symbol_kind_type la = ctx.token ();
828-
if (la != symbol_kind::S_YYEMPTY)
829-
std::cerr << " on token [" << symbol_name (la) << ']';
830-
}
826+
if (!ctx.lookahead ().empty ())
827+
std::cerr << " on token [" << ctx.lookahead ().name () << ']';
831828
{
832829
enum { TOKENMAX = 10 };
833830
symbol_kind_type expected[TOKENMAX];

0 commit comments

Comments
 (0)