예제 #1
0
파일: syntax.c 프로젝트: k0gaMSX/mcm
int initsyn()
  {
    syms1=newsymbol("");
    syms2=newsymbol("");
    syms3=newsymbol("");
    tempo=searchsym("tempo");
    hz=searchsym("Hz");
  }
예제 #2
0
// Function to get the value of a given symbol in the symbol table.
Value getsym_id (char *name){
  symrec *sym;
  // Search for the symbol in the symbol table.
  sym = searchsym(name);
  // If the symbol doesn't exist ...
  if(sym == NULL){
    // ... Throw an error and exit.
    printf("Variable %s not declared before \n", name);
    exit(1);
  }

  // Check if the symbol is a function.
  if(sym->type == sym_func){
    printf("Symbol %s is a function, not a variable\n", name);
    exit(1);
  }

  // Return the value of the symbol.
  return sym->value;
}
예제 #3
0
// Function to add a symbol to the symbol table of a given name.
symrec *putsym(char *name, symEnum type, struct nodeTypeTag *func_tree){
  // First, search if the symbol exists.
  symrec *sym = searchsym(name);

  // if the symbol already exists ...
  if(sym != NULL){
    // ... Don't do anything, and throw an error.
      printf("Symbol already exists!\n");
      return NULL;
  }

  // Create a place in the memory for the symbol.
  sym = (symrec *)malloc(sizeof(symrec));
  if(sym == NULL){
    printf("Not enough memory!\n");
    exit (-1);
  }

  // Create enough place for the name of the symbol.
  sym->name = (char *)malloc(sizeof(strlen(name)+1));
  if(sym->name == NULL){
    printf("Not enough memory for name!\n");
    exit (-1);
  }

  // Set the name of the symbol.
  sym->name = name;
  // Set the type of the symbol (Id, function).
  sym->type = type;
  // If the symbol is a function, add it's body to it.
  if (type == sym_func){
      sym->func_tree = func_tree;
  }
  // Add the symbol to the start of the symbol table.
  sym->next = sym_node;
  // Point at the symbol, making it the first symbol in the table.
  sym_node = sym;
  return sym;
}
예제 #4
0
// Function to change the value of a given symbol in the symbol table to a given Value and returns the new value.
Value symchange_id(char *name, Value newValue){
  symrec *sym;
  // Search for the symbol in the symbol table.
  sym = searchsym(name);
  // If the symbol doesn't exist ...
  if(sym == NULL){
    // ... throw an error and exist.
    printf("No variable found with name %s\n",name);
   exit (-1);
  }

  // Check if the symbol is a function.
  if(sym->type == sym_func){
    printf("Symbol %s is a function, not a variable\n", name);
    exit(1);
  }

  // Change the value of the found symbol.
  sym->value = newValue;
  // Return the value of the symbol.
  return sym->value;
}
예제 #5
0
파일: syntax.c 프로젝트: k0gaMSX/mcm
int syntaxan (int token,symbol * sym)
{
  static unsigned char num_channel;
  static unsigned char channels[12]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  static symbol ptr;

  switch (status)
    {
    case STATUS_INIT:     /* Initial status */
      recst = STATUS_INIT;    /*Save actual state for error handling  */
      switch (token)
        {
        case VAR:            /* Begin variable declaration */
          status = STATUS_BEGIN_VAR_DECL;
          return 0;

        case CHANNEL:        /* Begin channel declaration */
          status = STATUS_BEGIN_CHN_DECL;
          return 0;

        case IDEN:            /* Begin assign statement */
          status = STATUS_BEGIN_GLOBAL_ASGN; /* TODO: Join to local assign */
          if ((*sym = searchsym(lexcad)) == NULL)
            rerror(ESYNTAX, EIDEN_NAME, 0);
          return 0;

        case LN:              /* Empty sentence  */
          return 1;

        default:
          rerror(ESYNTAX, E_INI, 0);
        }

      /* Variable declaration states  */

    case STATUS_BEGIN_VAR_DECL: /* VAR ; variable declaration */
      switch (token)
        {
        case IDEN:            /* Name of the variable */
          status = STATUS_NAME_VAR_DECL;
          *sym = newsymbol(lexcad);
          return 0;

        default:
          rerror(ESYNTAX, E_VAR_DECL, 0);
        }

    case STATUS_NAME_VAR_DECL: /* VAR IDEN ; variable declaration */
      switch (token)
        {
        case LN:             /* end of declaration */
          status = STATUS_INIT;
          insvar(*sym);
          return 1;

        case COMA:            /* multiple declaration */
          status = STATUS_BEGIN_VAR_DECL;
          insvar(*sym);
          return 0;

        default:
          rerror(ESYNTAX, E_VAR_DECL, 0);
        }

      /* Channel declaration states */

    case STATUS_BEGIN_CHN_DECL: /* CHANNEL ; channel declaration */
      switch (token)
        {
        case NUMBER:         /* Number of the channel */
          status = STATUS_END_OF_CHANNEL;
          num_channel = atoi(lexcad) - 1;

          if(num_channel >= 12)
            rerror(ESYNTAX, E_BAD_CH, 0);
          else
            {
              ssymval(syms1, num_channel);
              *sym = syms1;
            }

          if(channels[num_channel])
            rerror(ESYNTAX, E_DECL_CH, 0);

          channels[num_channel]=1;
          return 0;

        case IDEN:           /* Variable with the name of the channel */
          status = STATUS_END_OF_CHANNEL;
          if ((*sym = searchsym(lexcad)) == NULL)
            rerror(ESYNTAX, EIDEN_NAME, 0);
          else if ((num_channel = gsymval(*sym)) >= 12)
            rerror(ESYNTAX, E_BAD_CH, 0);

          if (channels[num_channel])
            rerror(ESYNTAX, E_DECL_CH, 0);

          channels[num_channel] = 1;
          return 0;

        default: rerror(ESYNTAX, E_CHANNEL, 0);
        }

      /* end of channel declaration */
    case STATUS_END_OF_CHANNEL: /* CHANNEL IDEN | NUMBER ; end of channl dcl*/
      switch (token)
        {
        case LN:             /* finish channel dcl */
          status = STATUS_BEGIN_CHN_BODY;
          inscode2(CHANNEL, gsymval(*sym));
          return 1;

        default:
          rerror(ESYNTAX, E_CHANNEL, 0);
        }

      /* Begin channel body */
    case STATUS_BEGIN_CHN_BODY:      /* CHANNEL IDEN | NUMBER LN ; chl body*/
      recst = STATUS_BEGIN_CHN_BODY;   /*Save state for error handling*/
      switch (token)
        {
        case LN:
          return 1;

        case ENDC:           /* end of channel statement */
          status = STATUS_BEGIN_ENDC;
          initsym(syms1, token, token);
          *sym = syms1;
          return 0;

        case PLAY:
          status = 11;          /* play statement */
          initexpr();
          initsym(syms1, token, token);
          *sym = syms1;
          return 0;

        case SIL:               /* silence statement  */
        case DECOC:             /* dec octave statement */
        case INCOC:             /* inc octave statement */
        case ENDL:              /* end of loop statement */
        case DECV:              /* dec volume */
        case INCV:              /* inc volume */
          status = STATUS_END_OF_1CMD;
          initsym(syms1, token, token);
          *sym = syms1;
          return 0;

        case OCT:               /* octave statement */
        case VOL:               /* volume statement */
        case BAT:               /* battery statement */
        case INST:              /* instrument statement */
        case LOOP:              /* loop statement */
        case AMPL:
        case VIB:               /* vibrato statement */
        case TIMES:             /* time short format statement */
        case TIMEL:             /* time long format statement */
        case DIVSUS:
        case BATL:              /* battery long format statement */
        case INSTL:             /* instrument long format statement */
        case FREC:              /* set frequency statement */
          status = STATUS_BEGIN_EXP_2CMD;
          initexpr();
          initsym(syms1, token, token);
          *sym = syms1;
          return 0;

        case TIMEP:
          status = 39;
          initexpr();
          initsym(syms1, token, token);
          initsym(syms2, NUMBER, 0);
          ssymsig(syms2, syms1);
          *sym = syms2;
          return 0;

        case REGFM:             /* write to fm register statement */
          status = 8;
          initexpr();
          initsym(syms1, token, token);
          *sym = syms1;
          return 0;

        case PAR:               /* parameter statement */
          status = 9;
          initsym(syms1, token, token);
          *sym = syms1;
          return 0;

        case IDEN:              /* Begin a assign statement */
          status = 10;
          if ((*sym = searchsym(lexcad)) == NULL)
            rerror(ESYNTAX, EIDEN_NAME, 0);

          return 0;

        default:
          rerror(ESYNTAX, E_UNK_COMM, 0);
        }

      /* End of 1 word statement */
    case STATUS_END_OF_1CMD:
      switch (token)
        {
        case LN:
          status = STATUS_BEGIN_CHN_BODY;
          inscodeI(*sym, NULL, num_channel);
          return 1;

        default:
          rerror(ESYNTAX, E_BAD_COMM, 0);
        }

    case 8:
      switch (token)
        {
        case NUMBER:
          status = 21;
          initsym(syms3, NUMBER, 0);
          ssymsig(syms3,*sym);
          *sym = syms3;
          pushexp(NUMBER, atoi(lexcad));
          return 0;

        case IDEN:
          status = 21;
          if((ptr = searchsym(lexcad)) == NULL)
            rerror(ESYNTAX, EIDEN_NAME, 0);

          initsym(syms3, NUMBER, 0);
          ssymsig(syms3,*sym);
          *sym = syms3;
          pushexp(NUMBER, gsymval(ptr));
          return 0;

        case PARI:
          status = 22;
          ssymsig(syms3,*sym);
          *sym = syms3;
          pushexp(token, 0);
          return 0;

        default:
          rerror(ESYNTAX, E_EXP, 0);
        }

    case 9:
      switch (token)
        {
        case ENVLOFF:
        case ENVLON:
        case SUSON:
        case HFNUM:
        case LFNUM:
        case NOISE:
        case TONE:
          status = STATUS_END_OF_1CMD;
          initsym(syms2, token, token);
          ssymsig(syms2,*sym);
          *sym = syms2;
          return 0;

        case DECO:
          status = STATUS_BEGIN_EXP_2CMD;
          initexpr();
          initsym(syms3, token, token);
          ssymsig(syms3,*sym);
          *sym = syms3;
          return 0;

        case TAMP:
          status = STATUS_BEGIN_EXP_2CMD;
          initexpr();
          initsym(syms3, token, token);
          ssymsig(syms3,*sym);
          *sym = syms3;
          return 0;

        case RITMON:
          status = STATUS_END_OF_1CMD;
          initsym(syms2, token, token);
          ssymsig(syms2,*sym);
          *sym = syms2;
          return 0;

        case MELON:
          status = STATUS_END_OF_1CMD;
          initsym(syms2, token, token);
          ssymsig(syms2,*sym);
          *sym = syms2;
          return 0;

        default:
          rerror(ESYNTAX, E_PAR, 0);
        }
    case 10:
      switch (token)
        {
        case EQ:
          status = STATUS_BEGIN_EXP_2CMD;
          initexpr();
          initsym(syms3, EQ, EQ);
          ssymsig(syms3, *sym);
          *sym = syms3;
          return 0;

        default:
          rerror(ESYNTAX, E_ASIG, 0);
        }

    case 11:
      switch(token)
        {
        case NUMBER:
          status = STATUS_PLAY_EXPRESION;
          initsym(syms2, NUMBER, 0);
          ssymsig(syms2,*sym);
          *sym = syms2;
          pushexp(NUMBER, atoi(lexcad));
          return 0;

        case IDEN:
          status = STATUS_PLAY_EXPRESION;
          if((ptr = searchsym(lexcad)) == NULL)
            rerror(ESYNTAX, EIDEN_NAME, 0);

          initsym(syms2, NUMBER, 0);
          ssymsig(syms2,*sym);
          *sym = syms2;
          pushexp(NUMBER, gsymval(ptr));
          return 0;

        case PARI:
          status = STATUS_PLAY_EXPRESION;
          ssymsig(syms2,*sym);
          *sym = syms2;
          pushexp(token, 0);
          return 0;

        default:
          rerror(ESYNTAX, E_EXP, 0);
        }

      /* Begin end of channel statement */
    case STATUS_BEGIN_ENDC:   /* ENDC ; endc command */
      switch(token)
        {
        case LN:
          status = 13;
          inscode(gsymval(*sym));
          execute();
          return 1;

        default:
          rerror(ESYNTAX, E_BAD_COMM, 0);
        }


    case 13:
      recst = 13;

      switch(token)
        {
        case WRITE:
          status = 38;
          return 0;

        case CHANNEL:
          status = STATUS_BEGIN_CHN_DECL;
          return 0;

        case LN:
          return 1;

        default:
          rerror(ESYNTAX, E_INI, 0);
        }



    case STATUS_BEGIN_GLOBAL_ASGN:
      switch(token)
        {
        case EQ:
          status = 15;
          initexpr();
          return 0;

        default: rerror(ESYNTAX, E_ASIG, 0);
        }

    case 15:
      switch(token)
        {
        case NUMBER:
          status = 26;
          {pushexp(NUMBER, atoi(lexcad));};
          return 0;
        case IDEN:
          status = 26;
          (ptr = searchsym(lexcad))?pushexp(NUMBER, gsymval(ptr)):rerror(ESYNTAX, EIDEN_NAME, 0);
          return 0;
        case PARI:
          status = 27;
          pushexp(token, 0);
          return 0;
        default: rerror(ESYNTAX, E_EXP, 0);
        }


      /*******************************************************************/
    case STATUS_BEGIN_EXP_2CMD:
      switch (token)
        {
        case PARI:
          status = STATUS_EXP2_OPERAND;
          ssymsig(syms2,*sym);
          *sym = syms2;
          pushexp(token, 0);
          return 0;

        case NUMBER:
          status = STATUS_EXP2_OPERAND;
          initsym(syms2, NUMBER, 0);
          ssymsig(syms2,*sym);
          *sym = syms2;
          pushexp(NUMBER, atoi(lexcad));
          return 0;

        case IDEN:
          status = STATUS_EXP2_OPERAND;
          if(!(ptr = searchsym(lexcad)))
            rerror(ESYNTAX, EIDEN_NAME, 0);

          initsym(syms2, NUMBER, 0);
          ssymsig(syms2,*sym);
          *sym = syms2;
          pushexp(NUMBER, gsymval(ptr));
          return 0;

        default:
          rerror(ESYNTAX, E_EXP, 0);

        }


    case STATUS_EXP2_OPERAND:
      switch(token)
        {
        case NUMBER:
          status = STATUS_EXP2_OPERAND;
          pushexp(NUMBER, atoi(lexcad));
          return 0;

        case IDEN:
          status = STATUS_EXP2_OPERAND;
          if ((ptr = searchsym(lexcad)) == NULL)
            rerror(ESYNTAX, EIDEN_NAME, 0);

          pushexp(NUMBER, gsymval(ptr));
          return 0;

        case ADD:
        case SUB:
        case MUL:
        case DIV:
        case PARD:
        case PARI:              /* left parenthesis  */
          status = STATUS_EXP2_OPERAND;
          pushexp(token, 0);
          return 0;

        case LN:
          status = recst;
          pushexp(token, 0);
          ssymval(*sym, evalexpr());
          inscodeI(*sym, NULL, num_channel);
          return 1;

        default:
          rerror(ESYNTAX, E_EXP, 0);
        }


      /***********************************************/

      /* initial assign expression*/
    case 26:
      switch(token)
        {
        case ADD:
          status = 15;
          pushexp(token, 0);
          return 0;
        case SUB:
          status = 15;
          pushexp(token, 0);
          return 0;
        case MUL:
          status = 15;
          pushexp(token, 0);
          return 0;
        case DIV:
          status = 15;
          pushexp(token, 0);
          return 0;
        case LN:
          status = STATUS_INIT;{pushexp(token, 0);ssymval(*sym, evalexpr());}  return 1;
        default: rerror(ESYNTAX, E_EXP, 0);
        }
    case 27:
      switch(token)
        {
        case NUMBER:
          status = 28;{pushexp(NUMBER, atoi(lexcad));}return 0;
        case IDEN:
          status = 28;{symbol ptr;(ptr = searchsym(lexcad))?pushexp(NUMBER, gsymval(ptr)):rerror(ESYNTAX, EIDEN_NAME, 0);}return 0;
        case PARI:
          status = 27;
          pushexp(token, 0);
          return 0;
        default: rerror(ESYNTAX, E_EXP, 0);
        }

    case 28:
      switch(token)
        {
        case PARD:
          status = 28;
          pushexp(token, 0);
          return 0;
        case ADD:
          status = 27;
          pushexp(token, 0);
          return 0;
        case SUB:
          status = 27;
          pushexp(token, 0);
          return 0;
        case MUL:
          status = 27;
          pushexp(token, 0);
          return 0;
        case DIV:
          status = 27;
          pushexp(token, 0);
          return 0;
        case LN:
          status = STATUS_INIT;{pushexp(token, 0);ssymval(*sym, evalexpr());}return 1;
        default: rerror(ESYNTAX, E_EXP, 0);
        }


    case 30:


      /*Expresion de play*/

    case STATUS_PLAY_EXPRESION:
            switch(token) {
            case ADD:
            case SUB:
            case MUL:
            case DIV:
                    status = 32;
                    pushexp(token, 0);
                    return 0;

            case SOS:
                    status = STATUS_PLAY_SOST;
                    return 0;

            case BEMOL:
                    status = STATUS_PLAY_BEMOL;
                    return 0;

            case COMA:
            case LN:
                    pushexp(LN, 0);
                    ssymval(*sym, evalexpr());
                    inscodeI(*sym, NULL, num_channel);
                    if (token == COMA) {
                            status = 32;
                            initexpr();
                            return 0;
                    } else {
                            status = STATUS_BEGIN_CHN_BODY;
                            return 1;
                    }


            default:
                    rerror(ESYNTAX, E_EXP, 0);
            }


    case 32:
      switch(token)
        {
        case NUMBER:
          status = 33;{pushexp(NUMBER, atoi(lexcad));}return 0;
        case IDEN:
          status = 33;{symbol ptr;(ptr = searchsym(lexcad))?pushexp(NUMBER, gsymval(ptr)):rerror(ESYNTAX, EIDEN_NAME, 0);}return 0;
        case PARI:
          status = 32;
          pushexp(token, 0);
          return 0;
        default: rerror(ESYNTAX, E_EXP, 0);
        }

    case 33:
      switch(token)
        {
        case PARD:
          status = 33;
          pushexp(token, 0);
          return 0;
        case ADD:
          status = 34;
          pushexp(token, 0);
          return 0;
        case SUB:
          status = 34;
          pushexp(token, 0);
          return 0;
        case MUL:
          status = 34;
          pushexp(token, 0);
          return 0;
        case DIV:
          status = 34;
          pushexp(token, 0);
          return 0;
        case SOS:
          status = STATUS_PLAY_SOST;{pushexp(token, 0);ssymval(*sym, evalexpr());}return 0;
        case BEMOL:
          status = STATUS_PLAY_BEMOL;{pushexp(token, 0);ssymval(*sym, evalexpr());}return 0;
        case COMA:
          status = 32;{pushexp(LN, 0);ssymval(*sym, evalexpr());inscodeI(*sym, NULL, num_channel);initexpr();} return 0;
        case LN:
          status = STATUS_BEGIN_CHN_BODY;{pushexp(token, 0);ssymval(*sym, evalexpr());inscodeI(*sym, NULL, num_channel);}return 1;
        default: rerror(ESYNTAX, E_EXP, 0);
        }
    case 34:
      switch(token)
        {
        case NUMBER:
          status = STATUS_PLAY_EXPRESION;{pushexp(NUMBER, atoi(lexcad));}return 0;
        case IDEN:
          status = STATUS_PLAY_EXPRESION;{symbol ptr;(ptr = searchsym(lexcad))?pushexp(NUMBER, gsymval(ptr)):rerror(ESYNTAX, EIDEN_NAME, 0);}return 0;
        case PARI:
          status = 32;
          pushexp(token, 0);
          return 0;
        default: rerror(ESYNTAX, E_EXP, 0);
        }

    case STATUS_PLAY_BEMOL:
      switch(token) {
      case BEMOL:
              pushexp(SUB, 0);
              pushexp(NUMBER, 3);
              return 0;

      case COMA:
      case LN:
              pushexp(LN, 0);
              ssymval(*sym, evalexpr() - 3);
              inscodeI(*sym, NULL, num_channel);
              if (token == LN) {
                      status = STATUS_BEGIN_CHN_BODY;
                      return 1;
              } else {
                      status = 32;
                      initexpr();
                      return 0;
              }

      default: rerror(ESYNTAX, E_BEMOL, 0);
      }

    case STATUS_PLAY_SOST:
      switch(token) {
      case SOS:
              pushexp(ADD, 0);
              pushexp(NUMBER, 3);
              return 0;

      case COMA:
      case LN:
              pushexp(LN, 0);
              ssymval(*sym, evalexpr() + 3);
              inscodeI(*sym, NULL, num_channel);
              if (token == LN) {
                      status = STATUS_BEGIN_CHN_BODY;
                      return 1;
              } else {
                      status = 32;
                      initexpr();
                      return 0;
              }


      default: rerror(ESYNTAX, E_SOS, 0);
      }


    case 38:
      switch(token)
        {
        case LN:
          status = 37;{errorg?rerror(EERROR, 0, 0):writesong();}return 2;            /*Fin de entrada*/
        default: rerror(ESYNTAX, E_BAD_COMM, 0);
        }


    case 39:
      switch (token)
        {
        case NUMBER:
          status = 40;{pushexp(NUMBER, atoi(lexcad));}return 0;
        case IDEN:
          status = 40;{symbol ptr;(ptr = searchsym(lexcad))?pushexp(NUMBER, gsymval(ptr)):rerror(ESYNTAX, EIDEN_NAME, 0);}return 0;
        case PARI:
          status = 41;
          pushexp(token, 0);
          return 0;
        default: rerror(ESYNTAX, E_EXP, 0);
        }


    case 40:
      switch(token)
        {
        case ADD:
          status = 39;
          pushexp(token, 0);
          return 0;
        case SUB:
          status = 39;
          pushexp(token, 0);
          return 0;
        case MUL:
          status = 39;
          pushexp(token, 0);
          return 0;
        case DIV:
          status = 39;
          pushexp(token, 0);
          return 0;
        case POINT:
          status = 43;{pointp = point=32;};
          return 0;
        case LN:
          status = STATUS_BEGIN_CHN_BODY;
          {
            float time;

            pushexp(token, 0);
            time = evalexpr();
            time/=64.0;
            time*=(240.0*((float)(gsymval(hz))))/((float)(gsymval(tempo)));
            if((time-((float)((unsigned char)time))) > 0.5)
              time=((float)((unsigned char)time))+1.0;
            else
              time=(float)((unsigned char)time);

            ssymval(*sym,(unsigned char)time);
            inscodeI(*sym, NULL, num_channel);
          }return 1;


        default: rerror(ESYNTAX, E_EXP, 0);
        }

    case 41:
      switch(token)
        {
        case NUMBER:
          status = 42;{pushexp(NUMBER, atoi(lexcad));}return 0;
        case IDEN:
          status = 42;{symbol ptr;(ptr = searchsym(lexcad))?pushexp(NUMBER, gsymval(ptr)):rerror(ESYNTAX, EIDEN_NAME, 0);}return 0;
        case PARI:
          status = 41;
          pushexp(token, 0);
          return 0;
        default: rerror(ESYNTAX, E_EXP, 0);
        }

    case 42:
      switch(token)
        {
        case PARD:
          status = 42;
          pushexp(token, 0);
          return 0;
        case ADD:
        case SUB:
        case MUL:
        case DIV:
          status = 41;
          pushexp(token, 0);
          return 0;

        case POINT:
          status = 43;{pointp = point=32;} return 0;
        case LN:
          status = STATUS_BEGIN_CHN_BODY;
          {
            float time, timei;

            pushexp(token, 0);
            time = evalexpr();
            time/=64.0;
            time*=(240.0*((float)(gsymval(hz))))/((float)(gsymval(tempo)));
            time = fabs(time);

            timei = floor(time);
            if(time-timei)
              time = timei+1.0;
            else
              time = timei;

            ssymval(*sym,(unsigned char)time);
            inscodeI(*sym, NULL, num_channel);
          }return 1;
        default: rerror(ESYNTAX, E_EXP, 0);
        }
    case 43:
      switch(token)
        {
        case POINT:
          pointp >>= 1;
          point += pointp;
          return 0;

        case LN:
          status = STATUS_BEGIN_CHN_BODY;
          {
            float time, timei;

            pushexp(token, 0);
            time = evalexpr();
            time/=64;
            time*=(240.0*((float)(gsymval(hz))))/((float)(gsymval(tempo)));
            time = fabs(time);
            time+=time*(((float)point)/64.0);


            timei = floor(time);
            if(time-timei)
              time = timei+1.0;
            else
              time = timei;

            ssymval(*sym,(unsigned char)time);
            inscodeI(*sym, NULL, num_channel);
          }return 1;
        }
    default:
      rerror(ESYNTAX, E_POINT, 0);

    }
}
예제 #6
0
// Function to execute a node in the AST and returns the value of the executed node.
Value ex(nodeType *p){
  // If the node is empty, return an empty value (null).
  if (!p) return empty_value();

  // Depending on the type of the node, do different actions.
  switch(p->type){
    case typeCon: // If it was a constant.
      return p->con.val; // Return its value.
    case typeId: { // If it was an id (variable).
      Value v;
      v = getsym_id(p->id.name); // Get the value of the symbol in the symbol table.
      return v; // Return the value of hte symbol.
    }
    case typeFunc: { // If it was a function.
      // Value v;

      // v = getsym_id(p->id.name); // Get the value of the symbol in the symbol table.
      return ex(searchsym(p->func.name)->func_tree); // Return the value of hte symbol.
    }
    case typeOpr: // If it was an operation.
    // Check for the type of operation.
    switch(p->opr.oper){
      case WHILE: { // If it was a while loop.
        LOOPLABEL: { // Define a start label.
        Value v = ex(p->opr.op[0]); // Execute the expression of the loop.
        // Depending on the type of the variable ...
        switch(v.type){
          case conInt: // If the value is integer.
            // Check if it is true.
            if(v.ival){
              // Execute the statements in the body of the while loop.
              ex(p->opr.op[1]);
              // Return to start label.
              goto LOOPLABEL;
            }
            break;
          case conReal: // If the value is real (float).
            // Check if it is true.
            if(v.realval){
              // Execute the statements in the body of the while loop.
              ex(p->opr.op[1]);
              // Return to start label.
              goto LOOPLABEL;
            }
            break;
          default: // If it was a string then just ignore.
            break;
        }
      }
        return empty_value(); // Return an empty value (null).
      }
      case LOOP: { // If it was a loop.
        int end = ex(p->opr.op[0]).ival; //here we know it is for sure an integer.
        int i;
        for (i = 0; i < end; i++){
          ex(p->opr.op[1]); // Execute the body of the loop statement.
        }
        return empty_value(); // Return an empty value.
      }
      case IF:{ // If it was an if statement.
        Value v = ex(p->opr.op[0]); // Execute the expression in the if statement.
        // Execute the if statement depending on the type of the value.
        switch(v.type){
          case conInt:
            if (v.ival)
              ex(p->opr.op[1]);
            else if (p->opr.nops > 2)
              ex(p->opr.op[2]);
            break;
          case conReal:
            if (v.realval)
              ex(p->opr.op[1]);
            else if (p->opr.nops > 2)
              ex(p->opr.op[2]);
            break;
          default:
            break;
        }

        return empty_value();
      }
      case PRINT:{ // If it is a print statement.
        Value v = ex(p->opr.op[0]); // Take the value of the expression.
        // Format the output depending on the type of the value.
        switch (v.type){
          case conInt:
            printf("%d\n", v.ival);
            break;
          case conReal:
            printf("%f\n", v.realval);
            break;
          case conString:
            printf("%s\n", v.str);
            break;
        }
        return empty_value();
      }
      case READ_INT: { // If it was a read integer statement.
        //TODO: IMPLEMENT This later.
        // Value v = getsym(p->opr.op[0]->id.name);
        // Value tmp;
        // switch (v.type) {
        //   case conInt:{
        //     tmp.type = conInt;
        //     scanf("%d", &tmp.ival);
        //     symchange(p->opr.op[0]->id.name, tmp);
        //     return empty_value();
        //   }
        //   case conReal:{
        //     tmp.type = conReal;
        //     scanf("%f", &tmp.realval);
        //     symchange(p->opr.op[0]->id.name, tmp);
        //     return empty_value();
        //   }
        //   case conString:{
        //     tmp.type = conString;
        //     scanf("\n%s", tmp.str);
        //     symchange(p->opr.op[0]->id.name, tmp);
        //     return empty_value();
        //   }
        // }
        // Define a new integer value.
        Value v;
        v.type = conInt;
        // Prompt the user to enter an integer value.
        printf("> ");
        scanf("%d", &v.ival);
        // Change the value of the id (variable) to the newly read integer value.
        symchange_id(p->opr.op[0]->id.name, v);
        return empty_value();
      }
      case READ_REAL:{ // If it was a read real number (float) statement.
        // Define a new real number (float) value.
        Value v;
        v.type = conReal;
        // Prompt the user to enter a real number (float) value.
        printf("> ");
        scanf("%f", &v.realval);
        // Change the value of the id (variable) to the newly read real number (float) value.
        symchange_id(p->opr.op[0]->id.name, v);
        return empty_value();
      }
      case READ_STR:{ // If it was a read string statement.
        // Define a new string value.
        Value v;
        v.type = conString;
        // Prompt the user to enter a string value
        printf("> ");
        scanf("\n%s", str_buf);
        // Point at the string buffer.
        v.str = str_buf;
        // Change the value of the id (variable) to the newly read string value.
        symchange_id(p->opr.op[0]->id.name, v);
        return empty_value();
      }
      case ';': // If it was a semicolon.
        // Execute the operations.
        ex(p->opr.op[0]);
        return ex(p->opr.op[1]);
      case '=':{ // If it was an assignment statement.
        // Change the value of the variable to the right expression.
        return symchange_id(p->opr.op[0]->id.name, ex(p->opr.op[1]));
      }
      case UMINUS: { // If it was the unary minus (negative) operator.
        Value v = ex(p->opr.op[0]); // Get the value of the expression to be negated.
        // Negate the value depening on its type.
        switch (v.type) {
          case conInt:
            v.ival = -v.ival;
            break;
          case conReal:
            v.realval = -v.realval;
            break;
          default: // TODO: Reverse string when negated.
            return empty_value();
        }
        return v;
      }
      // The rest are arithmetic function. They all call the ex_arith function to get executed.
      case '+':
        return ex_arith('+',ex(p->opr.op[0]),ex(p->opr.op[1]));
      case '-':
        return ex_arith('-',ex(p->opr.op[0]),ex(p->opr.op[1]));
      case '*':
        return ex_arith('*',ex(p->opr.op[0]),ex(p->opr.op[1]));
      case '/':
        return ex_arith('/',ex(p->opr.op[0]),ex(p->opr.op[1]));
      case '^':
        return ex_arith('^',ex(p->opr.op[0]),ex(p->opr.op[1]));
      case MOD:
        return ex_arith(MOD ,ex(p->opr.op[0]),ex(p->opr.op[1]));
      case LT:
        return ex_arith(LT ,ex(p->opr.op[0]),ex(p->opr.op[1]));
      case GT:
        return ex_arith(GT ,ex(p->opr.op[0]),ex(p->opr.op[1]));
      case LTE:
        return ex_arith(LTE ,ex(p->opr.op[0]),ex(p->opr.op[1]));
      case GTE:
        return ex_arith(GTE ,ex(p->opr.op[0]),ex(p->opr.op[1]));
      case EQ:
        return ex_arith(EQ ,ex(p->opr.op[0]),ex(p->opr.op[1]));
      case NEQ:
        return ex_arith(NEQ ,ex(p->opr.op[0]),ex(p->opr.op[1]));
    }
  }
  return empty_value();
}