00001
00004 %{
00005
00006 #include <stdio.h>
00007 #include <string>
00008 #include <vector>
00009
00010 #include "expression.h"
00011
00012 %}
00013
00014
00015
00016
00017 %require "2.3"
00018
00019
00020
00021 %debug
00022
00023
00024 %start start
00025
00026
00027 %defines
00028
00029
00030 %skeleton "lalr1.cc"
00031
00032
00033 %name-prefix="example"
00034
00035
00036 %define "parser_class_name" "Parser"
00037
00038
00039 %locations
00040 %initial-action
00041 {
00042
00043 @$.begin.filename = @$.end.filename = &driver.streamname;
00044 };
00045
00046
00047
00048
00049 %parse-param { class Driver& driver }
00050
00051
00052 %error-verbose
00053
00054
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
00077
00078 %{
00079
00080 #include "driver.h"
00081 #include "scanner.h"
00082
00083
00084
00085
00086 #undef yylex
00087 #define yylex driver.lexer->lex
00088
00089 %}
00090
00091 %%
00092
00093
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 :
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
00216
00217 %%
00218
00219 void example::Parser::error(const Parser::location_type& l,
00220 const std::string& m)
00221 {
00222 driver.error(l, m);
00223 }