00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "config.h"
00021 #include "parser.h"
00022
00023 #include "parser.tab.hh"
00024 #include "vypIO.h"
00025
00026 #ifndef BUILDING_DOX
00027 # include <stack>
00028 # include <string>
00029 #endif
00030
00031 using namespace StreamDecorator;
00032 using std::string;
00033
00035 class BisonListener: public IBisonListener {
00036 public:
00037 BisonListener(IBuilder *, string fileName);
00038 virtual ~BisonListener() { }
00039 virtual void setType(EToken type);
00040 virtual void glVar(Token token);
00041 virtual void fncInit(Token token);
00042 virtual void fncDecl();
00043 virtual void fncDefEnter();
00044 virtual void fncDefLeave();
00045 virtual void argDecl();
00046 virtual void argDef(Token token);
00047 virtual void lcVar(Token token);
00048 virtual void assign(Token token) { builder_ -> assign(token); }
00049 virtual void ifEnter(Token token) { builder_ -> ifEnter(token); }
00050 virtual void ifElse() { builder_ -> ifElse(); }
00051 virtual void ifLeave() { builder_ -> ifLeave(); }
00052 virtual void whileInit(Token token) { builder_ -> whileInit(token); }
00053 virtual void whileEnter() { builder_ -> whileEnter(); }
00054 virtual void whileLeave() { builder_ -> whileLeave(); }
00055 virtual void pushToken(Token token) { builder_ -> pushToken(token); }
00056 virtual void evalUnOp(Token token) { builder_ -> evalUnOp(token); }
00057 virtual void evalBinOp(Token token) { builder_ -> evalBinOp(token); }
00058 virtual void fncCallInit(Token token);
00059 virtual void fncCallArg();
00060 virtual void fncCallPrintArg();
00061 virtual void fncCallAsCmd();
00062 virtual void fncCallAsExpr();
00063 private:
00064 IBuilder *builder_;
00065 string fileName_;
00066 EToken type_;
00067 EToken fncType_;
00068 Token fncId_;
00069 bool fncInitDeclSent_;
00070 bool fncInitDefSent_;
00071 EToken fncPrint_;
00072
00073 typedef STD_PAIR(Token, int) TFncCall;
00074 typedef STD_STACK(TFncCall) TStack;
00075 TStack stack_;
00076
00077 bool initDeclIfNeeded();
00078 bool initDefIfNeeded();
00079 void errMixedDeclDef();
00080 bool chkStack();
00081 };
00082
00083 BisonListener::BisonListener(IBuilder *builder, string fileName):
00084 builder_(builder),
00085 fileName_(fileName),
00086 type_(ETOKEN_NULL),
00087 fncType_(ETOKEN_NULL),
00088 fncInitDeclSent_(false),
00089 fncInitDefSent_(false),
00090 fncPrint_(ETOKEN_NULL)
00091 {
00092 }
00093
00094 void BisonListener::setType(EToken type) {
00095 type_ = type;
00096 }
00097
00098 void BisonListener::glVar(Token token) {
00099 builder_ -> glVar(type_, token);
00100 }
00101
00102 void BisonListener::fncInit(Token token) {
00103 fncType_ = type_;
00104 fncId_ = token;
00105 fncInitDeclSent_ = false;
00106 fncInitDefSent_ = false;
00107 }
00108
00109 void BisonListener::fncDecl() {
00110 if (initDeclIfNeeded())
00111 builder_ -> fncDecl();
00112 }
00113
00114 void BisonListener::fncDefEnter() {
00115 initDefIfNeeded();
00116 builder_ -> fncDefBody();
00117 }
00118
00119 void BisonListener::fncDefLeave() {
00120 if (initDefIfNeeded())
00121 builder_ -> fncDef();
00122 }
00123
00124 void BisonListener::argDecl() {
00125 if (initDeclIfNeeded())
00126 builder_ -> fncDeclArg(type_);
00127 }
00128
00129 void BisonListener::argDef(Token token) {
00130 if (initDefIfNeeded())
00131 builder_ -> fncDefArg(type_, token);
00132 }
00133
00134 void BisonListener::lcVar(Token token) {
00135 if (initDefIfNeeded())
00136 builder_ -> fncDefVar(type_, token);
00137 }
00138
00139 void BisonListener::fncCallInit(Token token) {
00140 fncPrint_ = ETOKEN_NULL;
00141 #if DEBUG_BISON_LISTENER_STACK
00142 std::cerr << Color(C_LIGHT_PURPLE) << "BisonListener stack"
00143 << Color(C_NO_COLOR) << " <-- " << token
00144 << "[" << Color(C_LIGHT_PURPLE) << 0
00145 << Color(C_NO_COLOR) << "]" << std::endl;
00146 #endif
00147 stack_.push(TFncCall(token, 0));
00148 }
00149
00150 void BisonListener::fncCallArg() {
00151 TFncCall &top = stack_.top();
00152 int &argCnt = top.second;
00153 ++ argCnt;
00154 #if DEBUG_BISON_LISTENER_STACK
00155 std::cerr << Color(C_LIGHT_PURPLE) << "BisonListener stack"
00156 << Color(C_NO_COLOR) << " <-> " << top.first
00157 << "[" << Color(C_LIGHT_PURPLE) << top.second
00158 << Color(C_NO_COLOR) << "]" << std::endl;
00159 #endif
00160 }
00161
00162 void BisonListener::fncCallPrintArg() {
00163 if (!chkStack())
00164 return;
00165 TFncCall &top = stack_.top();
00166 Token tFnc = top.first;
00167 if (tFnc.text != "print") {
00168 std::cerr << Error(E_ERROR, fileName_, "print syntax used for another function", tFnc) << std::endl;
00169 builder_->errorDetected();
00170 }
00171 fncPrint_ = type_;
00172 }
00173
00174 void BisonListener::fncCallAsCmd() {
00175 if (!chkStack())
00176 return;
00177
00178 TFncCall top = stack_.top();
00179 stack_.pop();
00180 #if DEBUG_BISON_LISTENER_STACK
00181 std::cerr << Color(C_LIGHT_PURPLE) << "BisonListener stack"
00182 << Color(C_NO_COLOR) << " --> " << top.first
00183 << "[" << Color(C_LIGHT_PURPLE) << top.second
00184 << Color(C_NO_COLOR) << "]" << std::endl;
00185 #endif
00186 if (fncPrint_ == ETOKEN_NULL)
00187 builder_ -> fncCall(top.first, top.second, false);
00188 else
00189 builder_ -> fncCallPrint(top.first, fncPrint_);
00190 }
00191
00192 void BisonListener::fncCallAsExpr() {
00193 if (!chkStack())
00194 return;
00195
00196 TFncCall top = stack_.top();
00197 stack_.pop();
00198 #if DEBUG_BISON_LISTENER_STACK
00199 std::cerr << Color(C_LIGHT_PURPLE) << "BisonListener stack"
00200 << Color(C_NO_COLOR) << " --> " << top.first
00201 << "[" << Color(C_LIGHT_PURPLE) << top.second
00202 << Color(C_NO_COLOR) << "]" << std::endl;
00203 #endif
00204 builder_ -> fncCall(top.first, top.second, true);
00205 }
00206
00207 bool BisonListener::initDeclIfNeeded() {
00208 if (fncInitDefSent_) {
00209 errMixedDeclDef();
00210 return false;
00211 }
00212
00213 if (!fncInitDeclSent_) {
00214 builder_ -> fncDeclInit(fncType_, fncId_);
00215 fncInitDeclSent_ = true;
00216 }
00217 return true;
00218 }
00219
00220 bool BisonListener::initDefIfNeeded() {
00221 if (fncInitDeclSent_) {
00222 errMixedDeclDef();
00223 return false;
00224 }
00225
00226 if (!fncInitDefSent_) {
00227 builder_ -> fncDefInit(fncType_, fncId_);
00228 fncInitDefSent_ = true;
00229 }
00230 return true;
00231 }
00232
00233 bool BisonListener::chkStack() {
00234 if (stack_.empty()) {
00235 std::cerr << Error(E_ERROR, fileName_, "BisonListener: stack underflow", Token(), true) << std::endl;
00236 builder_ -> errorDetected();
00237 return false;
00238 }
00239 return true;
00240 }
00241
00242 void BisonListener::errMixedDeclDef() {
00243 std::cerr << Error(E_ERROR, fileName_, "mixed declaration/definition is not allowed", fncId_) << std::endl;
00244 builder_ -> errorDetected();
00245 }
00246
00247 namespace yy {
00248 #ifndef BUILDING_DOX
00249 void BisonParser::error(const yy::location& loc, const string& msg) {
00250 std::cerr << Error(E_ERROR, fileName, msg, loc.end.line, "syntax error")
00251 << std::endl;
00252 }
00253 #endif
00254
00255 int yylex (Token *token, yy::location *loc, IScanner *scanner) {
00256 for (;;) {
00257 if (!scanner->readNext(*token))
00258 return 0;
00259 loc->begin.line = loc->end.line = token->lineno;
00260
00261 switch (token->type) {
00262 case ETOKEN_ID: return BisonParser::token::T_ID;
00263 case ETOKEN_KW_AND: return BisonParser::token::T_AND;
00264 case ETOKEN_KW_DIV: return BisonParser::token::T_DIV;
00265 case ETOKEN_KW_DOUBLE: return BisonParser::token::T_DOUBLE;
00266 case ETOKEN_KW_ELSE: return BisonParser::token::T_ELSE;
00267 case ETOKEN_KW_EQ: return BisonParser::token::T_EQ;
00268 case ETOKEN_KW_IF: return BisonParser::token::T_IF;
00269 case ETOKEN_KW_INT: return BisonParser::token::T_INT;
00270 case ETOKEN_KW_OR: return BisonParser::token::T_OR;
00271 case ETOKEN_KW_NEQ: return BisonParser::token::T_NEQ;
00272 case ETOKEN_KW_NOT: return BisonParser::token::T_NOT;
00273 case ETOKEN_KW_STRING: return BisonParser::token::T_STRING;
00274 case ETOKEN_KW_VAR: return BisonParser::token::T_VAR;
00275 case ETOKEN_KW_VOID: return BisonParser::token::T_VOID;
00276 case ETOKEN_KW_WHILE: return BisonParser::token::T_WHILE;
00277 case ETOKEN_NUMBER_DOUBLE: return BisonParser::token::T_DOUBLE_LIT;
00278 case ETOKEN_NUMBER_INT: return BisonParser::token::T_INT_LIT;
00279 case ETOKEN_OP_ASSIGN: return BisonParser::token::T_ASSIGN;
00280 case ETOKEN_OP_COMMA: return ',';
00281 case ETOKEN_OP_GREATER: return '>';
00282 case ETOKEN_OP_GREATER_EQ: return BisonParser::token::T_GE;
00283 case ETOKEN_OP_LCBR: return '{';
00284 case ETOKEN_OP_LESS: return '<';
00285 case ETOKEN_OP_LESS_EQ: return BisonParser::token::T_LE;
00286 case ETOKEN_OP_LPAR: return '(';
00287 case ETOKEN_OP_MINUS: return '-';
00288 case ETOKEN_OP_PLUS: return '+';
00289 case ETOKEN_OP_RCBR: return '}';
00290 case ETOKEN_OP_RPAR: return ')';
00291 case ETOKEN_OP_SEMICOLON: return ';';
00292 case ETOKEN_OP_SLASH: return '/';
00293 case ETOKEN_OP_STAR: return '*';
00294 case ETOKEN_STRING: return BisonParser::token::T_STRING_LIT;
00295 default:
00296 std::cerr << Error(E_WARNING, "yylex", "unhandled token", *token, true) << std::endl;
00297 }
00298 }
00299 }
00300 }
00301
00302 int Parser::parse(IScanner *scanner, IBuilder *builder, std::string fileName) {
00303 IBisonListener *listener = new BisonListener(builder, fileName);
00304 yy::BisonParser *parser = new yy::BisonParser(scanner, listener, fileName);
00305 #if 0
00306 parser->set_debug_level(1);
00307 #endif
00308 int status = parser->parse();
00309
00310 delete parser;
00311 delete listener;
00312 return status;
00313 }