#include <stdio.h>
#include <assert.h>
#include "token_bytecodes.h"
#include "ast.h"
#include "y.tab.h"

YYSTYPE yylval;

int yylineno = 0;

struct {
  bytecode bc;
  int tok;
} table[] = {
#define xx(s) {LBC_##s,s}
#define xy(s) {LBC_##s,yy##s,}
xx(ID), 
xx(STRING),
xx(REAL),
xx(INTEGER),
xy(AND),
xx(ARRAY),
xx(BEGIN),
xx(BY),
xy(DIV),
xx(DO),
xx(ELSE),
xx(ELSIF),
xx(END),
xx(EXIT),
xx(FOR),
xx(IF),
xx(IS),
xx(LOOP),
xy(MOD),
xy(NOT),
xx(OF),
xy(OR),
xx(PROCEDURE),
xx(PROGRAM),
xx(READ),
xx(RECORD),
xx(RETURN),
xx(THEN),
xx(TO),
xx(TYPE),
xx(VAR),
xx(WHILE),
xx(WRITE),
xx(ASGN),
xx(LEQ),
xx(GEQ),
xx(NEQ),
xx(LBRANG),
xx(RBRANG),
{LBC_SEMICOLON,';'},
{LBC_COMMA,','},
{LBC_COLON,':'},
{LBC_LPAREN,'('},
{LBC_RPAREN,')'},
{LBC_LT,'<'},
{LBC_GT,'>'},
{LBC_EQ,'='},
{LBC_PLUS,'+'},
{LBC_MINUS,'-'},
{LBC_STAR,'*'},
{LBC_SLASH,'/'},
{LBC_LCURLY,'{'},
{LBC_RCURLY,'}'},
{LBC_LSQUARE,'['},
{LBC_RSQUARE,']'},
{LBC_DOT,'.'}
}; 


int bc_to_tok(unsigned int bc) {
  int i;
  for (i = 0; i < (sizeof(table)/sizeof(table[0])); i++)
    if (table[i].bc == bc)
      return table[i].tok;
  assert(0 /* no matching token for bytecode */); 
}

/* Returns bytecode or EOF. */
int load_code() {
  return getchar();
}  

/* Read low-order byte first. */
int load_int() {
  int i0,i1,i2,i3;
  i0 = getchar();
  assert(i0 != EOF);
  i1 = getchar();
  assert(i1 != EOF);
  i2 = getchar();
  assert(i2 != EOF);
  i3 = getchar();
  assert(i3 != EOF);
  return i0 | (i1 << 8) | (i2 << 16) | (i3 <<24);
}

/* Read string length first. */
char *load_string() {
  char buff[256];
  int i;
  int slen = getchar();
  assert(slen != EOF);
  for (i = 0; i < slen; i++) {
    int c = getchar();
    assert(c != EOF);
    buff[i] = c;
  };
  buff[slen] = '\0';
  return strsave(buff);
}

int yylex() {
  int c;
  while ((c = load_code()) != EOF) {
    if (c == LBC_LINE) 
      yylineno = load_int();
    else {
      int tok = bc_to_tok(c);
      switch (tok) {
      case ID:
      case REAL:
      case STRING:
	yylval.svalue = load_string();
	break;
      case INTEGER:
	yylval.ivalue = load_int();
	break;
      };
      return tok;
    }
  };
  return 0;
}



