Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

Parser.C

Go to the documentation of this file.
00001 // Copyright (C) 2001, Compaq Computer Corporation
00002 // 
00003 // This file is part of Vesta.
00004 // 
00005 // Vesta is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 // 
00010 // Vesta is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 /* File: Parser.C                                              */
00020 /* Last Modified On Wed Apr 27 09:23:11 EDT 2005 by irina.furman@intel.com */
00021 /*      Modified On Fri Aug  6 13:13:54 EDT 2004 by ken@xorian.net */
00022 /*      Modified On Mon Jan 22 13:04:04 PST 2001 by yuanyu     */
00023 /*      Modified On Sat Feb 12 17:54:55 PST 2000 by mann       */
00024 /*      Modified On Tue May  4 14:23:59 PDT 1999 by heydon     */
00025 /*      Modified On Tue Mar  5 12:12:46 PST 1996 by levin      */
00026 /*      Modified On Fri Jan 26 18:31:28 PST 1996 by horning    */
00027 /*      Modified On Wed Dec  8 20:10:17 PST 1993 by hanna      */
00028 
00029 #include "Parser.H"
00030 #include "Files.H"
00031 #include "Lex.H"
00032 #include "ModelState.H"
00033 #include "Err.H"
00034 #include "Expr.H"
00035 #include "Val.H"
00036 #include "Prim.H"
00037 #include <iostream>
00038 
00039 using std::istream;
00040 
00041 static char *pragmaNoCache = "nocache";
00042 static char *pragmaInPK    = "pk";
00043 
00044 // State for the parser:
00045 static Token eatenToken, token, nextToken;
00046 static bool hasNextToken = false;
00047 
00048 void PError(const Text& msg) {
00049   outputMu.lock();  
00050   Error(msg, token.loc);
00051   outputMu.unlock();  
00052   throw "\nParsing terminated.\n";
00053 }
00054 
00055 inline void NextToken() {
00056   if (hasNextToken) {
00057     token.TokenAssign(nextToken);
00058     hasNextToken = false;
00059   }
00060   else
00061     token.Next();
00062   return;
00063 }
00064 
00065 inline void TokenLookAhead() {
00066   if (!hasNextToken) {
00067     nextToken.Next();
00068     hasNextToken = true;
00069   }
00070   return;
00071 }
00072 
00073 bool AtToken(TokenClass tc) {
00074   while (token.tclass == TkPragma &&
00075          strcmp(token.Bytes(), pragmaInPK) &&
00076          strcmp(token.Bytes(), pragmaNoCache)) {
00077     NextToken();
00078   }
00079   return (token.tclass == tc);
00080 }
00081 
00082 bool AtDelimiter() {
00083   while (token.tclass == TkPragma &&
00084          strcmp(token.Bytes(), pragmaInPK) &&
00085          strcmp(token.Bytes(), pragmaNoCache)) {
00086     NextToken();
00087   }
00088   return ((token.tclass == TkSlash) ||
00089           (token.tclass == TkBackSlash));
00090 }
00091 
00092 bool AtArc() {
00093   while (token.tclass == TkPragma &&
00094          strcmp(token.Bytes(), pragmaInPK) &&
00095          strcmp(token.Bytes(), pragmaNoCache)) {
00096     NextToken();
00097   }
00098   return ((token.tclass == TkId) ||
00099           (token.tclass == TkNumber) ||
00100           (token.tclass == TkString));
00101 }
00102 
00103 inline bool EatPragma() {
00104   if (token.tclass == TkPragma) {
00105     eatenToken.TokenAssign(token);
00106     NextToken();
00107     return true;
00108   }
00109   return false;
00110 }
00111 
00112 inline bool EatToken(TokenClass tc) {
00113   if (AtToken(tc)) {
00114     eatenToken.TokenAssign(token);
00115     NextToken();
00116     return true;
00117   }
00118   return false;
00119 }
00120 
00121 inline bool EatName(Name& name) {
00122   if (AtToken(TkId)) {
00123     name = (Name)(token.expr);
00124     eatenToken.TokenAssign(token);
00125     NextToken();
00126     return true;
00127   }
00128   return false;
00129 }
00130 
00131 inline bool EatArc(Name& arc) {
00132   if (AtArc()) {
00133     arc = NEW_CONSTR(NameEC, (token.AsText(), token.loc));
00134     eatenToken.TokenAssign(token);
00135     NextToken();
00136     return true;
00137   }
00138   return false;
00139 }
00140 
00141 inline bool EatDelimiter() {
00142   if (AtDelimiter()) {
00143     eatenToken.TokenAssign(token);
00144     NextToken();
00145     return true;
00146   }
00147   return false;
00148 }
00149 
00150 void Expect(TokenClass tk, char *msg) {
00151   if (!EatToken(tk))
00152     PError(Text("Expected ") + msg + "  Current token class: "
00153       + TokenNames[token.tclass] + ", `" + token.AsText() + "'.\n");
00154 }
00155 
00156 inline Name GetName() {
00157   Expect(TkId, "identifier.");
00158 
00159   Name name = (Name)(eatenToken.expr);
00160   return name;
00161 }
00162 
00163 Text ModelPath(const Text& from, const Text& path) {
00164   int fromLast = from.Length()-1;
00165 
00166   if (fromLast < 0) return path;
00167   if (path.Empty()) return from;
00168   if (IsDelimiter(from[fromLast])) {
00169     if (IsDelimiter(path[0]))
00170       return from + path.Sub(1);
00171     else
00172       return from + path;
00173   }
00174   else {
00175     if (IsDelimiter(path[0]))
00176       return from + path;
00177     else
00178       return from + PathnameSep + path;
00179   }
00180 }
00181 
00182 Expr ConvertToBindElem(Expr lhs, Expr rhs) {
00183   // Not used.
00184   Name name;
00185 
00186   switch (lhs->kind) {
00187   case NameEK:
00188     ((Name)lhs)->ClearFreeVars();
00189     return NEW_CONSTR(BindEC, (lhs, rhs, lhs->loc));
00190   case ConstantEK:
00191     {
00192       Val v = ((ConstantEC*)lhs)->val;
00193       if (v->vKind == IntegerVK)
00194         name = NEW_CONSTR(NameEC, (PrintForm(v), lhs->loc));
00195       else if (v->vKind == TextVK)
00196         name = NEW_CONSTR(NameEC, (((TextVC*)v)->NDS(), lhs->loc));
00197       else {
00198         Error("Expected left side of binding, found: `", lhs->loc);
00199         ErrorVal(v);
00200         ErrorDetail("'.\n");
00201         return NEW_CONSTR(ErrorEC, (token.loc));
00202       }
00203       name->ClearFreeVars();
00204       return NEW_CONSTR(BindEC, (name, rhs, lhs->loc));
00205     }
00206   case SelectEK:
00207     {
00208       BindingEC *be = NEW_CONSTR(BindingEC, (1, token.loc));
00209       SelectEC *sel = (SelectEC*)lhs;
00210       be->AddExpr(NEW_CONSTR(BindEC, (sel->field, rhs, sel->field->loc)));
00211       return ConvertToBindElem(sel->binding, be);
00212     }
00213   default:
00214     Error("Invalid left side of binding element: `", lhs->loc);
00215     ErrorExpr(lhs);
00216     ErrorDetail("'.\n");
00217     return NEW_CONSTR(ErrorEC, (token.loc));
00218   }
00219   // assert(false); // not reached
00220 }
00221 
00222 void InitState(istream *lexIn, const Text& modelName, ShortId sid,
00223                VestaSource *modelRoot) {
00224   ModelStateInit(lexIn, modelRoot);
00225   token.Init(modelName, sid);
00226   NextToken();
00227 }
00228 
00229 /* The recursive descent parsing function signatures: */
00230 Expr Model        ();
00231 
00232 ExprList Files    ();
00233 Expr FileItem     (bool couldBeList);
00234 Expr FileList     ();
00235 
00236 ExprList Imports  ();
00237 Expr IncItem      (const Text& from, bool hasForm, bool couldBeList);
00238 Expr IncList      (const Text& from, bool hasForm);
00239 Text DelimPath    (Name& arc, bool arcSeen);
00240 
00241 Expr Block        ();
00242 Expr Stmt         ();
00243 Expr Func         (const Text& name, bool noCache);
00244 ArgList Formals   ();
00245 Expr Assign       (Name name);
00246 Expr Iterate      ();
00247 Expr Control      ();
00248 
00249 Expr Expression   ();
00250 Expr Expr1        ();
00251 Expr Expr2        ();
00252 Expr Expr3        ();
00253 Expr Expr4        ();
00254 Expr Expr5        ();
00255 Expr Expr6        ();
00256 Expr Expr7        ();
00257 Expr Expr8        ();
00258 Expr Primary      ();
00259 
00260 Expr BindingCons  (Expr e);
00261 Expr BindElem     ();
00262 Expr ListCons     (Expr e);
00263 Expr GenArc       ();
00264 ArgList Actuals   ();
00265 Expr TypeDef      ();
00266 Expr Type         ();
00267 
00269 Expr Model() {
00270   ExprList files   = Files();
00271   ExprList imports = Imports();
00272   Expr block       = Block();
00273   return NEW_CONSTR(ModelEC, (files, imports, block, mRoot, files->loc));
00274 }
00275 
00276 ExprList Files() {
00277   ExprList dir = NEW_CONSTR(ExprListEC, (5, token.loc));
00278   bool looking;
00279 
00280   while (EatToken(TkFiles)) {
00281     looking = true;
00282     while (looking && (AtArc() || AtDelimiter())) {
00283       dir->AddExpr(FileItem(true));
00284       looking = EatToken(TkSemicolon);
00285     }
00286   }
00287   return dir;
00288 }
00289 
00290 Expr FileItem(bool couldBeList) {
00291   SrcLoc *eL = token.loc;
00292   Text path;
00293   Name arc, junque;
00294   Expr item;
00295   
00296   // assert(AtArc() || AtDelimiter())
00297   if (EatArc(arc)) {
00298     if (EatToken(TkEqual))
00299       if (EatToken(TkLBracket))
00300         if (couldBeList)
00301           item = FileList();
00302         else
00303           PError("Nested file lists not allowed.");
00304       else
00305         item = NEW_CONSTR(FileEC, 
00306                           (arc, DelimPath(junque, false), mRoot, false, eL));
00307     else if (AtDelimiter()) {
00308       path = DelimPath(arc, true);
00309       item = NEW_CONSTR(FileEC, (arc, path, mRoot, false, eL));
00310     }
00311     else
00312       item = NEW_CONSTR(FileEC, (arc, arc->id, mRoot, false, eL));
00313   }
00314   else if (AtDelimiter()) {
00315     path = DelimPath(arc, false);
00316     item = NEW_CONSTR(FileEC, (arc, path, mRoot, false, eL));
00317   }
00318   else
00319     PError("Must be an arc: identifier, integer, or string.");
00320   return NEW_CONSTR(BindEC, (arc, item, eL));
00321 }
00322 
00323 Expr FileList() {
00324   BindingEC *files = NEW_CONSTR(BindingEC, (5, token.loc));
00325   bool looking = true;
00326   
00327   while (looking && (AtArc() || AtDelimiter())) {
00328     files->AddExpr(FileItem(false));
00329     looking = EatToken(TkComma);
00330   }
00331   Expect(TkRBracket, "`]' to terminate file list.");
00332   return files;
00333 }
00334 
00335 ExprList Imports() {
00336   SrcLoc *eL = token.loc;;
00337   Text from;
00338   Name name, junque;
00339   ExprList dir = NEW_CONSTR(ExprListEC, (5, eL));
00340   bool hasFrom, looking;
00341 
00342   // Always import self!
00343   Name arc = NEW_CONSTR(NameEC, ("_self", eL));
00344   Text selfHead, selfTail;
00345   SplitPath(eL->file, selfHead, selfTail);
00346   Expr item = NEW_CONSTR(FileEC, (arc, selfTail, mRoot, true, eL));
00347   dir->AddExpr(NEW_CONSTR(BindEC, (arc, item, eL)));
00348   
00349   while (AtToken(TkFrom) || AtToken(TkImport)) {
00350     hasFrom = false;
00351     if (EatToken(TkFrom)) {
00352       from = DelimPath(junque, false);
00353       hasFrom = true;
00354     }
00355     Expect(TkImport, "`import' at head of model list.");
00356     looking = true;
00357     while (looking && AtArc()) {
00358       dir->AddExpr(IncItem(from, hasFrom, true));
00359       looking = EatToken(TkSemicolon);
00360     }
00361   }
00362   return dir;
00363 }
00364 
00365 Expr IncItem(const Text& from, bool hasFrom, bool couldBeList) {
00366   SrcLoc *eL = token.loc;
00367   Text path, rest;
00368   Name arc, junque;
00369   Expr item;
00370   bool isList = false;
00371 
00372   if (!EatArc(arc)) {
00373     PError("Must be an arc: identifier, integer, or string.");
00374   }
00375 
00376   if (EatToken(TkEqual))
00377     if (EatToken(TkLBracket))
00378       if (couldBeList) {
00379         item = IncList(from, hasFrom);
00380         isList = true;
00381       }
00382       else
00383        PError("Nested import lists not allowed.");
00384     else if (hasFrom && AtDelimiter())
00385       PError("A delimiter is not permitted after this equality sign.");
00386     else {
00387       rest = DelimPath(junque, false);
00388       path = ModelPath(from, rest);
00389     }
00390   else if (!hasFrom) {
00391     PError("An explicit `id =' must precede this path.");
00392   }
00393   else if (AtDelimiter()) {
00394     Name more = arc;
00395     rest = DelimPath(more, true);
00396     path = ModelPath(from, rest);
00397   }
00398   else {
00399     path = ModelPath(from, arc->id);
00400   }
00401 
00402   if (!isList)
00403     item = NEW_CONSTR(FileEC, (arc, path, mRoot, true, eL));
00404   return NEW_CONSTR(BindEC, (arc, item, eL));
00405 }
00406 
00407 Expr IncList(const Text& from, bool hasFrom) {
00408   BindingEC *imports = NEW_CONSTR(BindingEC, (5, token.loc));
00409   bool looking = true;
00410   
00411   while (looking && AtArc()) {
00412     imports->AddExpr(IncItem(from, hasFrom, false));
00413     looking = EatToken(TkComma);
00414   }
00415   Expect(TkRBracket, "`]' to terminate import list.");
00416   return imports;
00417 }
00418 
00419 Text DelimPath(Name& arc, bool arcSeen) {
00420   Text path;
00421   
00422   if (arcSeen) {
00423     if (!AtDelimiter())
00424       return arc->id;
00425     path = arc->id;
00426   }
00427   /*
00428   else if (EatArc(arc)) {
00429     path = arc->id;
00430   }
00431   */  
00432   else {
00433     if (AtDelimiter()) {
00434       path += token.AsText();
00435       NextToken();
00436     }
00437     if (EatArc(arc)) {
00438       path += arc->id;
00439     }
00440     else {
00441       PError("Must be an arc: identifier, integer, or string.");
00442     }
00443   }
00444 
00445   while (AtDelimiter()) {
00446     path += token.AsText();
00447     NextToken();
00448     if (EatArc(arc))
00449       path += arc->id;
00450     else break;
00451   }
00452   return path;
00453 }
00454 
00455 Expr Block() {
00456   SrcLoc *eL = token.loc;
00457   StmtListEC *assocs = NEW_CONSTR(StmtListEC, (token.loc));
00458   bool looking = true;
00459 
00460   Expect(TkLBrace, "`{' at start of block.");
00461   while (looking && !EatToken(TkReturn) && !EatToken(TkValue)) {
00462     assocs->AddExpr(Stmt());
00463     looking = EatToken(TkSemicolon);
00464   }
00465   if (looking) {
00466     bool ret = (eatenToken.tclass == TkReturn);
00467     Expr body = Expression();
00468     looking = EatToken(TkSemicolon);
00469     Expect(TkRBrace, "`}' at end of block.");
00470     return NEW_CONSTR(BlockEC, (assocs, body, ret, eL));
00471   }
00472   else
00473     PError("Expecting semicolon.\n");
00474   return NULL; // not reached
00475 }
00476 
00477 Expr Stmt() {
00478   Name name;
00479   bool noCache = false;
00480 
00481   if (EatPragma()) {
00482     noCache = !strcmp(eatenToken.Bytes(), pragmaNoCache);
00483   }
00484   if (EatName(name)) {
00485     if (AtToken(TkLParen)) {
00486       return NEW_CONSTR(AssignEC, 
00487                         (name, Func(name->id, noCache), true, name->loc));
00488     }
00489     else {
00490       return NEW_CONSTR(AssignEC, 
00491                         (name, Assign(name), false, name->loc));
00492     }
00493   }
00494   if (EatToken(TkType)) {
00495     return TypeDef();
00496   }
00497   if (AtToken(TkForeach)) {
00498     return Iterate();
00499   }
00500   PError("Expected assignment, function def, type def, or iteration.\n");
00501   return NULL; // not reached
00502 }
00503 
00504 Expr Func(const Text& name, bool noCache) {
00505   SrcLoc *eL = token.loc;
00506   Expr type = NULL;
00507 
00508   if (EatToken(TkLParen))
00509     {
00510       ArgList l_formals = Formals();
00511       Expr l_body = Func(name + "()", noCache);
00512       return NEW_CONSTR(FuncEC, (noCache, name, l_formals, l_body, eL));
00513     }
00514   if (EatToken(TkColon))
00515     type = Type();
00516   return Block();
00517 }
00518 
00519 ArgList Formals() {
00520   ArgList formals = NEW_CONSTR(ArgListEC, (5, token.loc));
00521   Name name;
00522   bool looking = true;
00523   bool eqSeen = false;
00524   Expr type = NULL;
00525 
00526   if (EatToken(TkRParen)) {
00527     return formals;
00528   }
00529   while (looking) {
00530     SrcLoc *eL = token.loc;
00531     bool inPK = false;
00532     if (EatPragma()) {
00533       inPK = !strcmp(eatenToken.Bytes(), pragmaInPK);
00534     }
00535     if (EatName(name)) {
00536       if (name->id == nameDot) {
00537         PError("`.' not allowed as a formal parameter.\n");
00538       }
00539       for (int i = 0; i < formals->elems.size(); i++) {
00540         if (((Name)formals->elems.get(i))->id == name->id)
00541           PError(Text("`") + name->id 
00542                  + Text("' occurs more than once in parameter list.\n"));
00543       }
00544       if (EatToken(TkColon)) type = Type();
00545       eqSeen = (eqSeen || AtToken(TkEqual));
00546       if (eqSeen) {
00547         Expect(TkEqual, "`=' for parameter default.");
00548         formals->AddExpr(NEW_CONSTR(AssignEC, (name, Expression(), false, eL)),
00549                          inPK);
00550       }
00551       else {
00552         name->ClearFreeVars();
00553         formals->AddExpr(name, inPK);
00554       }
00555       looking = EatToken(TkComma);
00556     }
00557     else {
00558       // Error: a formal must be an Id.
00559       Expect(TkId, "identifier for formals.");
00560     }
00561   }
00562   assert(formals->Length() < 65);
00563   Expect(TkRParen, "`)' at end of formal list.");
00564   return formals;
00565 }
00566 
00567 Expr Assign(Name name) {
00568   Text op;
00569   Expr type = NULL;
00570 
00571   if (EatToken(TkColon))
00572     type = Type();
00573   if (AtToken(TkPlus) || AtToken(TkPlusPlus) || AtToken(TkMinus) ||
00574       AtToken(TkStar)) {
00575     op = token.AsText();
00576     NextToken();
00577   }
00578   Expect(TkEqual, "`=' in assignment.");
00579   Expr e = Expression();
00580   if (op.Empty())
00581     return e;
00582   return NEW_CONSTR(ApplyOpEC, (name, op, e, name->loc));
00583 }
00584 
00585 Expr Iterate() {
00586   SrcLoc *eL = token.loc;
00587   
00588   Expect(TkForeach, "`foreach' or other statement starter.");
00589   Expr control = Control();
00590   Expect(TkIn, "`in' following iteration variable.");
00591   Expr e = Expression();
00592   Expect(TkDo, "`do' following iteration expression.");
00593   StmtListEC *stmts = NEW_CONSTR(StmtListEC, (token.loc));
00594 
00595   bool looking = true;
00596   if (EatToken(TkLBrace)) {
00597     while (looking && !AtToken(TkRBrace)) {
00598       stmts->AddExpr(Stmt());
00599       looking = EatToken(TkSemicolon);
00600     }
00601     Expect(TkRBrace, "`}' following statements of iteration body.");
00602   }
00603   else
00604     stmts->AddExpr(Stmt());;
00605   return NEW_CONSTR(IterateEC, (control, e, stmts, eL));
00606 }
00607 
00608 Expr Control() {
00609   SrcLoc *eL = token.loc;
00610   Name name1, name2;
00611   Expr type = NULL;
00612   
00613   if (EatToken(TkLBracket)) {
00614     name1 = GetName();
00615     if (EatToken(TkColon)) type = Type();
00616     Expect(TkEqual, "`=' in iteration control pair.");
00617     name2 = GetName();
00618     if (EatToken(TkColon)) type = Type();
00619     Expect(TkRBracket, "`]' following iteration control pair.");
00620     return NEW_CONSTR(PairEC, (name1, name2, eL));
00621   }
00622   name1 = GetName();
00623   if (EatToken(TkColon)) type = Type();
00624   return name1;
00625 }
00626 
00627 Expr Expression() {
00628   SrcLoc *eL = token.loc;
00629 
00630   if (EatToken(TkIf)) {
00631     Expr e1 = Expression();
00632     Expect(TkThen, "`then' following `if' expression.");
00633     Expr e2 = Expression();
00634     Expect(TkElse, "`else' following `then' expression.");
00635     return NEW_CONSTR(IfEC, (e1, e2, Expression(), eL));
00636   }
00637   return Expr1();
00638 }
00639 
00640 Expr Expr1() {
00641   SrcLoc *eL = token.loc;
00642 
00643   Expr e = Expr2();
00644   while (EatToken(TkImplies))
00645     e = NEW_CONSTR(ApplyOpEC, (e, "=>", Expr2(), eL));
00646   return e;
00647 }
00648 
00649 Expr Expr2() {
00650   SrcLoc *eL = token.loc;
00651 
00652   Expr e = Expr3();
00653   while (EatToken(TkOr))
00654     e = NEW_CONSTR(ApplyOpEC, (e, "||", Expr3(), eL));
00655   return e;
00656 }
00657 
00658 Expr Expr3() {
00659   SrcLoc *eL = token.loc;
00660 
00661   Expr e = Expr4();
00662   while (EatToken(TkAnd))
00663     e = NEW_CONSTR(ApplyOpEC, (e, "&&", Expr4(), eL));
00664   return e;
00665 }
00666 
00667 Expr Expr4() {
00668   SrcLoc *eL = token.loc;
00669 
00670   Expr e = Expr5();
00671   if (AtToken(TkGreater)) {
00672     TokenLookAhead();
00673     if ((nextToken.tclass == TkNumber)    ||
00674         (nextToken.tclass == TkString)    ||
00675         (nextToken.tclass == TkId)        ||
00676         (nextToken.tclass == TkTrue)      ||
00677         (nextToken.tclass == TkFalse)     ||
00678         (nextToken.tclass == TkErr)       ||
00679         (nextToken.tclass == TkMinus)     ||
00680         (nextToken.tclass == TkBang)      ||
00681         (nextToken.tclass == TkLParen)    ||
00682         (nextToken.tclass == TkLess)      ||
00683         (nextToken.tclass == TkLBracket)  ||
00684         (nextToken.tclass == TkLBrace)) {
00685       // > is treated as arithmetic operator.
00686       EatToken(TkGreater);
00687       Text l_op = eatenToken.AsText();
00688       return NEW_CONSTR(ApplyOpEC, (e, l_op, Expr5(), eL));
00689     }
00690   }
00691   else if (EatToken(TkEqEq)    ||
00692            EatToken(TkNotEq)   ||
00693            EatToken(TkLess)    ||
00694            EatToken(TkLessEq)  ||
00695            EatToken(TkGreaterEq))
00696     {
00697       Text l_op = eatenToken.AsText();
00698       return NEW_CONSTR(ApplyOpEC, (e, l_op, Expr5(), eL));
00699     }
00700   return e;
00701 }
00702 
00703 Expr Expr5() {
00704   SrcLoc *eL = token.loc;
00705   Text op;
00706 
00707   Expr e = Expr6();
00708   while (AtToken(TkPlus) || AtToken(TkPlusPlus) ||
00709          AtToken(TkMinus)) {
00710     op = token.AsText();
00711     NextToken();
00712     e = NEW_CONSTR(ApplyOpEC, (e, op, Expr6(), eL));
00713   }
00714   return e;
00715 }
00716 
00717 Expr Expr6() {
00718   SrcLoc *eL = token.loc;
00719 
00720   Expr e = Expr7();
00721   while (AtToken(TkStar)) {
00722     NextToken();
00723     e = NEW_CONSTR(ApplyOpEC, (e, "*", Expr7(), eL));
00724   }
00725   return e;
00726 }
00727 
00728 Expr Expr7() {
00729   SrcLoc *eL = token.loc;
00730   
00731   if (EatToken(TkMinus))
00732     return NEW_CONSTR(ApplyUnOpEC, ("-", Primary(), eL));
00733   if (EatToken(TkBang))
00734     return NEW_CONSTR(ApplyUnOpEC, ("!", Primary(), eL));
00735   return Expr8();
00736 }
00737 
00738 Expr Expr8() {
00739   SrcLoc *eL = token.loc;
00740   Expr e = Primary();
00741   Expr type = NULL;
00742 
00743   if (EatToken(TkColon))
00744     type = Type();
00745   return e;
00746 }
00747 
00748 Expr Primary() {
00749   SrcLoc *eL = token.loc;
00750   Expr primary;
00751   ExprList elems;
00752 
00753   switch (token.tclass) {
00754   case TkId:
00755     {
00756       Name name = (Name)token.expr;
00757       PrimExec prim = LookupPrim(name->id);
00758       if (prim == NULL)
00759         primary = name;
00760       else
00761         primary = NEW_CONSTR(PrimitiveEC, (name->id, prim, eL));
00762       NextToken();
00763       break;
00764     }
00765   case TkString: case TkNumber:
00766     primary = token.expr;
00767     NextToken();
00768     return primary;
00769   case TkErr:
00770     NextToken();
00771     return NEW_CONSTR(ErrorEC, (token.loc, false));
00772   case TkTrue:
00773     NextToken();
00774     return NEW_CONSTR(ConstantEC, (valTrue, eL));
00775   case TkFalse:
00776     NextToken();
00777     return NEW_CONSTR(ConstantEC, (valFalse, eL));
00778   case TkLParen:
00779     NextToken();
00780     primary = Expression();
00781     Expect(TkRParen, "`)' to match `(' in primary.");
00782     break;
00783   case TkLBracket:              // constructing a binding
00784     NextToken();
00785     if (EatToken(TkRBracket))
00786       primary = NEW_CONSTR(BindingEC, (0, eL));
00787     else
00788       primary = BindingCons(BindElem());
00789     break;
00790   case TkLess:                  // constructing a List
00791     NextToken();
00792     if (EatToken(TkGreater))
00793       primary = NEW_CONSTR(ListEC, (0, eL));
00794     else
00795       primary = ListCons(Expression());
00796     break;
00797   case TkLBrace:
00798     primary = Block();
00799     break;
00800   default:
00801     PError(Text("Expected primary, saw `") + token.AsText() + "'.\n");
00802     break;
00803   }
00804   while (true) {
00805     if (EatToken(TkSlash) || EatToken(TkBackSlash))
00806       primary = NEW_CONSTR(SelectEC, (primary, GenArc(), false, primary->loc));
00807     else if (EatToken(TkBang))
00808       primary = NEW_CONSTR(SelectEC, (primary, GenArc(), true, primary->loc));
00809     else if (EatToken(TkLParen))
00810       primary = NEW_CONSTR(ApplyEC, (primary, Actuals(), primary->loc));
00811     else return primary;
00812   }
00813 }
00814 
00815 Expr GenArc() {
00816   Name name;
00817   Expr computed;
00818   
00819   if (EatArc(name)) {
00820     name->ClearFreeVars();
00821     return name;
00822   }
00823   if (EatToken(TkDollar)) {
00824     if (EatToken(TkLParen)) {
00825       computed = Expression();
00826       Expect(TkRParen, "`)' at end of computed field.");
00827     }
00828     else
00829       computed = GetName();
00830   }
00831   else if (EatToken(TkPercent)) {
00832     computed = Expression();
00833     Expect(TkPercent, "`%' at end of computed field.");
00834   }
00835   else
00836     Expect(TkErr, "name in binding field.");
00837   return NEW_CONSTR(ComputedEC, (computed));
00838 }
00839 
00840 Expr BindingCons(Expr e) {
00841   BindingEC *be = NEW_CONSTR(BindingEC, (5, e->loc));
00842   
00843   be->AddExpr(e);
00844   while (EatToken(TkComma) && !AtToken(TkRBracket))
00845     be->AddExpr(BindElem());
00846   Expect(TkRBracket, "`]' to end binding.");
00847   return be;
00848 }
00849 
00850 Expr BindElem() {
00851   Expr name = GenArc();
00852 
00853   if (EatDelimiter()) {
00854     if (EatToken(TkEqual))
00855       return NEW_CONSTR(BindEC, (name, Expression(), name->loc));
00856     BindingEC *be = NEW_CONSTR(BindingEC, (1, token.loc));
00857     be->AddExpr(BindElem());
00858     return NEW_CONSTR(BindEC, (name, be, name->loc));
00859   }
00860   if (EatToken(TkEqual))
00861     return NEW_CONSTR(BindEC, (name, Expression(), name->loc));
00862   if (eatenToken.tclass == TkId &&
00863       name->kind == NameEK) {
00864     Expr name1 = NEW_CONSTR(NameEC, (((NameEC*)name)->id, name->loc));
00865     return NEW_CONSTR(BindEC, (name, name1, name->loc));
00866   }
00867   PError(Text("Expected identifier.\n"));
00868   return NULL; // not reached
00869 }
00870 
00871 Expr ListCons(Expr e) {
00872   ListEC *elst = NEW_CONSTR(ListEC, (5, e->loc));
00873 
00874   elst->AddExpr(e);
00875   while (EatToken(TkComma) && !AtToken(TkGreater))
00876     elst->AddExpr(Expression());
00877   Expect(TkGreater, "`>' to end list.");
00878   return elst;
00879 }
00880 
00881 ArgList Actuals() {
00882   SrcLoc *eL = token.loc;
00883   ArgList actuals = NEW_CONSTR(ArgListEC, (5, token.loc));
00884   bool looking = true;
00885 
00886   while (looking && !AtToken(TkRParen)) {
00887     actuals->AddExpr(Expression(), false);
00888     looking = EatToken(TkComma);
00889   }
00890   Expect(TkRParen, "`)' at end of actual parameter list.");
00891   return actuals;
00892 }
00893 
00894 Expr TypeDef() {
00895   Name name;
00896 
00897   if (EatName(name)) {
00898     Expect(TkEqual, "`=' following identifier in type definition.");
00899     return NEW_CONSTR(AssignEC, (name, Type(), false, name->loc));
00900   }
00901   else
00902     PError("Expected type identifier.\n");
00903   return NULL; // not reached
00904 }
00905 
00906 Expr Type() {
00907   bool looking = true;
00908   Name name;
00909   SrcLoc *eL;
00910 
00911   if (EatToken(TkBool) || EatToken(TkInt) || EatToken(TkText))
00912     eL = token.loc;
00913   else if (EatToken(TkList)) {
00914     eL = token.loc;
00915     if (EatToken(TkLBracket)) {
00916       // This is here only for backward compatible.
00917       Type();
00918       Expect(TkRBracket, "`]' to close list type.");
00919     }
00920     else if (EatToken(TkLParen)) {
00921       Type();
00922       Expect(TkRParen, "`)' to close list type.");
00923     }
00924   }
00925   else if (EatToken(TkBinding)) {
00926     eL = token.loc;
00927     if (EatToken(TkLBracket)) {
00928       // This is here only for backward compatible.
00929       if (EatToken(TkColon))
00930         Type();
00931       else {
00932         while (looking && EatName(name)) {
00933           if (EatToken(TkColon))
00934             Type();
00935           looking = EatToken(TkComma);
00936         }
00937       }
00938       Expect(TkRBracket, "`]' to close binding type.");
00939     }
00940     else if (EatToken(TkLParen)) {
00941       if (EatToken(TkColon))
00942         Type();
00943       else {
00944         while (looking && EatName(name)) {
00945           if (EatToken(TkColon))
00946             Type();
00947           looking = EatToken(TkComma);
00948         }
00949       }
00950       Expect(TkRParen, "`)' to close binding type.");
00951     }
00952   }
00953   else if (EatToken(TkFunction)) {
00954     eL = token.loc;
00955     if (EatToken(TkLParen)) {
00956       while (looking && !AtToken(TkRParen)) {
00957         if (EatToken(TkId)) {
00958           if (EatToken(TkColon)) Type();
00959         } 
00960         else
00961           Type();
00962         looking = EatToken(TkComma);
00963       }
00964       Expect(TkRParen, "`)' to close function type.");
00965     }
00966     if (EatToken(TkColon))
00967       Type();
00968   }
00969   else {
00970     eL = token.loc;
00971     Expect(TkId, "type identifier or type expression.");
00972   }
00973   return NEW_CONSTR(BaseTEC, ("<Type>", eL));
00974 }
00975 
00976 // Parse a Vesta model:
00977 Expr Parse(istream *lexIn, const Text& name, ShortId sid, 
00978            VestaSource *modelRoot) {
00979   InitState(lexIn, name, sid, modelRoot);
00980   Expr result = Model();
00981   token.LexFlush();
00982   return result;
00983 }

Generated on Mon May 8 00:48:38 2006 for Vesta by  doxygen 1.4.2