ref: c1cebeee3da60bac9fdde3d8b2caac29c27ef912
dir: /main.c/
#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);
}