diff options
author | Akim Demaille <akim@epita.fr> | 2005-06-22 15:32:10 +0000 |
---|---|---|
committer | Akim Demaille <akim@epita.fr> | 2005-06-22 15:32:10 +0000 |
commit | 0ffd4fd1a23f0ff8196ee3b15d12a5f3aad89c40 (patch) | |
tree | 63584d060a515efd5187dcaae2f1e5d3bdad8815 /examples | |
parent | 0925ebb4fa72edab483ba025aa2e998339117599 (diff) | |
download | bison-0ffd4fd1a23f0ff8196ee3b15d12a5f3aad89c40.tar.gz |
Start a set of simple examples.
* examples/calc++/Makefile, examples/calc++/calc++-driver.cc,
* examples/calc++/calc++-driver.hh,
* examples/calc++/calc++-parser.yy,
* examples/calc++/calc++-scanner.ll, examples/calc++/calc++.cc,
* examples/calc++/compile, examples/calc++/test: New.
Diffstat (limited to 'examples')
-rw-r--r-- | examples/calc++/Makefile | 15 | ||||
-rw-r--r-- | examples/calc++/calc++-driver.cc | 37 | ||||
-rw-r--r-- | examples/calc++/calc++-driver.hh | 64 | ||||
-rw-r--r-- | examples/calc++/calc++-parser.yy | 68 | ||||
-rw-r--r-- | examples/calc++/calc++-scanner.ll | 45 | ||||
-rw-r--r-- | examples/calc++/calc++.cc | 18 | ||||
-rwxr-xr-x | examples/calc++/compile | 9 | ||||
-rwxr-xr-x | examples/calc++/test | 26 |
8 files changed, 282 insertions, 0 deletions
diff --git a/examples/calc++/Makefile b/examples/calc++/Makefile new file mode 100644 index 00000000..cad628b2 --- /dev/null +++ b/examples/calc++/Makefile @@ -0,0 +1,15 @@ +all: calc++ + +calc++: + flex -ocalc++-scanner.cc calc++-scanner.ll + bison -o calc++-parser.cc calc++-parser.yy + $(CC) -o calc++ calc++.cc calc++-driver.cc calc++-parser.cc calc++-scanner.cc + +check: all + ./test + +clean: + rm -f *~ *.o *.tab.* input position.hh location.hh stack.hh \ + calc++-parser.cc calc++-parser.hh \ + calc++-scanner.cc \ + calc++ diff --git a/examples/calc++/calc++-driver.cc b/examples/calc++/calc++-driver.cc new file mode 100644 index 00000000..13df5294 --- /dev/null +++ b/examples/calc++/calc++-driver.cc @@ -0,0 +1,37 @@ +#include "calc++-driver.hh" +#include "calc++-parser.hh" + +calcxx_driver::calcxx_driver () + : trace_scanning (false), + trace_parsing (false) +{ + variables["one"] = 1; + variables["two"] = 2; +} + +calcxx_driver::~calcxx_driver () +{ +} + +void +calcxx_driver::parse (const std::string &f) +{ + file = f; + scan_begin (); + yy::calcxx_parser parser (*this); + parser.set_debug_level (trace_parsing); + parser.parse (); + scan_end (); +} + +void +calcxx_driver::error (const yy::location& l, const std::string& m) +{ + std::cerr << l << ": " << m << std::endl; +} + +void +calcxx_driver::error (const std::string& m) +{ + std::cerr << m << std::endl; +} diff --git a/examples/calc++/calc++-driver.hh b/examples/calc++/calc++-driver.hh new file mode 100644 index 00000000..8b3ed532 --- /dev/null +++ b/examples/calc++/calc++-driver.hh @@ -0,0 +1,64 @@ +#ifndef CALCXX_DRIVER_HH +# define CALCXX_DRIVER_HH +# include <string> +# include <map> + +/// Forward declarations. +union YYSTYPE; + +namespace yy +{ + class calcxx_parser; + class location; +} + +class calcxx_driver; + +// Announce to Flex the prototype we want for lexing function, ... +# define YY_DECL \ + int yylex (YYSTYPE* yylval, yy::location* yylloc, calcxx_driver& driver) +// ... and declare it for the parser's sake. +YY_DECL; + +/// Conducting the whole scanning and parsing of Calc++. +class calcxx_driver +{ +public: + calcxx_driver (); + virtual ~calcxx_driver (); + + /// The variables. + std::map<std::string, int> variables; + + /// \name Handling the scanner. + /// \{ + /// Open \a file for scanning. + void scan_begin (); + /// End scanning, clean up memory. + void scan_end (); + /// Whether to enable scanner traces. + bool trace_scanning; + /// \} + + /// \name Handling the parser. + /// \{ + /// Parse the file \a f. + void parse (const std::string& f); + /// The file being parsed. + std::string file; + /// Whether to enable parsing traces. + bool trace_parsing; + /// \} + + /// The result. + int result; + + /// \name Error handling. + /// \{ + /// Register a located error. + void error (const yy::location& l, const std::string& m); + /// Register an error. + void error (const std::string& m); + /// \} +}; +#endif diff --git a/examples/calc++/calc++-parser.yy b/examples/calc++/calc++-parser.yy new file mode 100644 index 00000000..67281434 --- /dev/null +++ b/examples/calc++/calc++-parser.yy @@ -0,0 +1,68 @@ +%skeleton "lalr1.cc" /* -*- C++ -*- */ +%define "parser_class_name" "calcxx_parser" +%defines +%{ +# include <string> +# include "calc++-driver.hh" +%} + +%error-verbose + +// The parsing context. +%parse-param { calcxx_driver& driver } +%lex-param { calcxx_driver& driver } + +%locations +%initial-action +{ + // Initialize the initial location. + @$.begin.filename = @$.end.filename = &driver.file; +}; + +// Define yydebug. +%debug + +// Symbols. + +%union +{ + /// Value of a numeric literal. + int ival; + /// Name of a variable. + std::string *sval; +}; + +%token YYEOF 0 "end of file" +%token TOKEN_ASSIGN ":=" +%token <sval> TOKEN_IDENTIFIER "identifier" +%token <ival> TOKEN_NUMBER "number" +%type <ival> exp "expression" + +%printer { debug_stream () << *$$; } "identifier" +%destructor { delete $$; } "identifier" + +%printer { debug_stream () << $$; } "number" "expression" + +%% +%start unit; +unit: assignments exp { driver.result = $2; }; + +assignments: assignments assignment {} + | /* Nothing. */ {}; + +assignment: TOKEN_IDENTIFIER ":=" exp { driver.variables[*$1] = $3; }; + +%left '+' '-'; +%left '*' '/'; +exp: exp '+' exp { $$ = $1 + $3; } + | exp '-' exp { $$ = $1 - $3; } + | exp '*' exp { $$ = $1 * $3; } + | exp '/' exp { $$ = $1 / $3; } + | TOKEN_IDENTIFIER { $$ = driver.variables[*$1]; } + | TOKEN_NUMBER { $$ = $1; }; +%% +void +yy::calcxx_parser::error (const location& l, const std::string& m) +{ + driver.error (l, m); +} diff --git a/examples/calc++/calc++-scanner.ll b/examples/calc++/calc++-scanner.ll new file mode 100644 index 00000000..dd9a8b8a --- /dev/null +++ b/examples/calc++/calc++-scanner.ll @@ -0,0 +1,45 @@ +%{ /* -*- C++ -*- */ + +# include <string> +# include <cerrno> +# include "calc++-driver.hh" +# include "calc++-parser.hh" +%} + +%option noyywrap nounput debug batch + +id [a-zA-Z][a-zA-Z_0-9]* +int [0-9]+ +blank [ \t] + +%% + +%{ +# define YY_USER_ACTION yylloc->columns (yyleng); + yylloc->step (); +%} +{blank}+ yylloc->step (); +[\n]+ yylloc->lines (yyleng); yylloc->step (); + + +[-+*/] return yytext[0]; +":=" return TOKEN_ASSIGN; +{int} yylval->ival = atoi (yytext); return TOKEN_NUMBER; +{id} yylval->sval = new std::string (yytext); return TOKEN_IDENTIFIER; +. driver.error (*yylloc, "invalid character"); + +%% + +void +calcxx_driver::scan_begin () +{ + yy_flex_debug = trace_scanning; + if (!(yyin = fopen (file.c_str (), "r"))) + error (std::string ("cannot open ") + file); +} + +void +calcxx_driver::scan_end () +{ + fclose (yyin); +} diff --git a/examples/calc++/calc++.cc b/examples/calc++/calc++.cc new file mode 100644 index 00000000..44e74c80 --- /dev/null +++ b/examples/calc++/calc++.cc @@ -0,0 +1,18 @@ +#include <iostream> +#include "calc++-driver.hh" + +int +main (int argc, const char* argv[]) +{ + calcxx_driver driver; + for (++argv; argv[0]; ++argv) + if (*argv == std::string ("-p")) + driver.trace_parsing = true; + else if (*argv == std::string ("-s")) + driver.trace_scanning = true; + else + { + driver.parse (*argv); + std::cout << driver.result << std::endl; + } +} diff --git a/examples/calc++/compile b/examples/calc++/compile new file mode 100755 index 00000000..fac1036b --- /dev/null +++ b/examples/calc++/compile @@ -0,0 +1,9 @@ +#! /bin/sh + +set -ex +BISON_PKGDATADIR=$HOME/src/bison/data +export BISON_PKGDATADIR + +flex -ocalc++-scanner.cc calc++-scanner.ll +bison -o calc++-parser.cc calc++-parser.yy +g++ -o calc++ calc++.cc calc++-driver.cc calc++-parser.cc calc++-scanner.cc diff --git a/examples/calc++/test b/examples/calc++/test new file mode 100755 index 00000000..b4f0d258 --- /dev/null +++ b/examples/calc++/test @@ -0,0 +1,26 @@ +#! /bin/sh +set +e +cat >input <<EOF +a := 1 +b := 2 +c := 3 +d := a + b * c +d +EOF + +./calc++ input +./calc++ -p input + +cat >input <<EOF +a := 1 +d := a + b * c +EOF +./calc++ input + +set -x +echo toto +cat >input <<EOF +toto := 1 +toto +EOF +./calc++ -s input |