shithub: semblance

ref: c1cebeee3da60bac9fdde3d8b2caac29c27ef912
dir: /main.c/

View raw version
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <geometry.h>
#include "dat.h"
#include "fns.h"

int debuglexer;

/*
 * decl	: type ;
 * 	| type id
 * 	| type id , decl
 * 	| type id , ids
 * ids	: id
 * 	| id , ids
 */
static int
parsedecl(Lexer *l)
{
	Var v;
	int vt;

	vt = vartype(l->tok.type);

	if(gotany(l, ';', 0))
		return 0;
ids:
	if(!expect(l, TID))
		return -1;
	if(getsym(l->tok.s) != nil){
		werrstr("'%s' already declared", l->tok.s);
		return -1;
	}

	v.type = vt;
	memset(v.val, 0, sizeof(v.val));
	if(declsym(l->tok.s, SYMVAR, v) == nil){
		werrstr("declsym: %r");
		return -1;
	}
	free(l->tok.s);

	if(gotany(l, ',', 0)){
		if(gottype(l))
			return parsedecl(l);
		goto ids;
	}
	return 0;
}

static int
parseexpr(Lexer *l)
{
	Symbol *s1, *s2;
	Op op;
	double n1, n2;

	s1 = s2 = nil;

	if(l->tok.type == TNUM)
		n1 = l->tok.v;
	else{
		s1 = getsym(l->tok.s);
		if(s1 == nil){
			werrstr("'%s' undefined", l->tok.s);
			return -1;
		}
		free(l->tok.s);
	}

	if(!expectany(l, '+', '-', '*', '/', L'·', L'×', 0))
		return -1;
	op.type = optype(l->tok.type);
	op.tok = l->tok.type;

	if(!expectany(l, TNUM, TID, 0))
		return -1;
	if(l->tok.type == TNUM)
		n2 = l->tok.v;
	else{
		s2 = getsym(l->tok.s);
		if(s2 == nil){
			werrstr("'%s' undefined", l->tok.s);
			return -1;
		}
		free(l->tok.s);
	}
	if(s1 != nil)
		fprint(2, "%s", s1->name);
	else
		fprint(2, "%g", n1);
	fprint(2, " %C", op.tok);
	if(s2 != nil)
		fprint(2, " %s\n", s2->name);
	else
		fprint(2, " %g\n", n2);
	return 0;
}

/*
 * stmt	: stmts ;
 * stmts: decl
 */
static int
parsestmt(Lexer *l)
{
	if(gottype(l))
		if(parsedecl(l) < 0)
			sysfatal("parsedecl: %r");
	if(gotany(l, TNUM, TID, 0))
		if(parseexpr(l) < 0)
			sysfatal("parseexpr: %r");
	if(!expect(l, ';'))
		return -1;
	return 0;
}

static int
parse(Lexer *l)
{
	for(;;){
		if(peek(l) < 0)
			sysfatal("error: %r");
		else if(l->peektok.type == TEOF)
			break;
		if(parsestmt(l) < 0)
			sysfatal("parsestmt: %r");
	}
	printsymtab();
	return 0;
}

static void
usage(void)
{
	fprint(2, "usage: %s\n", argv0);
	exits("usage");
}

void
main(int argc, char *argv[])
{
	Lexer *l;

	debuglexer = 0;
	ARGBEGIN{
	case 'd': debuglexer++; break;
	default: usage();
	}ARGEND;
	if(argc != 0)
		usage();

	l = emalloc(sizeof(Lexer));
	l->in = Bfdopen(0, OREAD);
	if(l->in == nil)
		sysfatal("Bfdopen: %r");
	l->ln.line = 1;

	parse(l);

	Bterm(l->in);
	free(l);
	exits(nil);
}