mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-23 11:13:03 +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], [[
|
]b4_parse_error_bmatch([custom\|detailed], [[
|
||||||
/// The user-facing name of the symbol whose (internal) number is
|
/// The user-facing name of the symbol whose (internal) number is
|
||||||
/// YYSYMBOL. No bounds checking.
|
/// YYSYMBOL. No bounds checking.
|
||||||
static const char *yysymbol_name (symbol_kind_type yysymbol);
|
static const char *symbol_name (symbol_kind_type yysymbol);
|
||||||
]])[
|
]])[
|
||||||
|
|
||||||
// Tables.
|
// Tables.
|
||||||
@@ -586,7 +586,7 @@ m4_if(b4_prefix, [yy], [],
|
|||||||
/* The user-facing name of the symbol whose (internal) number is
|
/* The user-facing name of the symbol whose (internal) number is
|
||||||
YYSYMBOL. No bounds checking. */
|
YYSYMBOL. No bounds checking. */
|
||||||
const char *
|
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[] =
|
static const char *const yy_sname[] =
|
||||||
{
|
{
|
||||||
@@ -1503,7 +1503,7 @@ b4_dollar_popdef])[]dnl
|
|||||||
{
|
{
|
||||||
yyres += ]b4_parse_error_case([verbose],
|
yyres += ]b4_parse_error_case([verbose],
|
||||||
[[yytnamerr_ (yytname_[yyarg[yyi++]])]],
|
[[yytnamerr_ (yytname_[yyarg[yyi++]])]],
|
||||||
[[yysymbol_name (yyarg[yyi++])]])[;
|
[[symbol_name (yyarg[yyi++])]])[;
|
||||||
++yyp;
|
++yyp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
136
doc/bison.texi
136
doc/bison.texi
@@ -325,8 +325,8 @@ The Lexical Analyzer Function @code{yylex}
|
|||||||
|
|
||||||
Error Reporting
|
Error Reporting
|
||||||
|
|
||||||
* Error Reporting Function:: You must supply a function @code{yyerror}.
|
* Error Reporting Function:: You must supply a @code{yyerror} function.
|
||||||
* Syntax Error Reporting Function:: You can supply a function @code{yyreport_syntax_error}.
|
* Syntax Error Reporting Function:: You can supply a @code{yyreport_syntax_error} function.
|
||||||
|
|
||||||
Parser Internationalization
|
Parser Internationalization
|
||||||
|
|
||||||
@@ -408,6 +408,7 @@ C++ Parsers
|
|||||||
* C++ Parser Interface:: Instantiating and running the parser
|
* C++ Parser Interface:: Instantiating and running the parser
|
||||||
* C++ Semantic Values:: %union vs. C++
|
* C++ Semantic Values:: %union vs. C++
|
||||||
* C++ Location Values:: The position and location classes
|
* 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
|
* C++ Scanner Interface:: Exchanges between yylex and parse
|
||||||
* A Complete C++ Example:: Demonstrating their use
|
* 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.
|
to the user must be specified by the developer.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* Error Reporting Function:: You must supply a function @code{yyerror}.
|
* Error Reporting Function:: You must supply a @code{yyerror} function.
|
||||||
* Syntax Error Reporting Function:: You can supply a function @code{yyreport_syntax_error}.
|
* Syntax Error Reporting Function:: You can supply a @code{yyreport_syntax_error} function.
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@node Error Reporting Function
|
@node Error Reporting Function
|
||||||
@@ -7465,8 +7466,8 @@ An opaque type that captures the circumstances of the syntax error.
|
|||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Type} yysymbol_kind_t
|
@deffn {Type} yysymbol_kind_t
|
||||||
An enum that includes all the symbols, tokens and nonterminals, of the
|
An enum that includes all the grammar symbols, tokens and nonterminals. Its
|
||||||
grammar. Its enumerators are forged from the token and symbol names:
|
enumerators are forged from the symbol names:
|
||||||
|
|
||||||
@example
|
@example
|
||||||
enum yysymbol_kind_t
|
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})
|
@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 ``unexpected'' token: the symbol kind of the lookahead token that caused
|
||||||
the syntax error. Return @code{YYSYMBOL_YYEMPTY} if there is no lookahead.
|
the syntax error. Return @code{YYSYMBOL_YYEMPTY} if there is no lookahead.
|
||||||
Can never return @code{YYSYMBOL_YYERROR}, or @code{YYSYMBOL_YYUNDEF}.
|
|
||||||
@end deftypefun
|
@end deftypefun
|
||||||
|
|
||||||
@deftypefun {YYLTYPE *} yypcontext_location (@code{const yypcontext_t *}@var{ctx})
|
@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");
|
fprintf (stderr, ": syntax error");
|
||||||
// Report the tokens expected at this point.
|
// Report the tokens expected at this point.
|
||||||
@{
|
@{
|
||||||
enum @{ TOKENMAX = 10 @};
|
enum @{ TOKENMAX = 5 @};
|
||||||
yysymbol_kind_t expected[TOKENMAX];
|
yysymbol_kind_t expected[TOKENMAX];
|
||||||
int n = yypcontext_expected_tokens (ctx, expected, TOKENMAX);
|
int n = yypcontext_expected_tokens (ctx, expected, TOKENMAX);
|
||||||
if (n < 0)
|
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++ Parser Interface:: Instantiating and running the parser
|
||||||
* C++ Semantic Values:: %union vs. C++
|
* C++ Semantic Values:: %union vs. C++
|
||||||
* C++ Location Values:: The position and location classes
|
* 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
|
* C++ Scanner Interface:: Exchanges between yylex and parse
|
||||||
* A Complete C++ Example:: Demonstrating their use
|
* A Complete C++ Example:: Demonstrating their use
|
||||||
@end menu
|
@end menu
|
||||||
@@ -11973,6 +11974,112 @@ files, reused by other parsers as follows:
|
|||||||
@end example
|
@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
|
@node C++ Scanner Interface
|
||||||
@subsection C++ Scanner Interface
|
@subsection C++ Scanner Interface
|
||||||
@c - prefix for yylex.
|
@c - prefix for yylex.
|
||||||
@@ -12332,7 +12439,7 @@ designed the grammar for.
|
|||||||
|
|
||||||
@comment file: calc++/parser.yy
|
@comment file: calc++/parser.yy
|
||||||
@example
|
@example
|
||||||
%skeleton "lalr1.cc" /* -*- C++ -*- */
|
%skeleton "lalr1.cc" // -*- C++ -*-
|
||||||
%require "@value{VERSION}"
|
%require "@value{VERSION}"
|
||||||
%defines
|
%defines
|
||||||
@end example
|
@end example
|
||||||
@@ -12403,14 +12510,15 @@ Then we request location tracking.
|
|||||||
@end example
|
@end example
|
||||||
|
|
||||||
@noindent
|
@noindent
|
||||||
Use the following two directives to enable parser tracing and verbose error
|
Use the following two directives to enable parser tracing and detailed error
|
||||||
messages. However, verbose error messages can contain incorrect information
|
messages. However, detailed error messages can contain incorrect
|
||||||
(@pxref{LAC}).
|
information if lookahead correction is not enabled (@pxref{LAC}).
|
||||||
|
|
||||||
@comment file: calc++/parser.yy
|
@comment file: calc++/parser.yy
|
||||||
@example
|
@example
|
||||||
%define parse.trace
|
%define parse.trace
|
||||||
%define parse.error verbose
|
%define parse.error detailed
|
||||||
|
%define parse.lac full
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@noindent
|
@noindent
|
||||||
@@ -12720,7 +12828,7 @@ driver::scan_begin ()
|
|||||||
yyin = stdin;
|
yyin = stdin;
|
||||||
else if (!(yyin = fopen (file.c_str (), "r")))
|
else if (!(yyin = fopen (file.c_str (), "r")))
|
||||||
@{
|
@{
|
||||||
std::cerr << "cannot open " << file << ": " << strerror(errno) << '\n';
|
std::cerr << "cannot open " << file << ": " << strerror (errno) << '\n';
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
@}
|
@}
|
||||||
@}
|
@}
|
||||||
|
|||||||
@@ -44,11 +44,18 @@ EOF
|
|||||||
run 0 9
|
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
|
cat >input <<EOF
|
||||||
a := 1
|
a := 1
|
||||||
d := a + b * c
|
d := a + b * c
|
||||||
EOF
|
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
|
cat >input <<EOF
|
||||||
|
|||||||
@@ -757,7 +757,7 @@ void
|
|||||||
{
|
{
|
||||||
symbol_kind_type la = ctx.token ();
|
symbol_kind_type la = ctx.token ();
|
||||||
if (la != symbol_kind::S_YYEMPTY)
|
if (la != symbol_kind::S_YYEMPTY)
|
||||||
fprintf (stderr, " on token [%s]", yysymbol_name (la));
|
std::cerr << " on token [" << symbol_name (la) << ']';
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
enum { TOKENMAX = 10 };
|
enum { TOKENMAX = 10 };
|
||||||
@@ -767,7 +767,7 @@ void
|
|||||||
{
|
{
|
||||||
std::cerr << " (expected:";
|
std::cerr << " (expected:";
|
||||||
for (int i = 0; i < n; ++i)
|
for (int i = 0; i < n; ++i)
|
||||||
std::cerr << " [" << yysymbol_name (expected[i]) << ']';
|
std::cerr << " [" << symbol_name (expected[i]) << ']';
|
||||||
std::cerr << ')';
|
std::cerr << ')';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user