
#include <stddef.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <iostream.h>
#include "Boolean.h"

#include "scanner.h"

struct tokbuf tokenbuffer;

Boolean tokenavailable;

static char linebuffer[81];
static int currentchar, linelength;

static void dumptoken(char t)
{	cout<<"<token ";
	switch (t) 
	{	case number:
			cout<<"num >\n";
			break;
		case letter:
			cout<<"let >\n";
			break;
		case sumfunc:
		case prodfunc:
			cout<<"fun >\n";
			break;
		case plusop:
			cout<<"+ >\n";
			break;
		case minusop:
			cout<<"- >\n";
			break;
		case timesop:
			cout<<"* >\n";
			break;
		case divideop:
			cout<<"/ >\n";
			break;
		case assignop:
			cout<<"= >\n";
			break;
		case rangeop:
			cout<<".. >\n";
			break;
		case lparen:
			cout<<"( >\n";
			break;
		case rparen:
			cout<<") >\n";
			break;
		case period:
			cout<<". >\n";
			break;	
		case semicolon:
			cout<<"; >\n";
			break;
	}
}

static void scanerror()
{	 cout<<"Scan error.\n";
}

void parseError(String s)
{	 cout<<"Parse error." << s << endl;
}

static void gettoken();

void match(char t)
{	if (!tokenavailable) gettoken();
	if (tokenbuffer.currenttoken == t) toss();
	else 
	{	parseError(String(" Match- trying ") + String(t));
	}
}

static void readline()
{	linelength = 0;
	//linelength = 
	cin.getline(linebuffer, sizeof(linebuffer));
//	while(linebuffer[linelength++] != '\n'); //nothing
	linelength = cin.gcount() - 1;
//	cout<<linelength;
//	cout>>linebuffer<<endl;
//	do 
//	{	cin >> ch; 
//		cout << ch;
//		ch = getchar();
//		putchar(ch);
//		linebuffer[linelength++] = ch;
//	} while (ch != '\n');
	linebuffer[linelength] = ' ';
//  putchar('\n'); 
//	cout << endl;
	currentchar = 0;
}

static char inspect()
{	if (currentchar > linelength)	readline();
	return linebuffer[currentchar];
}

static void advance()
{	currentchar++;
}

#define tab   '\t'
#define newline '\n'
#define space ' '

void toss()
{	tokenavailable = false;
}

static checkFunctions(const char* s)
{	if(strcmp(s, "sum")==0) return sumfunc;
	if(strcmp(s, "prod")==0) return prodfunc;
	return letter;
}

static void gettoken()
{	char ch, TEMP, TEMP1;
	char spelling[40];
	char * newSpell;
	int loc;

	while ((TEMP = inspect(), TEMP == tab || TEMP == space || TEMP == newline))
		advance();
	TEMP = inspect();	
	switch (TEMP) 
	{	case '=':
			tokenbuffer.currenttoken = assignop;
			advance();
			break;	
		case '+':
			tokenbuffer.currenttoken = plusop;
			advance();
			break;
		case '-':
			tokenbuffer.currenttoken = minusop;
			advance();
			break;
		case '*':
			tokenbuffer.currenttoken = timesop;
			advance();
			break;
		case '/':
			tokenbuffer.currenttoken = divideop;
			advance();
			break;
		case '(':
			tokenbuffer.currenttoken = lparen;
			advance();
			break;
		case ')':
			tokenbuffer.currenttoken = rparen;
			advance();
			break;
		case ';':
			tokenbuffer.currenttoken = semicolon;
			advance();
			break;
		case '.':
			tokenbuffer.currenttoken = period;
			advance();
			if(inspect()== '.')
			{	tokenbuffer.currenttoken = rangeop;
				advance();
			}
			break;
		default:
			if (isdigit(TEMP)) 
			{	tokenbuffer.currenttoken = number;
				tokenbuffer.value = inspect() - '0';
				advance();
				while ((TEMP1 = inspect(), isdigit(TEMP1))) 
				{	tokenbuffer.value = tokenbuffer.value * 10 + inspect() - '0';
					advance();
				}
			} 
			else if (isalpha(TEMP)) 
			{	ch = inspect();
				if (isupper(ch))
					ch = tolower(ch);
				spelling[0] =  ch; loc = 1;
				advance();
				while(isalpha(inspect()) || isdigit(inspect() ))
				{	spelling[loc++] = inspect();
					advance();
				}
				spelling[loc] = '\0';
				newSpell = new char(strlen(spelling) +1);
				strcpy(newSpell, spelling);
				tokenbuffer.which = newSpell;
				tokenbuffer.currenttoken = checkFunctions(newSpell);     
			}
			break;
	}
	tokenavailable = true;
}

char nextToken()
{	if (!tokenavailable) gettoken();
	return (tokenbuffer.currenttoken);
}

void initscanner()
{	tokenavailable = false;
	currentchar = 0;
	linelength = -1;
}

/* End. */

