src/parser.yy

Go to the documentation of this file.
00001 /* $Id: parser.yy 19 2007-08-19 20:36:24Z tb $ -*- mode: c++ -*- */
00004 %{ /*** C/C++ Declarations ***/
00005 
00006 #include <stdio.h>
00007 #include <string>
00008 #include <vector>
00009 
00010 #include "expression.h"
00011 
00012 %}
00013 
00014 /*** yacc/bison Declarations ***/
00015 
00016 /* Require bison 2.3 or later */
00017 %require "2.3"
00018 
00019 /* add debug output code to generated parser. disable this for release
00020  * versions. */
00021 %debug
00022 
00023 /* start symbol is named "start" */
00024 %start start
00025 
00026 /* write out a header file containing the token defines */
00027 %defines
00028 
00029 /* use newer C++ skeleton file */
00030 %skeleton "lalr1.cc"
00031 
00032 /* namespace to enclose parser in */
00033 %name-prefix="example"
00034 
00035 /* set the parser's class identifier */
00036 %define "parser_class_name" "Parser"
00037 
00038 /* keep track of the current position within the input */
00039 %locations
00040 %initial-action
00041 {
00042     // initialize the initial location object
00043     @$.begin.filename = @$.end.filename = &driver.streamname;
00044 };
00045 
00046 /* The driver is passed by reference to the parser and to the scanner. This
00047  * provides a simple but effective pure interface, not relying on global
00048  * variables. */
00049 %parse-param { class Driver& driver }
00050 
00051 /* verbose error messages */
00052 %error-verbose
00053 
00054  /*** BEGIN EXAMPLE - Change the example grammar's tokens below ***/
00055 
00056 %union {
00057     int                         integerVal;
00058     double                      doubleVal;
00059     std::string*                stringVal;
00060     CalcNode*                   calcnode;
00061 }
00062 
00063 %token                  END          0  "end of file"
00064 %token                  EOL             "end of line"
00065 %token <integerVal>     INTEGER         "integer"
00066 %token <doubleVal>      DOUBLE          "double"
00067 %token <stringVal>      STRING          "string"
00068 
00069 %type <calcnode>        constant variable
00070 %type <calcnode>        atomexpr powexpr unaryexpr mulexpr addexpr expr
00071 
00072 %destructor { delete $$; } STRING
00073 %destructor { delete $$; } constant variable
00074 %destructor { delete $$; } atomexpr powexpr unaryexpr mulexpr addexpr expr
00075 
00076  /*** END EXAMPLE - Change the example grammar's tokens above ***/
00077 
00078 %{
00079 
00080 #include "driver.h"
00081 #include "scanner.h"
00082 
00083 /* this "connects" the bison parser in the driver to the flex scanner class
00084  * object. it defines the yylex() function call to pull the next token from the
00085  * current lexer object of the driver context. */
00086 #undef yylex
00087 #define yylex driver.lexer->lex
00088 
00089 %}
00090 
00091 %% /*** Grammar Rules ***/
00092 
00093  /*** BEGIN EXAMPLE - Change the example grammar rules below ***/
00094 
00095 constant : INTEGER
00096            {
00097                $$ = new CNConstant($1);
00098            }
00099          | DOUBLE
00100            {
00101                $$ = new CNConstant($1);
00102            }
00103 
00104 variable : STRING
00105            {
00106                if (!driver.calc.existsVariable(*$1)) {
00107                    error(yyloc, std::string("Unknown variable \"") + *$1 + "\"");
00108                    delete $1;
00109                    YYERROR;
00110                }
00111                else {
00112                    $$ = new CNConstant( driver.calc.getVariable(*$1) );
00113                    delete $1;
00114                }
00115            }
00116 
00117 atomexpr : constant
00118            {
00119                $$ = $1;
00120            }
00121          | variable
00122            {
00123                $$ = $1;
00124            }
00125          | '(' expr ')'
00126            {
00127                $$ = $2;
00128            }
00129 
00130 powexpr : atomexpr
00131           {
00132               $$ = $1;
00133           }
00134         | powexpr '^' atomexpr
00135           {
00136               $$ = new CNPower($1, $3);
00137           }
00138 
00139 unaryexpr : powexpr
00140             {
00141                 $$ = $1;
00142             }
00143           | '+' powexpr
00144             {
00145                 $$ = $2;
00146             }
00147           | '-' powexpr
00148             {
00149                 $$ = new CNNegate($2);
00150             }
00151 
00152 mulexpr : unaryexpr
00153           {
00154               $$ = $1;
00155           }
00156         | mulexpr '*' unaryexpr
00157           {
00158               $$ = new CNMultiply($1, $3);
00159           }
00160         | mulexpr '/' unaryexpr
00161           {
00162               $$ = new CNDivide($1, $3);
00163           }
00164         | mulexpr '%' unaryexpr
00165           {
00166               $$ = new CNModulo($1, $3);
00167           }
00168 
00169 addexpr : mulexpr
00170           {
00171               $$ = $1;
00172           }
00173         | addexpr '+' mulexpr
00174           {
00175               $$ = new CNAdd($1, $3);
00176           }
00177         | addexpr '-' mulexpr
00178           {
00179               $$ = new CNSubtract($1, $3);
00180           }
00181 
00182 expr    : addexpr
00183           {
00184               $$ = $1;
00185           }
00186 
00187 assignment : STRING '=' expr
00188              {
00189                  driver.calc.variables[*$1] = $3->evaluate();
00190                  std::cout << "Setting variable " << *$1
00191                            << " = " << driver.calc.variables[*$1] << "\n";
00192                  delete $1;
00193                  delete $3;
00194              }
00195 
00196 start   : /* empty */
00197         | start ';'
00198         | start EOL
00199         | start assignment ';'
00200         | start assignment EOL
00201         | start assignment END
00202         | start expr ';'
00203           {
00204               driver.calc.expressions.push_back($2);
00205           }
00206         | start expr EOL
00207           {
00208               driver.calc.expressions.push_back($2);
00209           }
00210         | start expr END
00211           {
00212               driver.calc.expressions.push_back($2);
00213           }
00214 
00215  /*** END EXAMPLE - Change the example grammar rules above ***/
00216 
00217 %% /*** Additional Code ***/
00218 
00219 void example::Parser::error(const Parser::location_type& l,
00220                             const std::string& m)
00221 {
00222     driver.error(l, m);
00223 }

Generated on Mon Aug 20 13:34:21 2007 for Flex Bison C++ Example by  doxygen 1.5.2