ack/lang/b/compiler/b0.c

1423 lines
22 KiB
C
Raw Permalink Normal View History

2016-11-27 10:37:25 +00:00
#include "b.h"
void extdef(void);
struct hshtab * lookup(void);
void blkhed(void);
void blkend(void);
void statement(int d);
struct tnode * tree(void);
void errflush(int o);
int line = 1;
int peeksym = -1, peeksym2 = -1;;
int contlab = -1;
int brklab = -1;
int wordsize = 4;
const char* modulename = "bmodule_main";
int bsymb_part;
int code_part;
int string_part;
int paramsize;
struct hshtab hshtab[HSHSIZ];
int hshused;
int ateof;
int peekc;
const char* ctab;
struct hshtab *bsym;
struct hshtab *paraml, *parame;
int cval;
int isn;
char symbuf[NCPS+1];
FILE *sbufp;
int stack;
struct tnode **cp;
int *space;
int ospace[OSSIZ];
int retlab;
int nerror;
struct swtab swtab[SWSIZ];
struct swtab *swp;
int deflab;
int contlab;
int brklab;
int opdope[];
int line;
int peeksym, peeksym2;
2016-11-27 10:37:25 +00:00
void
init(char *s, int val)
{
char *sp;
struct hshtab *np;
sp = symbuf;
while (sp < symbuf+NCPS+1)
if ((*sp++ = *s++) == '\0')
s--;
np = lookup();
np->class = KEYWF;
np->offset = val;
}
static void
usage(void)
{
error("Usage: em_b [-w wordsize] [-B modulename] [-i inputfile] [-o outputfile]");
exit(1);
}
2016-11-27 10:37:25 +00:00
int
main(int argc, char *argv[])
{
for (;;) {
int opt = getopt(argc, argv, "w:B:i:o:");
if (opt == -1)
break;
switch (opt) {
case 'w':
wordsize = atoi(optarg);
break;
case 'B':
modulename = aprintf("bmodule_%s", optarg);
break;
case 'i':
if (freopen(optarg, "r", stdin) == NULL) {
error("Can't find %s", optarg);
exit(1);
}
break;
case 'o':
if (freopen(optarg, "w", stdout) == NULL) {
error("Can't create %s", optarg);
exit(1);
}
break;
default:
usage();
2016-11-27 10:37:25 +00:00
}
}
if (optind < argc)
usage();
2016-11-27 10:37:25 +00:00
init("auto", AUTO);
init("extrn", EXTERN);
init("case", CASE);
init("if", IF);
init("else", ELSE);
init("while", WHILE);
init("switch", SWITCH);
init("goto", GOTO);
init("return", RETURN);
init("default", DEFAULT);
init("break", BREAK);
C_init(wordsize, wordsize);
C_open(NULL);
C_magic();
C_ms_emx(wordsize, wordsize);
bsymb_part = 0;
string_part = 0;
code_part = C_getid();
C_beginpart(code_part);
while (!ateof) {
2016-11-27 10:37:25 +00:00
extdef();
blkend();
}
C_endpart(code_part);
C_insertpart(code_part);
if (string_part)
C_insertpart(string_part);
C_exa_dnam((char*) modulename);
C_df_dnam((char*) modulename);
if (bsymb_part)
C_insertpart(bsymb_part);
C_rom_cst(0);
C_close();
2016-11-27 10:37:25 +00:00
return nerror != 0;
}
/*
* Lexer
*/
int
spnextchar(void)
{
int c;
if ((c = peekc) == 0)
c = getchar();
if (c == '\t')
c = ' ';
else if (c == '\n') {
c = ' ';
line++;
}
peekc = c;
return c;
}
int
nextchar(void)
{
while (spnextchar() == ' ')
peekc = 0;
return peekc;
}
int
subseq(int c, int a, int b)
{
if (spnextchar() != c)
return a;
peekc = 0;
return b;
}
/* Only decimal and octal bases, could extend */
int
getnum(void)
{
int base;
int c;
base = 10;
cval = 0;
if ((c=spnextchar()) == '0')
base = 8;
for (; ctab[c] == DIGIT; c = getchar())
cval = cval*base + c-'0';
peekc = c;
return CON;
}
int
mapch(char c)
{
int a;
if ((a=getchar()) == c)
return -1;
switch (a) {
case '\n':
case '\0':
error("Nonterminated string");
peekc = a;
return -1;
case '*':
switch (a=getchar()) {
case 't':
return('\t');
case 'n':
return('\n');
case '0':
return('\0');
case '(':
return('{');
case ')':
return('}');
case 'e':
return(EOS);
case '\n':
line++;
return('\n');
}
}
return a;
}
int
getcc(void)
{
char *cp;
int c, cc;
cval = 0;
cc = 0;
cp = (char*) &cval;
while ((c = mapch('\'')) >= 0)
if (cc++ < wordsize)
2016-11-27 10:37:25 +00:00
*cp++ = c;
if (cc > wordsize)
2016-11-27 10:37:25 +00:00
error("Long character constant");
return CON;
}
int
getstr(void)
{
int c;
int i;
char b;
int partid;
partid = C_getid();
C_beginpart(partid);
if (string_part)
C_insertpart(string_part);
cval = isn++;
C_df_dlb(cval);
for (i = 1; (c = mapch('"')) >= 0; i++) {
b = c;
C_con_scon(&b, 1);
}
b = 04;
C_con_scon(&b, 1);
2016-11-27 10:37:25 +00:00
b = 0;
2016-11-27 10:37:25 +00:00
while ((i++%4) != 0)
C_con_scon(&b, 1);
C_endpart(partid);
string_part = partid;
2016-11-27 10:37:25 +00:00
return STRING;
}
struct hshtab *
lookup(void)
{
int i;
char *sp, *np;
struct hshtab *rp;
i = 0;
sp = symbuf;
while (sp < symbuf+NCPS)
i += *sp++&0177;
rp = &hshtab[i%HSHSIZ];
while (*(np = rp->name)) {
for (sp=symbuf; sp < symbuf+NCPS;)
if (*np++ != *sp++)
goto no;
return rp;
no:
if (++rp >= &hshtab[HSHSIZ])
rp = hshtab;
}
if (++hshused > HSHSIZ) {
error("Symbol table overflow");
exit(1);
}
rp->class = 0;
rp->offset = 0;
rp->dim = 0;
sp = symbuf;
for (np = rp->name; sp < symbuf+NCPS+1;)
*np++ = *sp++;
return rp;
}
/*
* Symbol peeking with one peeksym doesn't work if an ASSIGN is only peeked,
* since it itself peeks a symbol, which is then overwritten.
*/
/* Note: does not push bsyms !! */
int
pushsym(int sym)
{
if (peeksym < 0)
peeksym = sym;
else if (peeksym2 < 0) {
peeksym2 = peeksym;
peeksym = sym;
} else
error("Cannot push more than two symbols\n");
return sym;
}
int
symbol(void)
{
int c;
char *sp;
if (peeksym >= 0) {
c = peeksym;
peeksym = peeksym2;
peeksym2 = -1;
return c;
}
if (peekc) {
c = peekc;
peekc = 0;
} else
if (ateof)
2016-11-27 10:37:25 +00:00
return EOFC;
else
c = getchar();
if (c==EOF) {
ateof++;
2016-11-27 10:37:25 +00:00
return(EOFC);
}
loop:
switch (ctab[c]) {
case NEWLN:
line++;
/* fall through */
2016-11-27 10:37:25 +00:00
case SPACE:
c = getchar();
goto loop;
case HASH:
/* # is invalid in B; but we handle it out of convenience so that we can read
* in input files that have been run through the C preprocessor. Ideally we
* should only recognise it when it's the first character in a line, but as
* it's not used anywhere else we can get away with recognising it anywhere.
*/
while ((c = getchar()) == ' ')
;
peekc = c;
getnum();
line = cval;
while ((c = getchar()) != '\n')
;
goto loop;
2016-11-27 10:37:25 +00:00
case PLUS:
return subseq(c,PLUS,INCBEF);
case MINUS:
return subseq(c,MINUS,DECBEF);
2016-11-27 10:37:25 +00:00
case LESS:
if (subseq(c,0,1))
return LSHIFT;
return subseq('=', LESS, LESSEQ);
case GREAT:
if (subseq(c,0,1))
return RSHIFT;
return subseq('=', GREAT, GREATEQ);
case ASSIGN:
if (subseq(' ',0,1))
return ASSIGN;
/* avoid peeking a name, which could overwrite
* an already set bsym. */
if (ctab[peekc = spnextchar()] == LETTER)
return ASSIGN;
c = symbol();
2016-12-31 17:36:12 +00:00
if (PLUS <= c && c <= EOR)
2016-11-27 10:37:25 +00:00
return c + ASPLUS-PLUS;
if (c == ASSIGN)
return EQUAL;
pushsym(c);
return ASSIGN;
case EXCLA:
return subseq('=',EXCLA,NEQUAL);
case DIVIDE:
if (subseq('*',1,0))
return DIVIDE;
while ((c = spnextchar()) != EOFC) {
peekc = 0;
if (c == '*') {
if (spnextchar() == '/') {
peekc = 0;
c = getchar();
goto loop;
}
}
}
ateof++;
2016-11-27 10:37:25 +00:00
error("Nonterminated comment");
return EOFC;
case DIGIT:
peekc = c;
return getnum();
case SQUOTE:
return(getcc());
case DQUOTE:
return(getstr());
case LETTER:
sp = symbuf;
while (ctab[c] == LETTER || ctab[c] == DIGIT) {
if (sp < symbuf+NCPS)
*sp++ = c;
c = getchar();
}
while (sp < symbuf+NCPS+1)
*sp++ = '\0';
peekc = c;
bsym = lookup();
if (bsym->class == KEYWF) {
cval = bsym->offset;
return KEYW;
}
return NAME;
case UNKN:
error("Unknown character");
c = getchar();
goto loop;
}
return (ctab[c]);
}
/*
* Declarations and Definitions
*/
/* Declares a list of names to be of storage class "kw". */
void
declare(int kw)
{
int o;
while ((o = symbol()) == NAME) {
if (bsym->class)
error("%s redeclared", bsym->name);
bsym->class = kw;
while ((o = symbol()) == LBRACK) {
if ((o = symbol()) == CON) {
if (bsym->dim)
error("Bad vector");
bsym->dim = cval + 1;
o = symbol();
}
if (o != RBRACK)
goto syntax;
}
if (kw == ARG) {
bsym->next = NULL;
if (!paraml)
paraml = bsym;
else
parame->next = bsym;
parame = bsym;
}
if (o != COMMA)
break;
}
if ((o == SEMI && kw != ARG) || (o == RPARN && kw == ARG))
return;
syntax:
error("Declaration syntax");
errflush(o);
}
void
declist(void)
{
int o;
while ((o = symbol()) == KEYW && (cval == AUTO || cval == EXTERN))
declare(cval);
pushsym(o);
}
void
function(void)
{
declare(ARG);
statement(1);
C_ret(0);
C_end(paramsize);
2016-11-27 10:37:25 +00:00
}
void
global(char *s)
{
C_exa_dnam(manglename(s, 'b'));
2016-11-27 10:37:25 +00:00
}
void
bsymb(char *s)
2016-11-27 10:37:25 +00:00
{
int newpart = C_getid();
C_beginpart(newpart);
if (bsymb_part != 0)
C_insertpart(bsymb_part);
C_rom_dlb(isn, 0);
C_endpart(newpart);
bsymb_part = newpart;
C_df_dlb(isn++);
2016-11-27 10:37:25 +00:00
}
void
extdef(void)
{
int o, dim, i;
char *bs;
char *ms;
int neg;
2016-11-27 10:37:25 +00:00
if ((o = symbol()) == EOFC || o == SEMI)
return;
if (o != NAME)
goto syntax;
bs = bsym->name;
i = dim = 0;
neg = 0;
2016-11-27 10:37:25 +00:00
switch(o = symbol()) {
case SEMI:
global(bs);
C_df_dnam(manglename(bs, 'b'));
C_bss_cst(wordsize, 0, 1);
2016-11-27 10:37:25 +00:00
goto done;
/* init */
case CON:
case STRING:
case MINUS:
2016-11-27 10:37:25 +00:00
global(bs);
if (o == STRING)
bsymb(bs);
else if (o == MINUS) {
o = symbol();
if (o != CON)
goto syntax;
cval = -cval;
}
C_df_dnam(manglename(bs, 'b'));
2016-11-27 10:37:25 +00:00
pushsym(o);
goto init;
/* vector */
case LBRACK:
if ((o=symbol()) == CON) {
dim = cval + 1;
o=symbol();
}
if (o != RBRACK)
goto syntax;
global(bs);
if ((o=symbol()) == SEMI) {
bsymb(bs);
C_df_dnam(manglename(bs, 'b'));
C_con_dlb(isn, 0);
C_df_dlb(isn++);
C_bss_cst(wordsize*dim, 0, 1);
2016-11-27 10:37:25 +00:00
goto done;
}
bsymb(bs);
C_df_dnam(manglename(bs, 'b'));
C_con_dlb(isn, 0);
C_df_dlb(isn++);
2016-11-27 10:37:25 +00:00
pushsym(o);
init:
do {
if ((o=symbol()) != CON && o != STRING && o != NAME)
goto syntax;
if (o == NAME) {
bsymb(NULL);
C_con_dnam(manglename(bsym->name, 'b'), 0);
} else {
if (o == STRING) {
bsymb(NULL);
C_con_dlb(cval, 0);
} else
C_con_cst(cval);
}
2016-11-27 10:37:25 +00:00
i++;
} while ((o=symbol()) == COMMA);
dim = (i > dim) ? i : dim;
if (i == 0)
C_bss_cst((dim-i)*wordsize, 0, 1);
else {
while (dim -i) {
C_con_cst(0);
i++;
}
}
2016-11-27 10:37:25 +00:00
if (o == SEMI)
goto done;
goto syntax;
/* function */
case LPARN:
global(bs);
ms = manglename(bs, 'b');
bsymb(ms);
C_df_dnam(ms);
ms = manglename(bs, 'i');
C_con_pnam(ms);
C_inp(ms);
C_pro_narg(ms);
2016-11-27 10:37:25 +00:00
function();
done:
return;
case EOFC:
return;
}
syntax:
error("External definition syntax");
printtoken(o, stderr);
errflush(o);
statement(0);
}
void
blkhed(void)
{
int al, pl;
struct hshtab *bs;
declist();
stack = al = -wordsize;
pl = 0; /* EM parameters start at offset 0. */
2016-11-27 10:37:25 +00:00
while (paraml) {
paraml = (bs = paraml)->next;
bs->offset = pl;
pl += wordsize;
2016-11-27 10:37:25 +00:00
}
for (bs = hshtab; bs < &hshtab[HSHSIZ]; bs++)
if (bs->name[0]) {
if (bs->class == AUTO) {
bs->offset = al;
if (bs->dim) {
al -= bs->dim*wordsize;
C_lal(al);
al -= wordsize;
fromnativeaddr();
C_stl(al);
2016-11-27 10:37:25 +00:00
bs->offset = al;
}
al -= wordsize;
2016-11-27 10:37:25 +00:00
} else if (bs->class == ARG)
bs->class = AUTO;
}
paramsize = -al - wordsize;
2016-11-27 10:37:25 +00:00
}
void
blkend(void)
{
struct hshtab *np;
for (np = hshtab; np < &hshtab[HSHSIZ]; np++)
if (np->class != KEYWF) {
np->name[0] = '\0';
hshused--;
}
}
/*
* Statements and Expressions
*/
struct tnode *
pexpr(void)
{
struct tnode *t;
int o;
if ((o = symbol()) != LPARN)
goto syntax;
t = tree();
if ((o = symbol()) != RPARN)
goto syntax;
return t;
syntax:
error("Statement syntax");
errflush(o);
return NULL;
}
void
fnlabel(int l)
2016-11-27 10:37:25 +00:00
{
C_ilb(l);
2016-11-27 10:37:25 +00:00
}
/* Jump to "lab", if the expression "t" evaluated to 0. */
2016-11-27 10:37:25 +00:00
void
cbranch(struct tnode *t, int lab)
2016-11-27 10:37:25 +00:00
{
rcexpr(t);
C_zeq(lab);
2016-11-27 10:37:25 +00:00
}
void
jump(int lab)
{
C_bra(lab);
2016-11-27 10:37:25 +00:00
}
void
pswitch(void)
{
struct swtab *sswp;
int dl, swlab;
if (swp == NULL)
swp = swtab;
sswp = swp;
2016-11-27 10:37:25 +00:00
swlab = isn++;
C_lae_dlb(swlab, 0);
C_csb(wordsize);
2016-11-27 10:37:25 +00:00
dl = deflab;
deflab = 0;
statement(0);
if (!deflab)
deflab = brklab;
C_df_dlb(swlab);
C_rom_ilb(deflab);
C_rom_cst(swp - sswp);
2016-11-27 10:37:25 +00:00
while (swp > sswp && swp > swtab) {
--swp;
C_rom_cst(swp->swval);
C_rom_ilb(swp->swlab);
2016-11-27 10:37:25 +00:00
}
C_df_ilb(brklab);
2016-11-27 10:37:25 +00:00
deflab = dl;
swp = sswp;
}
void
statement(int d)
{
int o, o1, o2;
stmt:
if ((o = symbol()) == LBRACE) {
if (d)
blkhed();
while (!ateof) {
2016-11-27 10:37:25 +00:00
if ((o = symbol()) == RBRACE)
goto bend;
pushsym(o);
statement(0);
}
error("Missing '}'");
bend:
return;
} else {
pushsym(o);
if (d)
blkhed();
}
switch (o = symbol()) {
case EOFC:
error("Unexpected EOF");
case SEMI:
case RBRACE:
return;
case KEYW:
switch (cval) {
case GOTO:
if ((o = symbol()) != NAME)
goto syntax;
if (bsym->offset == 0)
bsym->offset = isn++;
2016-11-27 10:37:25 +00:00
jump(bsym->offset);
goto semi;
case RETURN:
if (pushsym(symbol()) == LPARN) {
2016-11-27 10:37:25 +00:00
rcexpr(pexpr());
C_ret(wordsize);
} else {
C_ret(0);
}
2016-11-27 10:37:25 +00:00
goto semi;
case IF:
cbranch(pexpr(), o1=isn++);
2016-11-27 10:37:25 +00:00
statement(0);
if ((o = symbol()) == KEYW && cval == ELSE) {
jump(o2 = isn++);
fnlabel(o1);
2016-11-27 10:37:25 +00:00
statement(0);
fnlabel(o2);
2016-11-27 10:37:25 +00:00
return;
}
pushsym(o);
fnlabel(o1);
2016-11-27 10:37:25 +00:00
return;
case WHILE:
o1 = contlab;
o2 = brklab;
fnlabel(contlab = isn++);
cbranch(pexpr(), brklab=isn++);
2016-11-27 10:37:25 +00:00
statement(0);
jump(contlab);
fnlabel(brklab);
2016-11-27 10:37:25 +00:00
contlab = o1;
brklab = o2;
return;
case BREAK:
if (brklab < 0)
error("Nothing to break from");
jump(brklab);
goto semi;
/* Not part of B, but very easy to implement */
/*
case CONTINUE:
if (contlab < 0)
error("Nothing to continue");
jump(contlab);
goto semi;
*/
case SWITCH:
o1 = brklab;
brklab = isn++;
rcexpr(pexpr());
/* rcexpr(tree()); */
pswitch();
brklab = o1;
return;
case CASE:
if ((o = symbol()) != CON)
goto syntax;
if ((o = symbol()) != COLON)
goto syntax;
if (swp == NULL) {
error("Case not in switch");
goto stmt;
}
if (swp >= swtab+SWSIZ)
error("Switch table overflow");
else {
swp->swlab = isn;
(swp++)->swval = cval;
fnlabel(isn++);
2016-11-27 10:37:25 +00:00
}
goto stmt;
case DEFAULT:
if (swp == NULL)
error("Default not in switch");
if ((o = symbol()) != COLON)
goto syntax;
deflab = isn++;
fnlabel(deflab);
2016-11-27 10:37:25 +00:00
goto stmt;
}
error("Unknown keyword");
goto syntax;
case NAME:
if (peekc == ':') {
peekc = 0;
if (bsym->class) {
error("Redefinition");
goto stmt;
}
bsym->class = INTERN;
if (bsym->offset == 0)
bsym->offset = isn++;
fnlabel(bsym->offset);
2016-11-27 10:37:25 +00:00
goto stmt;
}
}
pushsym(o);
rcexpr(tree());
C_asp(wordsize);
2016-11-27 10:37:25 +00:00
goto semi;
semi:
if ((o = symbol()) != SEMI)
goto syntax;
return;
syntax:
error("Statement syntax");
errflush(o);
goto stmt;
}
struct tnode *
block(int op, int value, struct tnode *tr1, struct tnode *tr2)
{
struct tnode t;
int n;
int *p, *ap;
p = space;
t.op = op;
t.value = value;
t.tr1 = tr1;
t.tr2 = tr2;
ap = (int*) &t;
n = (sizeof(struct tnode)+sizeof(int)-1) & ~sizeof(int);
if (space+n >= &ospace[OSSIZ]) {
error("Expression overflow 1");
exit(1);
}
while (n--)
*space++ = *ap++;
return (struct tnode *) p;
}
void
chklval(struct tnode *p)
{
if (p->op != NAME && p->op != STAR)
error("Lvalue required");
}
void
build(int op)
{
struct tnode *p1, *p2;
int dope;
/* a[i] -> *(a+i) */
if (op == LBRACK) {
build(PLUS);
op = STAR;
}
dope = opdope[op];
if (dope&01)
p2 = *--cp;
p1 = *--cp;
switch (op) {
case QUEST:
if (p2->op != COLON)
error("Illegal conditional");
break;
case AMPER:
if (p1->op == STAR) {
*cp++ = p1->tr1;
return;
}
if (p1->op == NAME) {
*cp++ = block(op,0,p1,NULL);
return;
}
error("Illegal lvalue");
}
if (dope&02)
chklval(p1);
if (dope&01)
*cp++ = block(op,0,p1,p2);
else
*cp++ = block(op,0,p1,NULL);
}
struct tnode *
tree(void)
{
struct tnode *cmst[CMSIZ];
int opst[SSIZE], prst[SSIZE];
int *op, *pp;
int andflg;
int o, os;
int p, ps;
space = ospace;
op = opst;
pp = prst;
cp = cmst;
*op = SEOF;
*pp = 06;
andflg = 0;
advanc:
switch (o=symbol()) {
case NAME:
if (pushsym(symbol()) == LPARN) { /* function */
if (bsym->class == 0)
bsym->class = EXTERN;
2016-11-27 10:37:25 +00:00
} else if (bsym->class == 0) {
error("%s undefined", bsym->name);
bsym->class = EXTERN;
}
*cp++ = block(NAME,0,(struct tnode *)bsym,NULL);
goto tand;
case STRING:
*cp++ = block(STRING,cval,NULL,NULL);
goto tand;
case CON:
caseCON:
*cp++ = block(CON,cval,NULL,NULL);
goto tand;
tand:
if (cp >= &cmst[CMSIZ]) {
error("Expression overflow 2");
exit(1);
}
if (andflg)
goto syntax;
andflg = 1;
goto advanc;
case DECBEF:
case INCBEF:
if (andflg)
o += 2;
goto oponst;
case EXCLA:
2017-01-01 17:40:06 +00:00
case NOT:
2016-11-27 10:37:25 +00:00
if (andflg)
goto syntax;
goto oponst;
case MINUS:
if (!andflg) {
if (pushsym(symbol()) == CON) {
symbol();
cval = -cval;
goto caseCON;
}
o = NEG;
}
andflg = 0;
goto oponst;
case AND:
case TIMES:
if (andflg)
andflg = 0;
else
if (o == AND)
o = AMPER;
else
o = STAR;
goto oponst;
case LPARN:
if (andflg) {
o = symbol();
if (o == RPARN)
o = MCALL;
else {
pushsym(o);
o = CALL;
andflg = 0;
}
}
goto oponst;
case RPARN:
case RBRACK:
if (!andflg)
goto syntax;
goto oponst;
}
if (!andflg)
goto syntax;
andflg = 0;
oponst:
p = (opdope[o]>>9) & 077;
opon1:
ps = *pp;
if (p > ps || (p == ps && (opdope[o]&0200))) { /* right-assoc */
switch (o) {
case LPARN:
case LBRACK:
case CALL:
p = 04;
}
if (op >= &opst[SSIZE]) {
error("Expression overflow 3");
exit(1);
}
*++op = o;
*++pp = p;
goto advanc;
}
--pp;
switch (os = *op--) {
case SEOF:
pushsym(o);
return(*--cp);
case CALL:
if (o != RPARN)
goto syntax;
build(os);
goto advanc;
case MCALL:
*cp++ = NULL;
os = CALL;
goto fbuild;
case LPARN:
if (o != RPARN)
goto syntax;
goto advanc;
case LBRACK:
if (o != RBRACK)
goto syntax;
build(LBRACK);
goto advanc;
}
fbuild:
build(os);
goto opon1;
syntax:
error("Expression syntax");
errflush(o);
return NULL;
}
void
error(char *s, ...)
{
va_list args;
va_start(args, s);
nerror++;
fprintf(stderr, "%d: ", line);
vfprintf(stderr, s, args);
putc('\n', stderr);
va_end(args);
}
void
errflush(int o)
{
while (o > RBRACE) /* ; { } */
o = symbol();
pushsym(o);
}
/*
* 000001 binary
* 000002 need lvalue
* 000004 relational
* 000010 assignment
* 000100 commutative
* 000200 right-assoc
* 0XX000 precedence
*/
int opdope[] = {
000000, /* EOFC */
000000, /* ; */
000000, /* { */
000000, /* } */
036000, /* [ */
002000, /* ] */
036000, /* ( */
002000, /* ) */
014201, /* : */
007001, /* , */
000000, /* 10 */
000000, /* 11 */
000000, /* 12 */
000000, /* 13 */
000000, /* 14 */
036001, /* mcall */
036001, /* call */
034202, /* ++a */
034202, /* a++ */
034202, /* --a */
034202, /* a-- */
034200, /* !un */
034200, /* -un */
034200, /* &un */
034200, /* *un */
014201, /* ? */
2017-01-01 17:40:06 +00:00
034200, /* ~un */
2016-11-27 10:37:25 +00:00
000000, /* 27 */
000000, /* 28 */
000000, /* 29 */
030101, /* + */
030001, /* - */
032001, /* % */
032101, /* * */
032001, /* / */
016101, /* | */
020101, /* & */
026001, /* << */
026001, /* >> */
022105, /* == */
022105, /* != */
024005, /* <= */
024005, /* < */
024005, /* >= */
024005, /* > */
2016-12-31 17:36:12 +00:00
017005, /* ^ */
2016-11-27 10:37:25 +00:00
000000, /* 46 */
000000, /* 47 */
000000, /* 48 */
012013, /* = */
012213, /* =+ */
012213, /* =- */
012213, /* =% */
012213, /* =* */
012213, /* =/ */
012213, /* =| */
012213, /* =& */
012213, /* =<< */
012213, /* =>> */
012213, /* === */
012213, /* =!= */
012213, /* =<= */
012213, /* =< */
012213, /* =>= */
012213, /* => */
2016-12-31 17:36:12 +00:00
012213, /* =^ */
000000, /* 66 */
000000, /* 67 */
000000, /* 68 */
000000, /* 69 */
2016-11-27 10:37:25 +00:00
000000, /* CON */
000000, /* STRING */
000000 /* NAME */
};
const char ctaba[129] = {
EOFC, /* -1 */
2016-11-27 10:37:25 +00:00
EOFC, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
LETTER, SPACE, NEWLN, SPACE, SPACE, UNKN, UNKN, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN, UNKN,
SPACE, EXCLA, DQUOTE, HASH, UNKN, MOD, AND, SQUOTE,
2016-11-27 10:37:25 +00:00
LPARN, RPARN, TIMES, PLUS, COMMA, MINUS, UNKN, DIVIDE,
DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT,
DIGIT, DIGIT, COLON, SEMI, LESS, ASSIGN, GREAT, QUEST,
UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
2016-12-31 17:36:12 +00:00
LETTER, LETTER, LETTER, LBRACK, UNKN, RBRACK, EOR, LETTER,
2016-11-27 10:37:25 +00:00
UNKN, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
2017-01-01 17:40:06 +00:00
LETTER, LETTER, LETTER, LBRACE, OR, RBRACE, NOT, UNKN
2016-11-27 10:37:25 +00:00
};
const char* ctab = &ctaba[1]; /* allows indexing with -1 */
2016-11-27 10:37:25 +00:00
/* debug function */
void printtoken(int tok, FILE *out)
{
static char *strtab[128];
strtab[0] = "EOFC";
strtab[1] = "SEMI";
strtab[2] = "LBRACE";
strtab[3] = "RBRACE";
strtab[4] = "LBRACK";
strtab[5] = "RBRACK";
strtab[6] = "LPARN";
strtab[7] = "RPARN";
strtab[8] = "COLON";
strtab[9] = "COMMA";
2016-12-31 17:36:12 +00:00
strtab[10] = "HASH";
2016-11-27 10:37:25 +00:00
strtab[15] = "MCALL";
strtab[16] = "CALL";
strtab[17] = "DECBEF";
strtab[18] = "INCBEF";
strtab[19] = "DECAFT";
strtab[20] = "INCAFT";
strtab[21] = "EXCLA";
strtab[22] = "NEG";
strtab[23] = "AMPER";
strtab[24] = "STAR";
strtab[25] = "QUEST";
2017-01-01 17:40:06 +00:00
strtab[26] = "NOT";
2016-11-27 10:37:25 +00:00
strtab[30] = "PLUS";
strtab[31] = "MINUS";
strtab[32] = "MOD";
strtab[33] = "TIMES";
strtab[34] = "DIVIDE";
strtab[35] = "OR";
strtab[36] = "AND";
strtab[37] = "LSHIFT";
strtab[38] = "RSHIFT";
strtab[39] = "EQUAL";
strtab[40] = "NEQUAL";
strtab[41] = "LESSEQ";
strtab[42] = "LESS";
strtab[43] = "GREATEQ";
strtab[44] = "GREAT";
2016-12-31 17:36:12 +00:00
strtab[45] = "EOR";
2016-11-27 10:37:25 +00:00
strtab[49] = "ASSIGN";
strtab[50] = "ASPLUS";
strtab[51] = "ASMINUS";
strtab[52] = "ASMOD";
strtab[53] = "ASTIMES";
strtab[54] = "ASDIV";
strtab[55] = "ASOR";
strtab[56] = "ASAND";
strtab[57] = "ASLSH";
strtab[58] = "ASRSH";
strtab[59] = "ASEQUAL";
strtab[60] = "ASNEQL";
strtab[61] = "ASLEQ";
strtab[62] = "ASLESS";
strtab[63] = "ASGTQ";
strtab[64] = "ASGREAT";
2016-12-31 17:36:12 +00:00
strtab[65] = "ASEOR";
2016-11-27 10:37:25 +00:00
2016-12-31 17:36:12 +00:00
strtab[70] = "CON";
strtab[71] = "STRING";
strtab[72] = "NAME";
strtab[73] = "KEYW";
2016-11-27 10:37:25 +00:00
strtab[127] = "UNKN";
if (tok == CON || tok == STRING) {
fprintf(out, "%s(%d) ", strtab[tok], cval);
return;
}
if (tok == NAME) {
fprintf(out, "%s(%s) ", strtab[tok], symbuf);
return;
}
fprintf(out, "%s ", strtab[tok]);
}