From 0ffd4fd1a23f0ff8196ee3b15d12a5f3aad89c40 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Wed, 22 Jun 2005 15:32:10 +0000 Subject: [PATCH] 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. --- ChangeLog | 11 ++++- examples/calc++/Makefile | 15 +++++++ examples/calc++/calc++-driver.cc | 37 +++++++++++++++++ examples/calc++/calc++-driver.hh | 64 +++++++++++++++++++++++++++++ examples/calc++/calc++-parser.yy | 68 +++++++++++++++++++++++++++++++ examples/calc++/calc++-scanner.ll | 45 ++++++++++++++++++++ examples/calc++/calc++.cc | 18 ++++++++ examples/calc++/compile | 9 ++++ examples/calc++/test | 26 ++++++++++++ 9 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 examples/calc++/Makefile create mode 100644 examples/calc++/calc++-driver.cc create mode 100644 examples/calc++/calc++-driver.hh create mode 100644 examples/calc++/calc++-parser.yy create mode 100644 examples/calc++/calc++-scanner.ll create mode 100644 examples/calc++/calc++.cc create mode 100755 examples/calc++/compile create mode 100755 examples/calc++/test diff --git a/ChangeLog b/ChangeLog index 309343cc..aec1a9ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2005-06-22 Akim Demaille + + 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. + 2005-06-09 Paul Eggert * data/yacc.c (malloc, free) [defined __cplusplus]: Wrap inside @@ -7653,7 +7662,7 @@ * tests/atlocal.at (GCC): New. * tests/synclines.at (AT_TEST_SYNCLINE): New macro. - (Prologue synch line, ,%union synch line, Postprologue synch line) + (Prologue synch line, %union synch line, Postprologue synch line) (Action synch line, Epilogue synch line): New tests. * src/reader.c (parse_union_decl): Define the muscle stype_line. * data/bison.simple, data/bison.c++: Use it. 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 +# include + +/// 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 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 +# 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 TOKEN_IDENTIFIER "identifier" +%token TOKEN_NUMBER "number" +%type 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 +# include +# 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 +#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 <input <input <