Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/expr/ExParser.h
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2007 George Tzanetakis <gtzan@cs.uvic.ca>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 #if !defined(MARSYAS_EX_PARSER_H)
00020 #define MARSYAS_EX_PARSER_H
00021 
00022 #include <marsyas/expr/ExNode.h>
00023 #include <marsyas/expr/ExSymTbl.h>
00024 #include <marsyas/expr/ExScanner.h>
00025 #include <marsyas/sched/Scheduler.h>
00026 #include <marsyas/system/MarSystem.h>
00027 #include <marsyas/common_header.h>
00028 
00029 #include <string>
00030 #include <iostream>
00031 #include <map>
00032 
00033 namespace Marsyas {
00034 
00035 class ExParser {
00036 private:
00037   int _EOF;
00038   int _tnatural;
00039   int _treal;
00040   int _tstr;
00041   int _tbool;
00042   int _tname;
00043   int _cname;
00044   int _rasgn;
00045   int _lasgn;
00046   int _addrasgn;
00047   int _subrasgn;
00048   int _mulrasgn;
00049   int _divrasgn;
00050   int _modrasgn;
00051   int _addlasgn;
00052   int _sublasgn;
00053   int _mullasgn;
00054   int _divlasgn;
00055   int _modlasgn;
00056   int _andrasgn;
00057   int _orrasgn;
00058   int _andlasgn;
00059   int _orlasgn;
00060   int _addop;
00061   int _subop;
00062   int _mulop;
00063   int _divop;
00064   int _modop;
00065   int _power;
00066   int _lbrkt;
00067   int _rbrkt;
00068   int _rlink;
00069   int _llink;
00070   int _notop;
00071   int _eqop;
00072   int _neop;
00073   int _gtop;
00074   int _geop;
00075   int _ltop;
00076   int _leop;
00077   int _andop;
00078   int _orop;
00079   int _exprbrk;
00080   int _blkstart;
00081   int _blkend;
00082   int _ifblk;
00083   int _atsym;
00084   int _propsep;
00085   int _lsbrkt;
00086   int _rsbrkt;
00087   int _colon;
00088   int _streamlib;
00089   int maxT;
00090 
00091   Token *dummyToken;
00092   int errDist;
00093   int minErrDist;
00094   bool fail;
00095 
00096   void SynErr(int n);
00097   void Get();
00098   void Expect(int n);
00099   bool StartOf(int s);
00100   void ExpectWeak(int n, int follow);
00101   bool WeakSeparator(int n, int syFol, int repFol);
00102 
00103 public:
00104   ExScanner *scanner;
00105 
00106   Token *t;         // last recognized token
00107   Token *la;            // lookahead token
00108 
00109   ExNode* tree;
00110   ExNode* getTree() { return tree; }
00111 
00112   std::map<std::string,std::string> aliases_;
00113   ExSymTbl symbol_table;
00114 
00115   MarSystem* marsystem_;
00116   Scheduler* scheduler_;
00117   TmTimer** timer_;
00118 
00119   bool IsLAsgn()//{{{
00120   {
00121     bool x=false;
00122     if (la->kind==_tname||la->kind==_cname) {
00123       Token* p = scanner->Peek();
00124       x= (p->kind==   _lasgn)
00125          || (p->kind==_addlasgn)
00126          || (p->kind==_sublasgn)
00127          || (p->kind==_mullasgn)
00128          || (p->kind==_divlasgn)
00129          || (p->kind==_modlasgn);
00130       scanner->ResetPeek();
00131     } else if (la->kind==_streamlib) {                          // Stream
00132       if (scanner->Peek()->kind==_propsep) {          // .
00133         if (scanner->Peek()->kind==_tname) {        // name
00134           if (scanner->Peek()->kind==_lasgn) {    // <<
00135             x=true;
00136           }
00137         }
00138       }
00139       scanner->ResetPeek();
00140     } else if (la->kind==_atsym) {
00141       x= scanner->Peek()->kind==_tname
00142          && scanner->Peek()->kind==_lasgn;
00143       scanner->ResetPeek();
00144     }
00145     return x;
00146   }//}}}
00147   bool IsCNameRAsgnAlias() {//{{{
00148     bool x=(la->kind==_cname)
00149            && (scanner->Peek()->kind==_rasgn)
00150            && (scanner->Peek()->kind==_atsym);
00151     scanner->ResetPeek();
00152     return x;
00153   }//}}}
00154   bool IsLink()//{{{
00155   {
00156     if (la->kind!=_cname) { return false; }
00157     Token* p = scanner->Peek();
00158     bool x = (p->kind==_rlink) || (p->kind==_llink);
00159     scanner->ResetPeek();
00160     return x;
00161   }//}}}
00162   bool in_colon()//{{{
00163   {
00164     bool x=false;
00165     if (la->kind==_tname) {
00166       if (la->val[0]=='i'&&la->val[1]=='n'&&la->val[2]=='\0') {
00167         Token* p=scanner->Peek();
00168         x=p->kind==_colon;
00169       }
00170     }
00171     scanner->ResetPeek();
00172     return x;
00173   }//}}}
00174   std::string prep_string(std::string s)//{{{
00175   {
00176     s=s.substr(1,s.length()-2); // remove quotes
00177     int c=0; bool f=false;
00178     for (unsigned int i=0; i<s.length(); ++i,++c) {
00179       if (f) {
00180         if (s[i]=='n') { c--; s[c]='\n'; }
00181         if (s[i]=='t') { c--; s[c]='\t'; }
00182         f=false;
00183       } else s[c]=s[i];
00184       if (s[i]==92) { f=true; }
00185     }
00186     s=s.substr(0,c);
00187     return s;
00188   }//}}}
00189 
00190   void Init()//{{{
00191   {
00192     ExRecord* library=new ExRecord();
00193     load_symbols(library);
00194     loadlib_timer(library,timer_);
00195     symbol_table.addTable(library);
00196     symbol_table.block_open();
00197   }//}}}
00198 
00199   ExNode* getFunctionCopy(std::string nm, ExNode* params)//{{{
00200   {
00201     std::string key=construct_signature(nm, params);
00202     ExFun* f=symbol_table.getFunctionCopy(key);
00203     if (f!=NULL) {
00204       f->setParams(params);
00205       if (f->is_const()) {
00206         ExVal xx = f->eval();
00207         ExNode* e = new ExNode(xx);
00208         delete(f);
00209         return e;
00210       }
00211     } else {
00212       MRSWARN("ExParser::getFunctionCopy   unbound function call: "+key);
00213     }
00214     return f;
00215   }//}}}
00216   int getKind(std::string nm)//{{{
00217   {
00218     ExRecord* r=symbol_table.getRecord(nm);
00219     return (r==NULL) ? 0 : r->getKind();
00220   }//}}}
00221   std::string getType(std::string nm)//{{{
00222   {
00223     ExRecord* r=symbol_table.getRecord(nm);
00224     return (r==NULL) ? "" : r->getType();
00225   }//}}}
00226   std::string getElemType(std::string nm)//{{{
00227   {
00228     ExRecord* r=symbol_table.getRecord(nm);
00229     return (r==NULL) ? "" : r->getElemType();
00230   }//}}}
00231   std::string getDefaultLib(std::string typ)//{{{
00232   {
00233     if (typ=="mrs_string") return "String";
00234     if (typ=="mrs_real") return "Real";
00235     if (typ=="mrs_natural") return "Natural";
00236     if (typ=="mrs_bool") return "Bool";
00237     if (typ=="mrs_timer") return "Timer";
00238     int len=(int)typ.length();
00239     if ((len>4)&&typ[len-1]=='t'&&typ[len-2]=='s'&&typ[len-3]=='i'&&typ[len-4]=='l'&&typ[len-5]==' ') return "List";
00240     return "";
00241   }//}}}
00242 
00243   /****************************************************************************/
00244   ExNode* expr_append(ExNode* u, ExNode* v)//{{{
00245   {
00246     if (u==NULL) return v;
00247     ExNode* x=u; while (u->next!=NULL) { u=u->next; } u->next=v;
00248     return x;
00249   } //}}}
00250   std::string exprs_type(ExNode* es)//{{{
00251   {
00252     if (es==NULL) return "";
00253     while (es->next!=NULL) { es=es->next; }
00254     return es->getType();
00255   } //}}}
00256   std::string construct_signature(std::string nm, ExNode* params)//{{{
00257   {
00258     std::string key=nm;
00259     key+="(";
00260     ExNode* ps=params;
00261     while (ps!=NULL) {
00262       std::string tp=ps->getType();
00263       key+=tp;
00264       if (tp=="mrs_natural") key+="|mrs_real";
00265       if (ps->is_list()) key+="|mrs_list";
00266       ps=ps->next;
00267       if (ps!=NULL) key+=",";
00268     }
00269     key+=")";
00270     return key;
00271   } //}}}
00272   bool is_alias(std::string nm) { return (aliases_.find(nm) != aliases_.end()); }
00273   bool is_num(std::string n)//{{{
00274   {
00275     for (unsigned int i=0; i<n.length(); ++i) {
00276       if (n[i]<'0'||n[i]>'9') return false;
00277     }
00278     return true;
00279   } //}}}
00280   ExNode* assignment(ExNode* u, ExRecord* r) {//{{{
00281     std::string rt=r->getType(); std::string ut=u->getType();
00282     if (rt=="mrs_real"&&ut=="mrs_natural") u=new ExNode_NaturalToReal(u);
00283     else if (rt=="mrs_natural"&&ut=="mrs_real") u=new ExNode_RealToNatural(u);
00284     if (rt==u->getType()) u=new ExNode_AsgnVar(u,r);
00285     else {
00286       MRSWARN("ExParser: Type mismatch in assignment: "+r->getType()+" << "+u->getType());
00287       fail=true; u->deref(); return NULL;
00288     }
00289     return u;
00290   }//}}}
00291   ExNode* do_asgn(std::string nm, ExNode* u)//{{{
00292   {
00293     if (is_alias(nm)) { return do_casgn(nm,u); }
00294     std::string t = getType(nm);
00295     // compare name type with u
00296     if (t=="") { // make a new variable in symbol table
00297       ExVal v = ExValTyped(T_VAR,u->getType());
00298       symbol_table.setValue(v,nm);
00299       t=u->getType();
00300     }
00301     ExRecord* r=symbol_table.getRecord(nm);
00302     return assignment(u,r);
00303   } //}}}
00304   ExNode* do_masgn(int atype, bool right_assign, std::string nm, ExNode* u)//{{{
00305   {
00306     if (is_alias(nm)) { return do_cmasgn(atype,right_assign,nm,u); }
00307     // get name type, it must exist because we need read it
00308     std::string rt=getType(nm);
00309     if (rt=="") {
00310       MRSWARN("ExParser: Unbound name '"+nm+"'");
00311       fail=true; u->deref(); return NULL;
00312     }
00313     ExRecord* r=symbol_table.getRecord(nm);
00314     ExNode* v=new ExNode_ReadVar(r,nm);
00315     if (!right_assign) { ExNode* a=u; u=v; v=a; }
00316     if (atype==OP_ADD||atype==OP_SUB) { u=do_addop(atype,u,v); }
00317     else if (atype==OP_MUL||atype==OP_DIV||atype==OP_MOD) { u=do_mulop(atype,u,v); }
00318     else { u=do_condop(atype,u,v); }
00319     if (u==NULL) return NULL;
00320     return assignment(u,r);
00321   }//}}}
00322   // assignment
00323   ExNode* do_alias(std::string anm, std::string cnm) { aliases_[anm]=cnm; return NULL; }
00324   ExNode* do_casgn(std::string nm, ExNode* u)//{{{
00325   {
00326     if (is_alias(nm)) nm=aliases_[nm];
00327     if (marsystem_->hasControl(nm)) {
00328       MarControlPtr p = marsystem_->getctrl(nm);
00329       // does p exist
00330       std::string t = p->getType();
00331       std::string ut= u->getType();
00332       // compare name type with u
00333       if (t=="mrs_real") {
00334         if (ut=="mrs_real") u=new ExNode_SetCtrlReal(nm,p,u);
00335         else if (ut=="mrs_natural") u=new ExNode_SetCtrlReal(nm,p,new ExNode_NaturalToReal(u));
00336         else {
00337           MRSWARN("ExParser: Cannot assign type '"+ut+"' to "+t);
00338           fail=true; u->deref(); return NULL;
00339         }
00340       }
00341       else if (t=="mrs_natural") {
00342         if (ut=="mrs_natural") u=new ExNode_SetCtrlNatural(nm,p,u);
00343         else {
00344           MRSWARN("ExParser: Cannot setctrl type '"+ut+"' to "+t);
00345           fail=true; u->deref(); return NULL;
00346         }
00347       }
00348       else if (t=="mrs_bool"&&ut=="mrs_bool") {
00349         u=new ExNode_SetCtrlBool(nm,p,u);
00350       }
00351       else if (t=="mrs_string"&&ut=="mrs_string") {
00352         u=new ExNode_SetCtrlString(nm,p,u);
00353       }
00354       else {
00355         MRSWARN("ExParser: Unknown types in setctrl");
00356         fail=true; u->deref(); return NULL;
00357       }
00358     } else {
00359       MRSWARN("ExParser: '"+nm+"' does not exist");
00360       fail=true; u->deref(); return NULL;
00361     }
00362     return u;
00363   } //}}}
00364   ExNode* do_cmasgn(int atype, bool right_assign, std::string nm, ExNode* u)//{{{
00365   {
00366     if (is_alias(nm)) nm=aliases_[nm];
00367     ExNode* v=do_getctrl(nm);
00368     if (v==NULL) return NULL;
00369     if (!right_assign) { ExNode* a=u; u=v; v=a; }
00370     if (atype==OP_ADD||atype==OP_SUB) { u=do_addop(atype,u,v); }
00371     else if (atype==OP_MUL||atype==OP_DIV||atype==OP_MOD) { u=do_mulop(atype,u,v); }
00372     else { u=do_condop(atype,u,v); }
00373     if (u==NULL) return NULL;
00374     return do_casgn(nm,u);
00375   } //}}}
00376   ExNode* do_getctrl(std::string nm)//{{{
00377   {
00378     if (marsystem_==NULL) {
00379       MRSWARN("ExParser: Control Name defined on NULL MarSystem");
00380       fail=true; return NULL;
00381     }
00382     if (marsystem_->hasControl(nm)) {
00383       MarControlPtr ptr=marsystem_->getctrl(nm);
00384       std::string t=ptr->getType();
00385       if (t=="mrs_bool") { return new ExNode_GetCtrlBool(nm,ptr); }
00386       else if (t=="mrs_string") { return new ExNode_GetCtrlString(nm,ptr); }
00387       else if (t=="mrs_natural") { return new ExNode_GetCtrlNatural(nm,ptr); }
00388       else if (t=="mrs_real") { return new ExNode_GetCtrlReal(nm,ptr); }
00389     }
00390     MRSWARN("ExParser: getctrl on '"+nm+"' failed.");
00391     fail=true;
00392     return NULL;
00393   }//}}}
00394   // operators
00395   ExNode* do_mulop(int m, ExNode* u, ExNode* v)//{{{
00396   {
00397     std::string ut=u->getType(); std::string vt=v->getType();
00398     std::string t=ut;
00399     if (ut=="mrs_real"&&vt=="mrs_natural") { v=new ExNode_NaturalToReal(v); vt="mrs_real"; }
00400     else if (vt=="mrs_real"&&ut=="mrs_natural") { u=new ExNode_NaturalToReal(u); ut="mrs_real"; t=ut; }
00401 
00402     if (ut!="mrs_real"&&ut!="mrs_natural") {
00403       MRSWARN("ExParser::mult  Expected mrs_real|mrs_natural types, got "+ut+" & "+vt);
00404       fail=true; u->deref(); v->deref(); return NULL;
00405     }
00406     ExNode* w=NULL;
00407     // check for const and evaluate if possible
00408     bool is_const = (u->is_const()&&v->is_const());
00409     if (m==OP_MUL) {
00410       if (is_const) { w=new ExNode(u->value*v->value); }
00411       else { u=new ExNode_MUL(t,u,v); }
00412     }
00413     else if (m==OP_DIV) {
00414       if (is_const) { w=new ExNode(u->value/v->value); }
00415       else { u=new ExNode_DIV(t,u,v); }
00416     }
00417     else if (m==OP_MOD) {
00418       if (is_const) { w=new ExNode(u->value%v->value); }
00419       else { u=new ExNode_MOD(t,u,v); }
00420     }
00421     if (w!=NULL) { u->deref(); v->deref(); u=w; }
00422     return u;
00423   } //}}}
00424   ExNode* do_addop(int m, ExNode* u, ExNode* v)//{{{
00425   {
00426     std::string ut=u->getType(); std::string vt=v->getType();
00427     // first step conversion, so that u and t are of the same type
00428     if (ut=="mrs_real"&&vt=="mrs_natural") { v=new ExNode_NaturalToReal(v); vt="mrs_real"; }
00429     else if (vt=="mrs_real"&&ut=="mrs_natural") { u=new ExNode_NaturalToReal(u); ut="mrs_real"; }
00430     else if (m==OP_ADD) {
00431       if (ut=="mrs_string") {
00432         if (vt=="mrs_real") {
00433           if (v->is_const()) { v->setValue(dtos(v->getValue().toReal())); }
00434           else { v=new ExNode_RealToString(v); }
00435         }
00436         else if (vt=="mrs_natural") {
00437           if (v->is_const()) { v->setValue(ltos(v->getValue().toNatural())); }
00438           else { v=new ExNode_NaturalToString(v); }
00439         }
00440         else if (vt=="mrs_bool") {
00441           if (v->is_const()) { v->setValue(btos(v->getValue().toBool())); }
00442           else { v=new ExNode_NaturalToString(v); }
00443         }
00444         vt="mrs_string";
00445       }
00446       else if (vt=="mrs_string") {
00447         if (ut=="mrs_real") {
00448           if (u->is_const()) { u->setValue(dtos(u->getValue().toReal())); }
00449           else { u=new ExNode_RealToString(u); }
00450         }
00451         else if (ut=="mrs_natural") {
00452           if (u->is_const()) { u->setValue(ltos(u->getValue().toNatural())); }
00453           else { u=new ExNode_NaturalToString(u); }
00454         }
00455         else if (ut=="mrs_bool") {
00456           if (u->is_const()) { u->setValue(btos(u->getValue().toBool())); }
00457           else { u=new ExNode_NaturalToString(u); }
00458         }
00459         ut="mrs_string";
00460       }
00461     }
00462     bool is_const = (u->is_const()&&v->is_const());
00463     ExNode* w=NULL;
00464     // type check operator
00465     bool list_t=false;
00466     if (u->is_list()&&v->is_list()) {
00467       if (ut==" list"&&vt!=" list") { ut=vt; }
00468       else if (vt==" list"&&ut!=" list") { vt=ut; }
00469       list_t=true;
00470     }
00471     if (ut==vt) {
00472       bool addable=
00473         (  ut=="mrs_real"
00474            || ut=="mrs_natural"
00475            || ut=="mrs_string"
00476            || list_t
00477         );
00478       if (m==OP_ADD&&addable) {
00479         if (is_const) { w=new ExNode(u->getValue()+v->getValue()); }
00480         else { u=new ExNode_ADD(ut,u,v); }
00481       }
00482       else if (m==OP_SUB&&(ut=="mrs_real"||ut=="mrs_natural")) {
00483         if (is_const) { w=new ExNode(u->getValue()-v->getValue()); }
00484         else { u=new ExNode_SUB(ut,u,v); }
00485       }
00486       else {
00487         MRSWARN("ExParser: Invalid types to addop: "+ut+" and "+vt);
00488         fail=true; delete u; delete v; return NULL;
00489       }
00490     }
00491     else {
00492       MRSWARN("ExParser: Invalid types to addop: "+ut+" and "+vt);
00493       fail=true; delete u; delete v; return NULL;
00494     }
00495     if (w!=NULL) { delete u; delete v; u=w; }
00496     return u;
00497   } //}}}
00498   ExNode* do_num_negate(ExNode* u)//{{{
00499   {
00500     if (u->getType()=="mrs_real") {
00501       if (u->is_const()) { (u->value).set(-(u->value).toReal()); }
00502       else { u=new ExNode_MathNeg_Real(u); }
00503     } else if (u->getType()=="mrs_natural") {
00504       if (u->is_const()) { (u->value).set(-(u->value).toNatural()); }
00505       else { u=new ExNode_MathNeg_Natural(u); }
00506     } else {
00507       MRSWARN("ExParser: Type mismatch in unary math negation operator");
00508       fail=true; delete u; return NULL;
00509     }
00510     return u;
00511   } //}}}
00512   ExNode* do_relop(int m, ExNode* u, ExNode* v)//{{{
00513   {
00514     if (u->getType()!=v->getType()) {
00515       MRSWARN("ExParser: Type mismatch to relational operator.");
00516       fail=true; delete u; delete v;
00517       return NULL;
00518     }
00519     bool is_const = (u->is_const()&&v->is_const());
00520     if (m==OP_EQ) {
00521       printf("@ eq\n");
00522       if (is_const) { ExVal a=u->value == v->value; u->deref(); v->deref(); u=new ExNode(a); }
00523       else { u=new ExNode_EQ("mrs_bool",u,v); }
00524     }
00525     else if (m==OP_NE) {
00526       if (is_const) { ExVal a=u->value != v->value; u->deref(); v->deref(); u=new ExNode(a); }
00527       else { u=new ExNode_NE("mrs_bool",u,v); }
00528     }
00529     else if (m==OP_GT) {
00530       if (is_const) { ExVal a=u->value > v->value; u->deref(); v->deref(); u=new ExNode(a); }
00531       else { u=new ExNode_GT("mrs_bool",u,v); }
00532     }
00533     else if (m==OP_GE) {
00534       if (is_const) { ExVal a=u->value >= v->value; u->deref(); v->deref(); u=new ExNode(a); }
00535       else { u=new ExNode_GE("mrs_bool",u,v); }
00536     }
00537     else if (m==OP_LT) {
00538       if (is_const) { ExVal a=u->value < v->value; u->deref(); v->deref(); u=new ExNode(a); }
00539       else { u=new ExNode_LT("mrs_bool",u,v); }
00540     }
00541     else if (m==OP_LE) {
00542       if (is_const) { ExVal a=u->value <= v->value; u->deref(); v->deref(); u=new ExNode(a); }
00543       else { u=new ExNode_LE("mrs_bool",u,v); }
00544     }
00545     return u;
00546   } //}}}
00547   ExNode* do_bool_negate(ExNode* v)//{{{
00548   {
00549     if (v->is_const()) { (v->value).set(!(v->value).toBool()); }
00550     else v=new ExNode_BoolNeg(v);
00551     return v;
00552   } //}}}
00553   ExNode* do_condop(int o, ExNode* u, ExNode* v)//{{{
00554   {
00555     if (u->getType()=="mrs_bool"&&v->getType()=="mrs_bool") {
00556       if (u->is_const()&&v->is_const()) {
00557         if (o==OP_AND) { u->value.set(u->value.toBool() && v->value.toBool()); }
00558         else { u->value.set(u->value.toBool() || v->value.toBool()); }
00559         delete v;
00560       }
00561       else if (o==OP_AND) u=new ExNode_AND("mrs_bool",u,v);
00562       else u=new ExNode_OR("mrs_bool",u,v);
00563     }
00564     else {
00565       MRSWARN("ExParser: Types to relational operator must bool.");
00566       fail=true; delete u; delete v; u=NULL;
00567     }
00568     return u;
00569   } //}}}
00570   ExNode* do_conditional(ExNode* cond, ExNode* ts, ExNode* es)//{{{
00571   {
00572     if (exprs_type(cond)!="mrs_bool") {
00573       MRSWARN("ExParser: Condition in conditional statement must be of type bool");
00574       fail=true; delete cond; delete ts; delete es;
00575       return NULL;
00576     }
00577     std::string tt=exprs_type(ts);
00578     std::string et=exprs_type(es);
00579     if (et!=tt||tt.length()==0||et.length()==0) {
00580       MRSWARN("ExParser: Type Mismatch in function");
00581       fail=true; delete cond; delete ts; delete es;
00582       return NULL;
00583     }
00584     return new ExNode_Conditional(tt,cond,ts,es);
00585   } //}}}
00586   ExNode* do_link(std::string f, std::string t)//{{{
00587   {
00588     if (marsystem_==NULL) {
00589       MRSWARN("ExParser: Control Name defined on NULL MarSystem");
00590       fail=true; return NULL;
00591     }
00592     if (marsystem_->hasControl(f)&&marsystem_->hasControl(t)) {
00593       MarControlPtr pf = marsystem_->getctrl(f);
00594       MarControlPtr pt = marsystem_->getctrl(t);
00595       if (pf.isInvalid()||pt.isInvalid()) {
00596         MRSWARN("ExParser: Cannot link controls '"+f+"' -> '"+t+"'");
00597         fail=true; return NULL;
00598       }
00599       if (pf->getType()!=pt->getType()) {
00600         MRSWARN("ExParser: linkctrl type mismatch between '"+f+"' -> '"+t+"'");
00601         fail=true; return NULL;
00602       }
00603       std::string tp = marsystem_->getctrl(f)->getType();
00604       return new ExNode_Link(pf,pt,tp);
00605     }
00606     MRSWARN("ExParser: Link controls '"+f+"' -> '"+t+"' failed.");
00607     fail=true; return NULL;
00608   }//}}}
00609   ExNode* do_name(bool is_fun, std::string key, ExNode* params)//{{{
00610   {
00611     (void) is_fun; // FIXME Unused parameter
00612     if (is_alias(key)) return do_getctrl(aliases_[key]);
00613     int kind=getKind(key); ExNode* u=NULL;
00614     if (kind==T_FUN) {
00615       u=getFunctionCopy(key,params);
00616     }
00617     else if (kind==T_VAR||kind==T_CONST) {
00618       ExRecord* nd=symbol_table.getRecord(key);
00619       u=new ExNode_ReadVar(nd,key);
00620     }
00621     if (u==NULL) {
00622       MRSWARN("ExParser::do_name("+ltos(la->col)+")  Unbound name '"+key+"'");
00623       fail=true; delete params; return NULL;
00624     }
00625     return u;
00626   } //}}}
00627   ExNode* do_property(ExNode* u, std::string key, ExNode* params)//{{{
00628   {
00629     if (u!=NULL) {
00630       key=getDefaultLib(u->getType())+"."+key;
00631       u->next=params; params=u; u=NULL;
00632     }
00633     int kind=getKind(key);
00634     if (kind==T_CONST) {
00636       if (params!=NULL) {
00637         MRSWARN("ExParser::property   parameters supplied to non-function call: "+key);
00638         delete params; delete u; fail=true; return NULL;
00639       }
00640       ExVal v=symbol_table.getValue(key);
00641       u=new ExNode(v);
00642     } else if (kind==T_VAR) {
00644       if (params!=NULL) {
00645         MRSWARN("ExParser::property   parameters supplied to non-function call: "+key);
00646         delete params; delete u; fail=true; return NULL;
00647       }
00648       ExRecord* r=symbol_table.getRecord(key);
00649       u=new ExNode_ReadVar(r,key);
00650     } else if (kind==T_FUN) {
00651       u=getFunctionCopy(key,params);
00652       if (u==NULL) {
00653 //                MRSWARN("ExParser::property   unbound function call: "+key);
00654         params->deref(); fail=true; return NULL;
00655       }
00656     } else {
00657       MRSWARN("ExParser::property   unbound name: "+key);
00658       delete u; delete params; fail=true; u=NULL;
00659     }
00660     return u;
00661   }//}}}
00662   ExNode* do_getelem(ExNode* u, ExNode* lidx, ExNode* ridx, bool is_range)//{{{
00663   {
00664     if (!u->is_seq()) {
00665       MRSWARN("ExParser::getelem  not a sequence type");
00666       fail=true; u->deref(); lidx->deref();
00667       if (ridx)ridx->deref(); return NULL;
00668     }
00669 //        int kind=u->getKind();
00670 //        if (kind==T_VAR||kind==T_CONST) {
00671     if (is_range) u=new ExNode_Range(u,lidx,ridx);
00672     else u=new ExNode_GetElem(u,lidx);
00673 //        }
00674     return u;
00675   }//}}}
00676   ExNode* do_setelem(std::string key, ExNode* lidx, ExNode* ridx, bool is_range, ExNode* u)//{{{
00677   {
00678     if (getKind(key)==T_VAR) {
00679       ExRecord* nd=symbol_table.getRecord(key);
00680       if (nd==NULL) {
00681         MRSWARN("ExParser::setelem  unbound name "+key);
00682         u->deref(); lidx->deref(); if(ridx)ridx->deref(); fail=true; u=NULL;
00683       } else if (nd->is_seq()) {
00684         if (nd->getElemType()==u->getType()) {
00685           if (is_range) {
00686             MRSWARN("ExParser::setelem  setting element as range not supported");
00687             u->deref(); u=NULL; lidx->deref(); if(ridx)ridx->deref(); fail=true;
00688           } else {
00689             u=new ExNode_SetElem(nd,lidx,u);
00690           }
00691         } else {
00692           MRSWARN("ExParser::setelem  type mismatch in setelem");
00693           u->deref(); u=NULL; lidx->deref(); if(ridx)ridx->deref(); fail=true;
00694         }
00695       } else {
00696         MRSWARN("ExParser::setelem  not a sequence type");
00697         fail=true; u->deref(); u=NULL; lidx->deref(); if(ridx)ridx->deref();
00698       }
00699     }
00700     return u;
00701   }//}}}
00702   ExNode* do_msetelem(std::string key, ExNode* lidx, ExNode* ridx, bool is_range, bool right_assign, int atype, ExNode* u)//{{{
00703   {
00704     // get name type, it must exist because we need read it
00705     std::string rt=getElemType(key);
00706     if (rt=="") {
00707       MRSWARN("ExParser: Unbound name '"+key+"'");
00708       fail=true; u->deref(); return NULL;
00709     }
00710     ExNode* v=NULL;
00711     ExRecord* nd=symbol_table.getRecord(key);
00712     if (nd==NULL) {
00713       MRSWARN("ExParser::getelem  unbound name "+key); fail=true;
00714     } else {
00715       v=do_getelem(new ExNode_ReadVar(nd,key),lidx,ridx,is_range);
00716     }
00717 
00718     if (v!=NULL) {
00719       if (!right_assign) { ExNode* a=u; u=v; v=a; }
00720       if (atype==OP_ADD||atype==OP_SUB) { u=do_addop(atype,u,v); }
00721       else if (atype==OP_MUL||atype==OP_DIV||atype==OP_MOD) { u=do_mulop(atype,u,v); }
00722       else { u=do_condop(atype,u,v); }
00723       if (u==NULL) return NULL;
00724       return do_setelem(key,lidx,ridx,is_range,u);
00725     }
00726     return NULL;
00727   }//}}}
00728   ExNode* list_append(ExNode* u, ExNode* v)//{{{
00729   {
00730     if (u==NULL) return v;
00731     if (u->getType()!=v->getType()) {
00732       MRSWARN("ExParser::list_append  type mismatch in list declaration");
00733       u->deref(); v->deref(); fail=true; return NULL;
00734     }
00735     ExNode* x=u; while (u->next!=NULL) { u=u->next; } u->next=v;
00736     return x;
00737   }//}}}
00738   ExNode* do_list(bool is_empty, ExNode* u)//{{{
00739   {
00740     if (is_empty) { return new ExNode(ExVal(0,NULL)); }
00741     mrs_natural len=0; ExNode* x=u; while (x!=NULL) { len++; x=x->next; }
00742     ExNode** elems=new ExNode*[len];
00743     int l=0; x=u; while (x!=NULL) { ExNode* y=x; elems[l]=x; l++; x=x->next; y->next=NULL; }
00744     return new ExNode(ExVal(len,(ExNode**)elems));
00745   }//}}}
00746   ExNode* do_iter(int iter_type, std::string var_nm, std::string ary_nm, ExNode* list, ExNode* exprs)//{{{
00747   {
00748     ExRecord* var=symbol_table.getRecord(var_nm);
00749     if (list && !list->is_seq()) {
00750       MRSWARN("ExParser::iterator  Expected sequence type to iterator");
00751       list->deref(); exprs->deref();
00752       fail=true;
00753       return NULL;
00754     }
00755     ExNode* e=NULL;
00756     if (iter_type==1) { // map
00757       if (list->getType()=="mrs_string") {
00758         e=new ExNode_StringMap(list,var,exprs,"mrs_string");
00759       } else {
00760         std::string rt=exprs_type(exprs)+" list";
00761         e=new ExNode_IterMap(list,var,exprs,rt);
00762       }
00763     }
00764     else if (iter_type==2) { // iter
00765       // note that list is null in this case, ary_nm is key to the list
00766       ExRecord* original=symbol_table.getRecord(ary_nm);
00767       if (original->getType()=="mrs_string") {
00768         e=new ExNode_StringIter(original,var,exprs);
00769       } else {
00770         if (original==NULL) {
00771           if (exprs) exprs->deref();
00772         }
00773         e=new ExNode_IterIter(original,var,exprs);
00774       }
00775     }
00776     else if (iter_type==3) { // for
00777       if (list->getType()=="mrs_string") {
00778         e=new ExNode_StringFor(list,var,exprs);
00779       } else {
00780         e=new ExNode_IterFor(list,var,exprs);
00781       }
00782     }
00783     else if (iter_type==4) { // rfor
00784       if (list->getType()=="mrs_string") {
00785         e=new ExNode_StringRFor(list,var,exprs);
00786       } else {
00787         e=new ExNode_IterRFor(list,var,exprs);
00788       }
00789     }
00790     return e;
00791   }//}}}
00792 
00793   /******************************************************************/
00794 
00795 
00796   ExParser(TmTimer** t, ExScanner *scanner);
00797   ~ExParser();
00798   void SemErr(char* msg);
00799 
00800   void Alias(std::string& nm);
00801   void Name(std::string& nm);
00802   void CName(std::string& nm);
00803   void AddOp(int& m);
00804   void MulOp(int& m);
00805   void RelOp(int& m);
00806   void LAsgnOp(int& type);
00807   void RAsgnOp(int& type);
00808   void Exprs(ExNode** u);
00809   void Task(ExNode** u);
00810   void LAsgn(ExNode** u);
00811   void Link(ExNode** u);
00812   void RAsgn(ExNode** u);
00813   void Condition(ExNode** u);
00814   void CondTerm(ExNode** u);
00815   void CondFact(ExNode** u);
00816   void Expr(ExNode** u);
00817   void Term(ExNode** u);
00818   void Property(ExNode** u);
00819   void Factor(std::string& l, ExNode** u);
00820   void ListElems(ExNode** u);
00821   void Sequence(std::string& l, ExNode** u);
00822   void ElemAccess(ExNode** u);
00823   void FactorB(std::string& l, ExNode** u);
00824   void Elem(ExNode*& idx);
00825   void Use();
00826   void Load();
00827   void UL();
00828   void Neil();
00829 
00830   void Parse();
00831   void Parse(Scheduler* v, MarSystem* m, ExRecord* est);
00832 
00833 }; // end ExParser
00834 
00835 }; // namespace
00836 
00837 #endif // !defined(MARSYAS_EX_PARSER_H)
00838