mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-09 12:23:04 +00:00
doc: c++: document parser::context
* doc/bison.texi (C++ Parser Context): New. * data/skeletons/lalr1.cc (parser::yysymbol_name): Rename as... (parser::symbol_name): this. (A Complete C++ Example): Promote LAC, now that we have it. Promote parse.error detailed over verbose. * examples/c++/calc++/calc++.test, tests/local.at: Adjust.
This commit is contained in:
@@ -308,7 +308,7 @@ m4_define([b4_shared_declarations],
|
||||
]b4_parse_error_bmatch([custom\|detailed], [[
|
||||
/// The user-facing name of the symbol whose (internal) number is
|
||||
/// YYSYMBOL. No bounds checking.
|
||||
static const char *yysymbol_name (symbol_kind_type yysymbol);
|
||||
static const char *symbol_name (symbol_kind_type yysymbol);
|
||||
]])[
|
||||
|
||||
// Tables.
|
||||
@@ -586,7 +586,7 @@ m4_if(b4_prefix, [yy], [],
|
||||
/* The user-facing name of the symbol whose (internal) number is
|
||||
YYSYMBOL. No bounds checking. */
|
||||
const char *
|
||||
]b4_parser_class[::yysymbol_name (symbol_kind_type yysymbol)
|
||||
]b4_parser_class[::symbol_name (symbol_kind_type yysymbol)
|
||||
{
|
||||
static const char *const yy_sname[] =
|
||||
{
|
||||
@@ -1503,7 +1503,7 @@ b4_dollar_popdef])[]dnl
|
||||
{
|
||||
yyres += ]b4_parse_error_case([verbose],
|
||||
[[yytnamerr_ (yytname_[yyarg[yyi++]])]],
|
||||
[[yysymbol_name (yyarg[yyi++])]])[;
|
||||
[[symbol_name (yyarg[yyi++])]])[;
|
||||
++yyp;
|
||||
}
|
||||
else
|
||||
|
||||
134
doc/bison.texi
134
doc/bison.texi
@@ -325,8 +325,8 @@ The Lexical Analyzer Function @code{yylex}
|
||||
|
||||
Error Reporting
|
||||
|
||||
* Error Reporting Function:: You must supply a function @code{yyerror}.
|
||||
* Syntax Error Reporting Function:: You can supply a function @code{yyreport_syntax_error}.
|
||||
* Error Reporting Function:: You must supply a @code{yyerror} function.
|
||||
* Syntax Error Reporting Function:: You can supply a @code{yyreport_syntax_error} function.
|
||||
|
||||
Parser Internationalization
|
||||
|
||||
@@ -408,6 +408,7 @@ C++ Parsers
|
||||
* C++ Parser Interface:: Instantiating and running the parser
|
||||
* C++ Semantic Values:: %union vs. C++
|
||||
* C++ Location Values:: The position and location classes
|
||||
* C++ Parser Context:: You can supply a @code{report_syntax_error} function.
|
||||
* C++ Scanner Interface:: Exchanges between yylex and parse
|
||||
* A Complete C++ Example:: Demonstrating their use
|
||||
|
||||
@@ -7352,8 +7353,8 @@ such as syntax error, or memory exhaustion. How this message is delivered
|
||||
to the user must be specified by the developer.
|
||||
|
||||
@menu
|
||||
* Error Reporting Function:: You must supply a function @code{yyerror}.
|
||||
* Syntax Error Reporting Function:: You can supply a function @code{yyreport_syntax_error}.
|
||||
* Error Reporting Function:: You must supply a @code{yyerror} function.
|
||||
* Syntax Error Reporting Function:: You can supply a @code{yyreport_syntax_error} function.
|
||||
@end menu
|
||||
|
||||
@node Error Reporting Function
|
||||
@@ -7465,8 +7466,8 @@ An opaque type that captures the circumstances of the syntax error.
|
||||
@end deffn
|
||||
|
||||
@deffn {Type} yysymbol_kind_t
|
||||
An enum that includes all the symbols, tokens and nonterminals, of the
|
||||
grammar. Its enumerators are forged from the token and symbol names:
|
||||
An enum that includes all the grammar symbols, tokens and nonterminals. Its
|
||||
enumerators are forged from the symbol names:
|
||||
|
||||
@example
|
||||
enum yysymbol_kind_t
|
||||
@@ -7491,7 +7492,6 @@ typedef enum yysymbol_kind_t yysymbol_kind_t;
|
||||
@deftypefun {yysymbol_kind_t} yypcontext_token (@code{const yypcontext_t *}@var{ctx})
|
||||
The ``unexpected'' token: the symbol kind of the lookahead token that caused
|
||||
the syntax error. Return @code{YYSYMBOL_YYEMPTY} if there is no lookahead.
|
||||
Can never return @code{YYSYMBOL_YYERROR}, or @code{YYSYMBOL_YYUNDEF}.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {YYLTYPE *} yypcontext_location (@code{const yypcontext_t *}@var{ctx})
|
||||
@@ -7528,7 +7528,7 @@ yyreport_syntax_error (const yypcontext_t *ctx)
|
||||
fprintf (stderr, ": syntax error");
|
||||
// Report the tokens expected at this point.
|
||||
@{
|
||||
enum @{ TOKENMAX = 10 @};
|
||||
enum @{ TOKENMAX = 5 @};
|
||||
yysymbol_kind_t expected[TOKENMAX];
|
||||
int n = yypcontext_expected_tokens (ctx, expected, TOKENMAX);
|
||||
if (n < 0)
|
||||
@@ -11280,6 +11280,7 @@ The Bison parser in C++ is an object, an instance of the class
|
||||
* C++ Parser Interface:: Instantiating and running the parser
|
||||
* C++ Semantic Values:: %union vs. C++
|
||||
* C++ Location Values:: The position and location classes
|
||||
* C++ Parser Context:: You can supply a @code{report_syntax_error} function.
|
||||
* C++ Scanner Interface:: Exchanges between yylex and parse
|
||||
* A Complete C++ Example:: Demonstrating their use
|
||||
@end menu
|
||||
@@ -11973,6 +11974,112 @@ files, reused by other parsers as follows:
|
||||
@end example
|
||||
|
||||
|
||||
@node C++ Parser Context
|
||||
@subsection C++ Parser Context
|
||||
|
||||
When @samp{%define parse.error custom} is used (@pxref{Syntax Error
|
||||
Reporting Function}), the user must define the following function.
|
||||
|
||||
@deftypemethod {parser} {void} report_syntax_error (@code{const context_type&}@var{ctx}) @code{const}
|
||||
Report a syntax error to the user. Whether it uses @code{yyerror} is up to
|
||||
the user.
|
||||
@end deftypemethod
|
||||
|
||||
Use the following types and functions to build the error message.
|
||||
|
||||
@defcv {Type} {parser} {context}
|
||||
A type that captures the circumstances of the syntax error.
|
||||
@end defcv
|
||||
|
||||
@defcv {Type} {parser} {symbol_kind_type}
|
||||
An enum that includes all the grammar symbols, tokens and nonterminals. Its
|
||||
enumerators are forged from the symbol names:
|
||||
|
||||
@example
|
||||
struct symbol_kind
|
||||
@{
|
||||
enum symbol_kind_type
|
||||
@{
|
||||
S_YYEMPTY = -2, // No symbol.
|
||||
S_YYEOF = 0, // "end of file"
|
||||
S_YYERROR = 1, // error
|
||||
S_YYUNDEF = 2, // "invalid token"
|
||||
S_PLUS = 3, // "+"
|
||||
S_MINUS = 4, // "-"
|
||||
[...]
|
||||
S_VAR = 14, // "variable"
|
||||
S_NEG = 15, // NEG
|
||||
S_YYACCEPT = 16, // $accept
|
||||
S_exp = 17, // exp
|
||||
S_input = 18 // input
|
||||
@};
|
||||
@};
|
||||
typedef symbol_kind::symbol_kind_t symbol_kind_type;
|
||||
@end example
|
||||
@end defcv
|
||||
|
||||
@deftypemethod {context} {const symbol_type&} lookahead () @code{const}
|
||||
The ``unexpected'' token: the lookahead that caused the syntax error.
|
||||
@end deftypemethod
|
||||
|
||||
@deftypemethod {context} {symbol_kind_type} token () @code{const}
|
||||
The symbol kind of the lookahead token that caused the syntax error. Return
|
||||
@code{symbol_kind::S_YYEMPTY} if there is no lookahead.
|
||||
@end deftypemethod
|
||||
|
||||
@deftypemethod {context} {const location&} location () @code{const}
|
||||
The location of the syntax error (that of the lookahead).
|
||||
@end deftypemethod
|
||||
|
||||
@deftypemethod {context} int expected_tokens (@code{symbol_kind_type} @var{argv}@code{[]}, @code{int} @var{argc}) @code{const}
|
||||
Fill @var{argv} with the expected tokens, which never includes
|
||||
@code{symbol_kind::S_YYEMPTY}, @code{symbol_kind::S_YYERROR}, or
|
||||
@code{symbol_kind::S_YYUNDEF}.
|
||||
|
||||
Never put more than @var{argc} elements into @var{argv}, and on success
|
||||
return the effective number of tokens stored in @var{argv}. Return 0 if
|
||||
there are more than @var{argc} expected tokens, yet fill @var{argv} up to
|
||||
@var{argc}.
|
||||
|
||||
If @var{argv} is null, return the size needed to store all the possible
|
||||
values, which is always less than @code{YYNTOKENS}.
|
||||
@end deftypemethod
|
||||
|
||||
@deftypemethod {parser} {const char *} symbol_name (@code{symbol_kind_t} @var{symbol}) @code{const}
|
||||
The name of the symbol whose kind is @var{symbol}, possibly translated.
|
||||
@end deftypemethod
|
||||
|
||||
A custom syntax error function looks as follows.
|
||||
|
||||
@example
|
||||
void
|
||||
yy::parser::report_syntax_error (const context& ctx)
|
||||
@{
|
||||
int res = 0;
|
||||
std::cerr << ctx.location () << ": syntax error";
|
||||
// Report the tokens expected at this point.
|
||||
@{
|
||||
enum @{ TOKENMAX = 5 @};
|
||||
symbol_kind_type expected[TOKENMAX];
|
||||
int n = ctx.expected_tokens (ctx, expected, TOKENMAX);
|
||||
for (int i = 0; i < n; ++i)
|
||||
std::cerr << i == 0 ? ": expected " : " or "
|
||||
<< symbol_name (expected[i]);
|
||||
@}
|
||||
// Report the unexpected token.
|
||||
@{
|
||||
symbol_kind_type lookahead = ctx.token ();
|
||||
if (lookahead != symbol_kind::S_YYEMPTY)
|
||||
std::cerr << " before " << symbol_name (lookahead));
|
||||
@}
|
||||
std::cerr << '\n';
|
||||
@}
|
||||
@end example
|
||||
|
||||
You still must provide a @code{yyerror} function, used for instance to
|
||||
report memory exhaustion.
|
||||
|
||||
|
||||
@node C++ Scanner Interface
|
||||
@subsection C++ Scanner Interface
|
||||
@c - prefix for yylex.
|
||||
@@ -12332,7 +12439,7 @@ designed the grammar for.
|
||||
|
||||
@comment file: calc++/parser.yy
|
||||
@example
|
||||
%skeleton "lalr1.cc" /* -*- C++ -*- */
|
||||
%skeleton "lalr1.cc" // -*- C++ -*-
|
||||
%require "@value{VERSION}"
|
||||
%defines
|
||||
@end example
|
||||
@@ -12403,14 +12510,15 @@ Then we request location tracking.
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
Use the following two directives to enable parser tracing and verbose error
|
||||
messages. However, verbose error messages can contain incorrect information
|
||||
(@pxref{LAC}).
|
||||
Use the following two directives to enable parser tracing and detailed error
|
||||
messages. However, detailed error messages can contain incorrect
|
||||
information if lookahead correction is not enabled (@pxref{LAC}).
|
||||
|
||||
@comment file: calc++/parser.yy
|
||||
@example
|
||||
%define parse.trace
|
||||
%define parse.error verbose
|
||||
%define parse.error detailed
|
||||
%define parse.lac full
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
|
||||
@@ -44,11 +44,18 @@ EOF
|
||||
run 0 9
|
||||
|
||||
|
||||
cat >input <<EOF
|
||||
1 +
|
||||
EOF
|
||||
run 1 'err: -:2.1: syntax error, unexpected end of file, expecting ( or identifier or number'
|
||||
|
||||
|
||||
# LAC finds many more tokens.
|
||||
cat >input <<EOF
|
||||
a := 1
|
||||
d := a + b * c
|
||||
EOF
|
||||
run 1 'err: -:3.1: syntax error, unexpected end of file, expecting ( or identifier or number'
|
||||
run 1 'err: -:3.1: syntax error, unexpected end of file'
|
||||
|
||||
|
||||
cat >input <<EOF
|
||||
|
||||
@@ -757,7 +757,7 @@ void
|
||||
{
|
||||
symbol_kind_type la = ctx.token ();
|
||||
if (la != symbol_kind::S_YYEMPTY)
|
||||
fprintf (stderr, " on token [%s]", yysymbol_name (la));
|
||||
std::cerr << " on token [" << symbol_name (la) << ']';
|
||||
}
|
||||
{
|
||||
enum { TOKENMAX = 10 };
|
||||
@@ -767,7 +767,7 @@ void
|
||||
{
|
||||
std::cerr << " (expected:";
|
||||
for (int i = 0; i < n; ++i)
|
||||
std::cerr << " [" << yysymbol_name (expected[i]) << ']';
|
||||
std::cerr << " [" << symbol_name (expected[i]) << ']';
|
||||
std::cerr << ')';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user