parser.cc

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008 Kamil Dudka <xdudka00@stud.fit.vutbr.cz>
00003  *
00004  * This file is part of vyp08 (compiler and interpreter of VYP08 language).
00005  *
00006  * vyp08 is free software: you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation, either version 3 of the License, or
00009  * any later version.
00010  *
00011  * vyp08 is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with vyp08.  If not, see <http://www.gnu.org/licenses/>.
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             // convert scanner token enumeration to bison #define values
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 }

Generated on Sat Jul 4 18:32:59 2009 for vyp08 (compiler and interpreter of VYP08 language) by  doxygen 1.5.4