/*
 * parse.c
 */
#define MAXCOL 50
#include "scanner.h"
#include "parse.h"
#include <stdio.h>
#include <string.h>

static Sp getsexpr (void);
static Sp tail (void);
static Sp newalfatom (Alftype );
static void wsexpr(Sp );
static void wtail(Sp );
static void writeout(char* );

static Token tok;
static long col;

Sp sexpr (void)
{
	gettoken(&tok);
	return(getsexpr());
}

static Sp getsexpr (void)
{
	if (tok.tokentype == alftok)
		return(newalfatom(tok.tokenval.alfval));
	if (tok.tokentype == numtok)
		return(newnumatom(tok.tokenval.numval));
	if (tok.tokentype == lprtok)
		return(tail());
	return(err(0));
}

static Sp tail (void)
{
	Sp s, t;
	gettoken(&tok);
	if (tok.tokentype == rprtok) return(NULL);
	s = getsexpr();
	t = tail();
	return(cons(s, t));
}

Sp cons (Sp s, Sp t)
{
	Sp r = (Sp) malloc(sizeof(Scell));
	r -> celltype = l;
	r -> ptrs.lcell.first = s;
	r -> ptrs.lcell.rest = t;
	return(r);
}

Sp car (Sp s)
{
	if (s == NULL) return(err(1));
	if (s -> celltype == l) return(s -> ptrs.lcell.first);
	return(err(2));
}

Sp cdr (Sp s)
{
	if (s == NULL) return(err(3));
	if (s -> celltype == l) return(s -> ptrs.lcell.rest);
	return(err(4));
}

static Sp newalfatom (char * alfa)
{
	Sp r = (Sp) malloc(sizeof(Scell));
	r -> celltype = a;
	r -> ptrs.alfp = (char *) malloc(strlen(alfa) + 1);
	strcpy(r -> ptrs.alfp, alfa);
	return(r);
}

Sp newnumatom (Numtype num)
{
	Sp r = (Sp) malloc(sizeof(Scell));
	r -> celltype = n;
	r -> ptrs.nump = num;
	return(r);
}

char * chars (Sp s)
{
	return(s -> ptrs.alfp);
} /* chars */

Numtype number (Sp s)
{
	return(s -> ptrs.nump);
} /* number */

Stype ctype (Sp s)
{
	return(s -> celltype);
}

void writesexpr(Sp s)
{
	col = 0;
	wsexpr(s);
	printf("\n");
}

static void wsexpr(Sp s)
{
	char str[30];
	if (s == NULL) {
		writeout("("); writeout(")");
		return;
	}
	if (ctype(s) == a) {
		writeout(chars(s));
		return;
	}
	if (ctype(s) == n) {
		sprintf(str, "%f", number(s));
		writeout(str);
		return;
	}
	writeout("(");
	wtail(s);
}

static void wtail(Sp s)
{
	if (s == NULL) {
		writeout(")");
		return;
	}
	wsexpr(car(s));
	writeout(" ");
	wtail(cdr(s));
}

static void writeout(char* c)
{
	long len = (long) strlen(c);
	if (col + len > MAXCOL) {
		printf("\n");
		col = 0;
	}
	printf("%s", c);
	col += len;
}
	
Sp err(long i)
{
	printf("Error number: %ld\n", i);
	return(NULL);
}

void inittrueatom(void)
{
	trueatom = newalfatom("T");
	nilatom =  newalfatom("NIL");
}		

