summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorAkim Demaille <akim@epita.fr>2005-06-22 15:32:10 +0000
committerAkim Demaille <akim@epita.fr>2005-06-22 15:32:10 +0000
commit0ffd4fd1a23f0ff8196ee3b15d12a5f3aad89c40 (patch)
tree63584d060a515efd5187dcaae2f1e5d3bdad8815 /examples
parent0925ebb4fa72edab483ba025aa2e998339117599 (diff)
downloadbison-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++/Makefile15
-rw-r--r--examples/calc++/calc++-driver.cc37
-rw-r--r--examples/calc++/calc++-driver.hh64
-rw-r--r--examples/calc++/calc++-parser.yy68
-rw-r--r--examples/calc++/calc++-scanner.ll45
-rw-r--r--examples/calc++/calc++.cc18
-rwxr-xr-xexamples/calc++/compile9
-rwxr-xr-xexamples/calc++/test26
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