+2005-06-22 Akim Demaille <akim@epita.fr>
+
+ 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 <eggert@cs.ucla.edu>
* data/yacc.c (malloc, free) [defined __cplusplus]: Wrap inside
* 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.
--- /dev/null
+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++
--- /dev/null
+#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;
+}
--- /dev/null
+#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
--- /dev/null
+%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);
+}
--- /dev/null
+%{ /* -*- 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);
+}
--- /dev/null
+#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;
+ }
+}
--- /dev/null
+#! /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
--- /dev/null
+#! /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