Moved the interpreter
[repair.git] / Repair / RepairInterpreter / aparser.cc
diff --git a/Repair/RepairInterpreter/aparser.cc b/Repair/RepairInterpreter/aparser.cc
new file mode 100755 (executable)
index 0000000..57b8df9
--- /dev/null
@@ -0,0 +1,591 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "aparser.h"
+#include "list.h"
+#include "common.h"
+#include "token.h"
+#include "amodel.h"
+#include "omodel.h"
+#include "model.h"
+
+AParser::AParser(Reader *r) {
+  reader=r;
+}
+
+Rule * AParser::parserule() {
+  Token token=reader->peakahead();
+  while(token.token_type==TOKEN_EOL) {
+    skiptoken();
+    token=reader->peakahead();
+  }
+  if (token.token_type==TOKEN_EOF)
+    return NULL;
+  bool delay=false;bool staticrule=false;
+  if (token.token_type==TOKEN_DELAY||token.token_type==TOKEN_STATIC) {
+    /* both shouldn't be allowed..doesn't make sense...*/
+    if(token.token_type==TOKEN_DELAY)
+      delay=true;
+    else
+      staticrule=true;
+    skiptoken();
+    token=reader->peakahead();
+  }
+  Rule *c;
+  /*Get Quantifiers*/
+  if (token.token_type==TOKEN_OPENBRACK) {
+    skiptoken();
+    c=parsequantifiers();
+    needtoken(TOKEN_COMMA);
+  } else c=new Rule();
+  if (delay)
+    c->setdelay();
+  if (staticrule) {
+    int count=0;
+    for(int i=0;i<c->numquants();i++) {
+      AQuantifier *aq=c->getquant(i);
+      switch(aq->gettype()) {
+      case AQUANTIFIER_SING:
+       if (count>=1)
+         error();
+       count++;
+       break;
+      case AQUANTIFIER_RANGE:
+       break;
+      default:
+       error();
+      }
+    }
+    c->setstatic();
+  }
+  
+  /*Peek ahead to see if sizeof*/
+  c->setstatementa(parsestatementa(false));
+  needtoken(TOKEN_IMPLIES);
+  c->setstatementb(parsestatementb());
+  return c;
+}
+
+TypeEle * AParser::parsetypeele() {
+  Token type=reader->readnext();
+  needtoken(TOKEN_OPENPAREN);
+  List *list=new List();
+  while(true) {
+    Token token=reader->peakahead();
+    switch(token.token_type) {
+    case TOKEN_CLOSEPAREN: {
+      skiptoken();
+      AElementexpr** larray=new AElementexpr* [list->size()];
+      list->toArray((void **)larray);
+      TypeEle *t=new TypeEle(copystr(type.str),list->size(),larray);
+      delete(list);
+      return t;
+    }
+    default:
+      list->addobject(parseaelementexpr(false));
+      if (reader->peakahead().token_type!=TOKEN_CLOSEPAREN)
+       needtoken(TOKEN_COMMA);
+      break;
+    }
+  }
+}
+
+Type * AParser::parsetype() {
+  Token type=reader->readnext();
+  needtoken(TOKEN_OPENPAREN);
+  List *list=new List();
+  while(true) {
+    Token token=reader->readnext();
+    switch(token.token_type) {
+    case TOKEN_CLOSEPAREN:
+      {
+      Label** larray=new Label* [list->size()];
+      list->toArray((void **)larray);
+      Type *t=new Type(copystr(type.str),list->size(),larray);
+      delete(list);
+      return t;
+      }
+    default:
+      list->addobject(new Label(copystr(token.str)));
+      if (reader->peakahead().token_type!=TOKEN_CLOSEPAREN)
+       needtoken(TOKEN_COMMA);
+      break;
+    }
+  }
+}
+
+Statementa * AParser::parsestatementa(bool flag) {
+  Statementa * oldst=NULL;
+  AElementexpr *oldee=NULL;
+  int eeflag=-1;
+  int joinflag=-1;
+  while(true) {
+    Token token=reader->peakahead();
+    switch(token.token_type) {
+    case TOKEN_EOL:
+      error();
+    case TOKEN_OPENPAREN:
+      {
+       skiptoken();
+       Statementa *st=parsestatementa(false);
+       if (flag)
+         return st;
+       if (oldst==NULL) {
+         oldst=st;
+       } else {
+         if (joinflag==TOKEN_AND) {
+           oldst=new Statementa(oldst, st, STATEMENTA_AND);
+         } else if (joinflag==TOKEN_OR) {
+           oldst=new Statementa(oldst, st, STATEMENTA_OR);       
+         } else {
+           error();
+         }
+         joinflag=-1;
+       }
+      }
+      break;
+    case TOKEN_IMPLIES:
+      return oldst;
+    case TOKEN_CLOSEPAREN:
+      skiptoken();
+      return oldst;
+    case TOKEN_AND:
+      skiptoken();
+      if (oldst==NULL) error();
+      joinflag=TOKEN_AND;
+      break;
+    case TOKEN_OR:
+      skiptoken();
+      if (oldst==NULL) error();
+      joinflag=TOKEN_OR;
+      break;
+    case TOKEN_TRUE:
+      {
+       skiptoken();
+       Statementa *st=new Statementa();
+       if (flag)
+         return st;
+       if (oldst==NULL) {
+         oldst=st;
+       } else {
+         if (joinflag==TOKEN_AND) {
+           oldst=new Statementa(oldst, st, STATEMENTA_AND);
+         } else if (joinflag==TOKEN_OR) {
+           oldst=new Statementa(oldst, st, STATEMENTA_OR);       
+         } else {
+           error();
+         }
+         joinflag=-1;
+       }
+      }
+      break;
+    case TOKEN_NOT:
+      {
+       skiptoken();
+       Statementa * st=new Statementa(parsestatementa(true));
+       if (flag)
+         return st;
+       if (oldst==NULL) {
+         oldst=st;
+       } else {
+         if (joinflag==TOKEN_AND) {
+           oldst=new Statementa(oldst, st, STATEMENTA_AND);
+         } else if (joinflag==TOKEN_OR) {
+           oldst=new Statementa(oldst, st, STATEMENTA_OR);
+         } else {
+           error();
+         }
+         joinflag=-1;
+       }
+      }
+      break;
+    case TOKEN_IN: {
+      skiptoken();
+      Set *s=parseset();
+      if (oldee==NULL||eeflag!=-1)
+       error();
+      Statementa * st=new Statementa(oldee,s);
+      if (flag)
+       return st;
+      oldee=NULL;
+      if (oldst==NULL) {
+       oldst=st;
+      } else {
+       if (joinflag==TOKEN_AND) {
+         oldst=new Statementa(oldst, st, STATEMENTA_AND);
+       } else if (joinflag==TOKEN_OR) {
+         oldst=new Statementa(oldst, st, STATEMENTA_OR);
+       } else {
+         error();
+       }
+       joinflag=-1;
+      }
+    }
+    break;
+    case TOKEN_ISVALID: {
+      if (oldee!=NULL) error();
+      skiptoken();
+      needtoken(TOKEN_OPENPAREN);
+      AElementexpr *ae=parseaelementexpr(false);
+      Token t=reader->peakahead();
+      char *type=NULL;
+      if (t.token_type==TOKEN_COMMA) {
+       skiptoken();
+       Token t2=reader->readnext();
+       type=copystr(t2.str);
+      }
+      Statementa *st=new Statementa(ae, type);
+      needtoken(TOKEN_CLOSEPAREN);
+      if (flag)
+       return st;
+      if (oldst==NULL) {
+       oldst=st;
+      } else {
+       if (joinflag==TOKEN_AND) {
+         oldst=new Statementa(oldst, st, STATEMENTA_AND);
+       } else if (joinflag==TOKEN_OR) {
+         oldst=new Statementa(oldst, st, STATEMENTA_OR);
+       } else {
+         error();
+       }
+       joinflag=-1;
+      }
+    }
+      break;
+    case TOKEN_EQUALS:
+      skiptoken();
+      if (oldee==NULL) error();
+      eeflag=STATEMENTA_EQUALS;
+      break;
+    case TOKEN_LT:
+      skiptoken();
+      if (oldee==NULL) error();
+      eeflag=STATEMENTA_LT;
+      break;
+    default:
+      if ((oldee!=NULL) && (eeflag==-1))
+       error();
+      else if ((oldee==NULL)&&(eeflag==-1))
+       oldee=parseaelementexpr(false);
+      else {
+       /*oldee!=NULL, and joinee!=-1*/
+       Statementa * sa=new Statementa(oldee, parseaelementexpr(false), eeflag);
+       eeflag=-1;
+       oldee=NULL;
+       if (flag) return sa;
+       if (oldst==NULL) {
+         oldst=sa;
+       } else {
+         if (joinflag==TOKEN_AND) {
+           oldst=new Statementa(oldst, sa, STATEMENTA_AND);
+         } else if (joinflag==TOKEN_OR) {
+           oldst=new Statementa(oldst, sa, STATEMENTA_OR);       
+         } else {
+           error();
+         }
+         joinflag=-1;
+       }
+      }
+      break;
+    }
+  }
+}
+
+AElementexpr * AParser::checkdot(AElementexpr * incoming) {
+  Token tdot=reader->peakahead();
+  if (tdot.token_type!=TOKEN_DOT) return incoming;
+  skiptoken();
+  Token tfield=reader->readnext();
+  Token tpeak=reader->peakahead();
+  if (tpeak.token_type==TOKEN_OPENBRACK) {
+    skiptoken();
+    AElementexpr *index=parseaelementexpr(false);
+    return checkdot(new AElementexpr(incoming, new Field(copystr(tfield.str)),index));
+  } else {
+    return checkdot(new AElementexpr(incoming, new Field(copystr(tfield.str))));
+  }
+}
+
+AElementexpr * AParser::parseaelementexpr(bool isquant) {
+  AElementexpr *oldee=NULL;
+  int joinop=-1;
+  while(true) {
+  Token t=reader->peakahead();
+  switch(t.token_type) {
+  case TOKEN_LITERAL:
+    {
+      if ((joinop==-1)&&(oldee!=NULL))
+       return oldee;
+      skiptoken();
+      needtoken(TOKEN_OPENPAREN);
+      Token literal=reader->readnext();
+      needtoken(TOKEN_CLOSEPAREN);
+      if (oldee==NULL)
+       oldee=new AElementexpr(new Literal(copystr(literal.str)));
+      else {
+       if (joinop!=-1) {
+         oldee=new AElementexpr(oldee,new AElementexpr(new Literal(copystr(literal.str))),joinop);
+         joinop=-1;
+       } else error();
+      }
+      break;
+    }
+  case TOKEN_CAST:
+    {
+      if ((joinop==-1)&&(oldee!=NULL))
+       return oldee;
+      skiptoken();
+      needtoken(TOKEN_OPENPAREN);
+      Token casttype=reader->readnext();
+      needtoken(TOKEN_COMMA);
+      AElementexpr *ee=parseaelementexpr(false);
+      AElementexpr *tee=checkdot(new AElementexpr(copystr(casttype.str),ee));
+      if (oldee==NULL)
+       oldee=tee;
+      else {
+       if (joinop!=-1) {
+         oldee=new AElementexpr(oldee,tee,joinop);
+         joinop=-1;
+       } else error();
+      }
+      break;
+    }
+   
+  case TOKEN_OPENPAREN:
+    {
+      if ((joinop==-1)&&(oldee!=NULL))
+       return oldee;
+      skiptoken();
+      AElementexpr *ee=checkdot(parseaelementexpr(false));
+      if (oldee==NULL)
+       oldee=ee;
+      else {
+       if (joinop!=-1) {
+         oldee=new AElementexpr(oldee,ee,joinop);
+         joinop=-1;
+       } else error();
+      }
+      break;
+    }
+  case TOKEN_CLOSEBRACK:
+    if (isquant)
+      return oldee;
+    skiptoken();
+    return oldee;
+  case TOKEN_CLOSEPAREN:
+    skiptoken();
+    return oldee;
+  case TOKEN_SUB:
+    skiptoken();
+    if ((oldee!=NULL)&&(joinop==-1))
+      joinop=AELEMENTEXPR_SUB;
+    else
+      error();
+    break;
+  case TOKEN_ADD:
+    skiptoken();
+    if ((oldee!=NULL)&&(joinop==-1))
+      joinop=AELEMENTEXPR_ADD;
+    else
+      error();
+    break;
+  case TOKEN_MULT:
+    skiptoken();
+    if ((oldee!=NULL)&&(joinop==-1))
+      joinop=AELEMENTEXPR_MULT;
+    else
+      error();
+    break;
+  case TOKEN_DIV:
+    skiptoken();
+    if ((oldee!=NULL)&&(joinop==-1))
+      joinop=AELEMENTEXPR_DIV;
+    else
+      error();
+    break;
+  case TOKEN_NULL:
+    if ((joinop==-1)&&(oldee!=NULL))
+      return oldee;
+    skiptoken();
+    if (oldee==NULL)
+      oldee=checkdot(new AElementexpr());
+    else {
+      if (joinop!=-1) {
+       oldee=new AElementexpr(oldee,checkdot(new AElementexpr()),joinop);
+       joinop=-1;
+      } else error();
+    }
+    break;
+  default:
+    if ((joinop==-1)&&(oldee!=NULL))
+      return oldee;
+    skiptoken();
+    if (oldee==NULL)
+      oldee=checkdot(new AElementexpr(new Label(copystr(t.str))));
+    else {
+      if (joinop!=-1) {
+       oldee=new AElementexpr(oldee,checkdot(new AElementexpr(new Label(copystr(t.str)))),joinop);
+       joinop=-1;
+      } else error();
+    }
+  }
+  }
+}
+
+Statementb * AParser::parsestatementb() {
+  Token t=reader->peakahead();
+  if (t.token_type==TOKEN_LT) {
+    skiptoken();
+    Token tpeak=reader->peakahead();
+    TypeEle *typel=NULL,*typer=NULL;
+    if (tpeak.token_type==TOKEN_OPENPAREN) {
+      skiptoken();
+      typel=parsetypeele();
+      needtoken(TOKEN_CLOSEPAREN);
+    }
+    AElementexpr *ael=parseaelementexpr(false);
+    needtoken(TOKEN_COMMA);
+    if (tpeak.token_type==TOKEN_OPENPAREN) {
+      skiptoken();
+      typer=parsetypeele();
+      needtoken(TOKEN_CLOSEPAREN);
+    }
+    AElementexpr *aer=parseaelementexpr(false);
+    needtoken(TOKEN_GT);
+    needtoken(TOKEN_IN);
+    Token setlabel=reader->readnext();
+    return new Statementb(typel,ael,typer,aer,new Setlabel(copystr(setlabel.str)));
+  }
+
+  TypeEle *type=NULL;
+  if (t.token_type==TOKEN_OPENPAREN) {
+    skiptoken();
+    type=parsetypeele();
+    needtoken(TOKEN_CLOSEPAREN);
+  }
+  AElementexpr *ae=parseaelementexpr(false);
+  needtoken(TOKEN_IN);
+  Token setlabel=reader->readnext();
+  return new Statementb(type,ae,new Setlabel(copystr(setlabel.str)));
+}
+
+void AParser::error() {
+  printf("ERROR\n");
+  reader->error();
+  exit(-1);
+}
+
+void AParser::skiptoken() {
+  reader->readnext();
+}
+
+void AParser::needtoken(int token) {
+  Token t=reader->readnext();
+  if (!(t.token_type==token)) {
+    printf("Needed token: ");
+    tokenname(token);
+    printf("\n Got token: %s ",t.str);
+    tokenname(t.token_type);
+    error();
+  }
+}
+
+Rule * AParser::parsequantifiers() {
+  bool bool_continue=true;
+  List * list=new List();
+  do {
+    Token token2=reader->readnext();
+    switch(token2.token_type) {
+    case TOKEN_CLOSEBRACK:
+      bool_continue=false;
+      break;
+    case TOKEN_FORALL:
+      list->addobject(parsequantifier());
+      break;
+    case TOKEN_FOR:
+      list->addobject(parsequantifierfor());
+    case TOKEN_COMMA:
+      break;
+    default:
+      error();
+    }
+  } while(bool_continue);
+  AQuantifier** qarray=new AQuantifier* [list->size()];
+  list->toArray((void **)qarray);
+  Rule *c=new Rule(qarray,list->size());
+  delete(list);
+  return c;
+}
+
+AQuantifier * AParser::parsequantifier() {
+  Token token=reader->peakahead();
+  if (token.token_type==TOKEN_LT) {
+    skiptoken();
+    Type *tl=NULL, *tr=NULL;
+    if (token.token_type==TOKEN_OPENPAREN) {
+      skiptoken();
+      tl=parsetype();
+      needtoken(TOKEN_CLOSEPAREN);
+    }
+    Token labell=reader->readnext();
+    needtoken(TOKEN_COMMA);
+
+    if (token.token_type==TOKEN_OPENPAREN) {
+      skiptoken();
+      tr=parsetype();
+      needtoken(TOKEN_CLOSEPAREN);
+    }
+    Token labelr=reader->readnext();
+
+    needtoken(TOKEN_GT);
+    needtoken(TOKEN_IN);
+    return new AQuantifier(new Label(copystr(labell.str)),tl,new Label(copystr(labelr.str)),tr,parseset());
+  } else {
+    Type *t=NULL;
+    if (token.token_type==TOKEN_OPENPAREN) {
+      skiptoken();
+      t=parsetype();
+      needtoken(TOKEN_CLOSEPAREN);
+    }
+    Token label=reader->readnext();
+    needtoken(TOKEN_IN);
+    return new AQuantifier(new Label(copystr(label.str)),t,parseset());
+  }
+}
+
+AQuantifier * AParser::parsequantifierfor() {
+  Token label=reader->readnext();
+  needtoken(TOKEN_EQUALS);
+  AElementexpr *lower=parseaelementexpr(false);
+  needtoken(TOKEN_TO);
+  AElementexpr *upper=parseaelementexpr(true);
+  return new AQuantifier(new Label(copystr(label.str)),lower,upper);
+}
+
+Set * AParser::parseset() {
+  Token label=reader->readnext();
+  if (label.token_type==TOKEN_OPENBRACE) {
+    bool bool_continue=true;
+    List * list=new List();
+    do {
+      Token token2=reader->readnext();
+      switch(token2.token_type) {
+      case TOKEN_CLOSEBRACE:
+       bool_continue=false;
+       break;
+      case TOKEN_COMMA:
+       break;
+      default:
+       list->addobject(new Literal(copystr(token2.str)));
+       break;
+      }
+    } while(bool_continue);
+    int size=list->size();
+    Literal** qarray=new Literal* [size];
+    list->toArray((void **)qarray);
+    delete(list);
+    return new Set(qarray,size);
+  } else
+    return new Set(new Setlabel(copystr(label.str)));
+}
+