mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-19 17:23:02 +00:00
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:
136
doc/bison.texi
136
doc/bison.texi
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user