examples: calc++: remove prefixes

This example uses the calcxx_ prefix for each class.  That's uselessly
heavy.

* doc/bison.texi (A Complete C++ Example): Simplify the class names.
Since now 'driver' denotes the class, use 'drv' for the values.
Formatting changes.
This commit is contained in:
Akim Demaille
2018-08-23 18:50:46 +02:00
parent e504c843c1
commit 82fa282a1b

View File

@@ -10854,14 +10854,13 @@ files, reused by other parsers as follows:
@c debug_stream. @c debug_stream.
@c - Reporting errors @c - Reporting errors
The output files @file{@var{output}.hh} and @file{@var{output}.cc} The output files @file{@var{output}.hh} and @file{@var{output}.cc} declare
declare and define the parser class in the namespace @code{yy}. The and define the parser class in the namespace @code{yy}. The class name
class name defaults to @code{parser}, but may be changed using defaults to @code{parser}, but may be changed using @samp{%define
@samp{%define parser_class_name @{@var{name}@}}. The interface of parser_class_name @{@var{name}@}}. The interface of this class is detailed
this class is detailed below. It can be extended using the below. It can be extended using the @code{%parse-param} feature: its
@code{%parse-param} feature: its semantics is slightly changed since semantics is slightly changed since it describes an additional member of the
it describes an additional member of the parser class, and an parser class, and an additional argument for its constructor.
additional argument for its constructor.
@defcv {Type} {parser} {semantic_type} @defcv {Type} {parser} {semantic_type}
@defcvx {Type} {parser} {location_type} @defcvx {Type} {parser} {location_type}
@@ -11105,17 +11104,16 @@ seven * seven
@c - A place to store error messages @c - A place to store error messages
@c - A place for the result @c - A place for the result
To support a pure interface with the parser (and the scanner) the To support a pure interface with the parser (and the scanner) the technique
technique of the ``parsing context'' is convenient: a structure of the ``parsing context'' is convenient: a structure containing all the
containing all the data to exchange. Since, in addition to simply data to exchange. Since, in addition to simply launch the parsing, there
launch the parsing, there are several auxiliary tasks to execute (open are several auxiliary tasks to execute (open the file for scanning,
the file for parsing, instantiate the parser etc.), we recommend instantiate the parser etc.), we recommend transforming the simple parsing
transforming the simple parsing context structure into a fully blown context structure into a fully blown @dfn{parsing driver} class.
@dfn{parsing driver} class.
The declaration of this driver class, in @file{driver.hh}, is as follows. The The declaration of this driver class, in @file{driver.hh}, is as follows.
first part includes the CPP guard and imports the required standard library The first part includes the CPP guard and imports the required standard
components, and the declaration of the parser class. library components, and the declaration of the parser class.
@comment file: calc++/driver.hh @comment file: calc++/driver.hh
@example @example
@@ -11128,32 +11126,29 @@ components, and the declaration of the parser class.
@noindent @noindent
Then comes the declaration of the scanning function. Flex expects Then comes the declaration of the scanning function. Flex expects the
the signature of @code{yylex} to be defined in the macro signature of @code{yylex} to be defined in the macro @code{YY_DECL}, and the
@code{YY_DECL}, and the C++ parser expects it to be declared. We can C++ parser expects it to be declared. We can factor both as follows.
factor both as follows.
@comment file: calc++/driver.hh @comment file: calc++/driver.hh
@example @example
// Tell Flex the lexer's prototype ... // Tell Flex the lexer's prototype ...
# define YY_DECL \ # define YY_DECL \
yy::calcxx_parser::symbol_type yylex (calcxx_driver& driver) yy::parser::symbol_type yylex (driver& drv)
// ... and declare it for the parser's sake. // ... and declare it for the parser's sake.
YY_DECL; YY_DECL;
@end example @end example
@noindent @noindent
The @code{calcxx_driver} class is then declared with its most obvious The @code{driver} class is then declared with its most obvious members.
members.
@comment file: calc++/driver.hh @comment file: calc++/driver.hh
@example @example
// Conducting the whole scanning and parsing of Calc++. // Conducting the whole scanning and parsing of Calc++.
class calcxx_driver class driver
@{ @{
public: public:
calcxx_driver (); driver ();
virtual ~calcxx_driver ();
std::map<std::string, int> variables; std::map<std::string, int> variables;
@@ -11212,37 +11207,35 @@ messages and set error state.
#include "driver.hh" #include "driver.hh"
#include "parser.hh" #include "parser.hh"
calcxx_driver::calcxx_driver () driver::driver ()
: trace_scanning (false), trace_parsing (false) : trace_scanning (false), trace_parsing (false)
@{ @{
variables["one"] = 1; variables["one"] = 1;
variables["two"] = 2; variables["two"] = 2;
@} @}
calcxx_driver::~calcxx_driver () @group
@{
@}
int int
calcxx_driver::parse (const std::string &f) driver::parse (const std::string &f)
@{ @{
file = f; file = f;
scan_begin (); scan_begin ();
yy::calcxx_parser parser (*this); yy::parser parser (*this);
parser.set_debug_level (trace_parsing); parser.set_debug_level (trace_parsing);
int res = parser.parse (); int res = parser.parse ();
scan_end (); scan_end ();
return res; return res;
@} @}
@end group
void void
calcxx_driver::error (const yy::location& l, const std::string& m) driver::error (const yy::location& l, const std::string& m)
@{ @{
std::cerr << l << ": " << m << '\n'; std::cerr << l << ": " << m << '\n';
@} @}
void void
calcxx_driver::error (const std::string& m) driver::error (const std::string& m)
@{ @{
std::cerr << m << '\n'; std::cerr << m << '\n';
@} @}
@@ -11252,16 +11245,15 @@ calcxx_driver::error (const std::string& m)
@subsubsection Calc++ Parser @subsubsection Calc++ Parser
The grammar file @file{parser.yy} starts by asking for the C++ deterministic The grammar file @file{parser.yy} starts by asking for the C++ deterministic
parser skeleton, the creation of the parser header file, and specifies the parser skeleton, the creation of the parser header file. Because the C++
name of the parser class. Because the C++ skeleton changed several times, skeleton changed several times, it is safer to require the version you
it is safer to require the version you designed the grammar for. 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
%define parser_class_name @{calcxx_parser@}
@end example @end example
@noindent @noindent
@@ -11294,7 +11286,7 @@ forward declaration of the driver. @xref{%code Summary}.
%code requires %code requires
@{ @{
# include <string> # include <string>
class calcxx_driver; class driver;
@} @}
@end example @end example
@@ -11306,7 +11298,7 @@ global variables.
@comment file: calc++/parser.yy @comment file: calc++/parser.yy
@example @example
// The parsing context. // The parsing context.
%param @{ calcxx_driver& driver @} %param @{ driver& drv @}
@end example @end example
@noindent @noindent
@@ -11321,7 +11313,7 @@ propagated.
%initial-action %initial-action
@{ @{
// Initialize the initial location. // Initialize the initial location.
@@$.begin.filename = @@$.end.filename = &driver.file; @@$.begin.filename = @@$.end.filename = &drv.file;
@}; @};
@end example @end example
@@ -11338,8 +11330,8 @@ messages. However, verbose error messages can contain incorrect information
@noindent @noindent
@findex %code @findex %code
The code between @samp{%code @{} and @samp{@}} is output in the The code between @samp{%code @{} and @samp{@}} is output in the @file{*.cc}
@file{*.cc} file; it needs detailed knowledge about the driver. file; it needs detailed knowledge about the driver.
@comment file: calc++/parser.yy @comment file: calc++/parser.yy
@example @example
@@ -11403,14 +11395,14 @@ Location Tracking Calculator - @code{ltcalc}}).
@example @example
%% %%
%start unit; %start unit;
unit: assignments exp @{ driver.result = $2; @}; unit: assignments exp @{ drv.result = $2; @};
assignments: assignments:
%empty @{@} %empty @{@}
| assignments assignment @{@}; | assignments assignment @{@};
assignment: assignment:
"identifier" ":=" exp @{ driver.variables[$1] = $3; @}; "identifier" ":=" exp @{ drv.variables[$1] = $3; @};
%left "+" "-"; %left "+" "-";
%left "*" "/"; %left "*" "/";
@@ -11420,22 +11412,20 @@ exp:
| exp "*" exp @{ $$ = $1 * $3; @} | exp "*" exp @{ $$ = $1 * $3; @}
| exp "/" exp @{ $$ = $1 / $3; @} | exp "/" exp @{ $$ = $1 / $3; @}
| "(" exp ")" @{ std::swap ($$, $2); @} | "(" exp ")" @{ std::swap ($$, $2); @}
| "identifier" @{ $$ = driver.variables[$1]; @} | "identifier" @{ $$ = drv.variables[$1]; @}
| "number" @{ std::swap ($$, $1); @}; | "number" @{ std::swap ($$, $1); @};
%% %%
@end example @end example
@noindent @noindent
Finally the @code{error} member function registers the errors to the Finally the @code{error} member function registers the errors to the driver.
driver.
@comment file: calc++/parser.yy @comment file: calc++/parser.yy
@example @example
void void
yy::calcxx_parser::error (const location_type& l, yy::parser::error (const location_type& l, const std::string& m)
const std::string& m)
@{ @{
driver.error (l, m); drv.error (l, m);
@} @}
@end example @end example
@@ -11527,26 +11517,26 @@ The rules are simple. The driver is used to report errors.
@comment file: calc++/scanner.ll @comment file: calc++/scanner.ll
@example @example
"-" return yy::calcxx_parser::make_MINUS (loc); "-" return yy::parser::make_MINUS (loc);
"+" return yy::calcxx_parser::make_PLUS (loc); "+" return yy::parser::make_PLUS (loc);
"*" return yy::calcxx_parser::make_STAR (loc); "*" return yy::parser::make_STAR (loc);
"/" return yy::calcxx_parser::make_SLASH (loc); "/" return yy::parser::make_SLASH (loc);
"(" return yy::calcxx_parser::make_LPAREN (loc); "(" return yy::parser::make_LPAREN (loc);
")" return yy::calcxx_parser::make_RPAREN (loc); ")" return yy::parser::make_RPAREN (loc);
":=" return yy::calcxx_parser::make_ASSIGN (loc); ":=" return yy::parser::make_ASSIGN (loc);
@group @group
@{int@} @{ @{int@} @{
errno = 0; errno = 0;
long n = strtol (yytext, NULL, 10); long n = strtol (yytext, NULL, 10);
if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE)) if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
driver.error (loc, "integer is out of range"); drv.error (loc, "integer is out of range");
return yy::calcxx_parser::make_NUMBER (n, loc); return yy::parser::make_NUMBER (n, loc);
@} @}
@end group @end group
@{id@} return yy::calcxx_parser::make_IDENTIFIER (yytext, loc); @{id@} return yy::parser::make_IDENTIFIER (yytext, loc);
. driver.error (loc, "invalid character"); . drv.error (loc, "invalid character");
<<EOF>> return yy::calcxx_parser::make_END (loc); <<EOF>> return yy::parser::make_END (loc);
%% %%
@end example @end example
@@ -11558,7 +11548,7 @@ on the scanner's data, it is simpler to implement them in this file.
@example @example
@group @group
void void
calcxx_driver::scan_begin () driver::scan_begin ()
@{ @{
yy_flex_debug = trace_scanning; yy_flex_debug = trace_scanning;
if (file.empty () || file == "-") if (file.empty () || file == "-")
@@ -11573,7 +11563,7 @@ calcxx_driver::scan_begin ()
@group @group
void void
calcxx_driver::scan_end () driver::scan_end ()
@{ @{
fclose (yyin); fclose (yyin);
@} @}
@@ -11595,14 +11585,14 @@ int
main (int argc, char *argv[]) main (int argc, char *argv[])
@{ @{
int res = 0; int res = 0;
calcxx_driver driver; driver drv;
for (int i = 1; i < argc; ++i) for (int i = 1; i < argc; ++i)
if (argv[i] == std::string ("-p")) if (argv[i] == std::string ("-p"))
driver.trace_parsing = true; drv.trace_parsing = true;
else if (argv[i] == std::string ("-s")) else if (argv[i] == std::string ("-s"))
driver.trace_scanning = true; drv.trace_scanning = true;
else if (!driver.parse (argv[i])) else if (!drv.parse (argv[i]))
std::cout << driver.result << '\n'; std::cout << drv.result << '\n';
else else
res = 1; res = 1;
return res; return res;