123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include <ctype.h>
- #include <mach.h>
- #define Extern extern
- #include "acid.h"
- #include "y.tab.h"
- struct keywd
- {
- char *name;
- int terminal;
- }
- keywds[] =
- {
- "do", Tdo,
- "if", Tif,
- "then", Tthen,
- "else", Telse,
- "while", Twhile,
- "loop", Tloop,
- "head", Thead,
- "tail", Ttail,
- "append", Tappend,
- "defn", Tfn,
- "return", Tret,
- "local", Tlocal,
- "aggr", Tcomplex,
- "union", Tcomplex,
- "adt", Tcomplex,
- "complex", Tcomplex,
- "delete", Tdelete,
- "whatis", Twhat,
- "eval", Teval,
- "builtin", Tbuiltin,
- 0, 0
- };
- char cmap[256] =
- {
- ['0'] '\0'+1,
- ['n'] '\n'+1,
- ['r'] '\r'+1,
- ['t'] '\t'+1,
- ['b'] '\b'+1,
- ['f'] '\f'+1,
- ['a'] '\a'+1,
- ['v'] '\v'+1,
- ['\\'] '\\'+1,
- ['"'] '"'+1,
- };
- void
- kinit(void)
- {
- int i;
-
- for(i = 0; keywds[i].name; i++)
- enter(keywds[i].name, keywds[i].terminal);
- }
- typedef struct IOstack IOstack;
- struct IOstack
- {
- char *name;
- int line;
- char *text;
- char *ip;
- Biobuf *fin;
- IOstack *prev;
- };
- IOstack *lexio;
- void
- pushfile(char *file)
- {
- Biobuf *b;
- IOstack *io;
- if(file)
- b = Bopen(file, OREAD);
- else{
- b = Bopen("/fd/0", OREAD);
- file = "<stdin>";
- }
- if(b == 0)
- error("pushfile: %s: %r", file);
- io = malloc(sizeof(IOstack));
- if(io == 0)
- fatal("no memory");
- io->name = strdup(file);
- if(io->name == 0)
- fatal("no memory");
- io->line = line;
- line = 1;
- io->text = 0;
- io->fin = b;
- io->prev = lexio;
- lexio = io;
- }
- void
- pushstr(Node *s)
- {
- IOstack *io;
- io = malloc(sizeof(IOstack));
- if(io == 0)
- fatal("no memory");
- io->line = line;
- line = 1;
- io->name = strdup("<string>");
- if(io->name == 0)
- fatal("no memory");
- io->line = line;
- line = 1;
- io->text = strdup(s->string->string);
- if(io->text == 0)
- fatal("no memory");
- io->ip = io->text;
- io->fin = 0;
- io->prev = lexio;
- lexio = io;
- }
- void
- restartio(void)
- {
- Bflush(lexio->fin);
- Binit(lexio->fin, 0, OREAD);
- }
- int
- popio(void)
- {
- IOstack *s;
- if(lexio == 0)
- return 0;
- if(lexio->prev == 0){
- if(lexio->fin)
- restartio();
- return 0;
- }
- if(lexio->fin)
- Bterm(lexio->fin);
- else
- free(lexio->text);
- free(lexio->name);
- line = lexio->line;
- s = lexio;
- lexio = s->prev;
- free(s);
- return 1;
- }
- int
- Lfmt(Fmt *f)
- {
- int i;
- char buf[1024];
- IOstack *e;
- e = lexio;
- if(e) {
- i = snprint(buf, sizeof(buf), "%s:%d", e->name, line);
- while(e->prev) {
- e = e->prev;
- if(initialising && e->prev == 0)
- break;
- i += snprint(buf+i, sizeof(buf)-i, " [%s:%d]", e->name, e->line);
- }
- } else
- snprint(buf, sizeof(buf), "no file:0");
- fmtstrcpy(f, buf);
- return 0;
- }
- void
- unlexc(int s)
- {
- if(s == '\n')
- line--;
- if(lexio->fin)
- Bungetc(lexio->fin);
- else
- lexio->ip--;
- }
- int
- lexc(void)
- {
- int c;
- if(lexio->fin) {
- c = Bgetc(lexio->fin);
- if(gotint)
- error("interrupt");
- return c;
- }
- c = *lexio->ip++;
- if(c == 0)
- return -1;
- return c;
- }
- int
- escchar(char c)
- {
- int n;
- char buf[Strsize];
- if(c >= '0' && c <= '9') {
- n = 1;
- buf[0] = c;
- for(;;) {
- c = lexc();
- if(c == Eof)
- error("%d: <eof> in escape sequence", line);
- if(strchr("0123456789xX", c) == 0) {
- unlexc(c);
- break;
- }
- if(n >= Strsize)
- error("string escape too long");
- buf[n++] = c;
- }
- buf[n] = '\0';
- return strtol(buf, 0, 0);
- }
- n = cmap[c];
- if(n == 0)
- return c;
- return n-1;
- }
- void
- eatstring(void)
- {
- int esc, c, cnt;
- char buf[Strsize];
- esc = 0;
- for(cnt = 0;;) {
- c = lexc();
- switch(c) {
- case Eof:
- error("%d: <eof> in string constant", line);
- case '\n':
- error("newline in string constant");
- goto done;
- case '\\':
- if(esc)
- goto Default;
- esc = 1;
- break;
- case '"':
- if(esc == 0)
- goto done;
- /* Fall through */
- default:
- Default:
- if(esc) {
- c = escchar(c);
- esc = 0;
- }
- buf[cnt++] = c;
- break;
- }
- if(cnt >= Strsize)
- error("string token too long");
- }
- done:
- buf[cnt] = '\0';
- yylval.string = strnode(buf);
- }
- void
- eatnl(void)
- {
- int c;
- line++;
- for(;;) {
- c = lexc();
- if(c == Eof)
- error("eof in comment");
- if(c == '\n')
- return;
- }
- }
- int
- yylex(void)
- {
- int c;
- extern char vfmt[];
- loop:
- Bflush(bout);
- c = lexc();
- switch(c) {
- case Eof:
- if(gotint) {
- gotint = 0;
- stacked = 0;
- Bprint(bout, "\nacid: ");
- goto loop;
- }
- return Eof;
- case '"':
- eatstring();
- return Tstring;
- case ' ':
- case '\t':
- goto loop;
- case '\n':
- line++;
- if(interactive == 0)
- goto loop;
- if(stacked) {
- print("\t");
- goto loop;
- }
- return ';';
- case '.':
- c = lexc();
- unlexc(c);
- if(isdigit(c))
- return numsym('.');
- return '.';
-
- case '(':
- case ')':
- case '[':
- case ']':
- case ';':
- case ':':
- case ',':
- case '~':
- case '?':
- case '*':
- case '@':
- case '^':
- case '%':
- return c;
- case '{':
- stacked++;
- return c;
- case '}':
- stacked--;
- return c;
- case '\\':
- c = lexc();
- if(strchr(vfmt, c) == 0) {
- unlexc(c);
- return '\\';
- }
- yylval.ival = c;
- return Tfmt;
- case '!':
- c = lexc();
- if(c == '=')
- return Tneq;
- unlexc(c);
- return '!';
- case '+':
- c = lexc();
- if(c == '+')
- return Tinc;
- unlexc(c);
- return '+';
- case '/':
- c = lexc();
- if(c == '/') {
- eatnl();
- goto loop;
- }
- unlexc(c);
- return '/';
- case '\'':
- c = lexc();
- if(c == '\\')
- yylval.ival = escchar(lexc());
- else
- yylval.ival = c;
- c = lexc();
- if(c != '\'') {
- error("missing '");
- unlexc(c);
- }
- return Tconst;
- case '&':
- c = lexc();
- if(c == '&')
- return Tandand;
- unlexc(c);
- return '&';
- case '=':
- c = lexc();
- if(c == '=')
- return Teq;
- unlexc(c);
- return '=';
- case '|':
- c = lexc();
- if(c == '|')
- return Toror;
- unlexc(c);
- return '|';
- case '<':
- c = lexc();
- if(c == '=')
- return Tleq;
- if(c == '<')
- return Tlsh;
- unlexc(c);
- return '<';
- case '>':
- c = lexc();
- if(c == '=')
- return Tgeq;
- if(c == '>')
- return Trsh;
- unlexc(c);
- return '>';
- case '-':
- c = lexc();
- if(c == '>')
- return Tindir;
- if(c == '-')
- return Tdec;
- unlexc(c);
- return '-';
- default:
- return numsym(c);
- }
- }
- int
- numsym(char first)
- {
- int c, isbin, isfloat, ishex;
- char *sel, *p;
- Lsym *s;
- symbol[0] = first;
- p = symbol;
- ishex = 0;
- isbin = 0;
- isfloat = 0;
- if(first == '.')
- isfloat = 1;
- if(isdigit(*p++) || isfloat) {
- for(;;) {
- c = lexc();
- if(c < 0)
- error("%d: <eof> eating symbols", line);
- if(c == '\n')
- line++;
- sel = "01234567890.xb";
- if(ishex)
- sel = "01234567890abcdefABCDEF";
- else if(isbin)
- sel = "01";
- else if(isfloat)
- sel = "01234567890eE-+";
- if(strchr(sel, c) == 0) {
- unlexc(c);
- break;
- }
- if(c == '.')
- isfloat = 1;
- if(!isbin && c == 'x')
- ishex = 1;
- if(!ishex && c == 'b')
- isbin = 1;
- *p++ = c;
- }
- *p = '\0';
- if(isfloat) {
- yylval.fval = atof(symbol);
- return Tfconst;
- }
- if(isbin)
- yylval.ival = strtoull(symbol+2, 0, 2);
- else
- yylval.ival = strtoull(symbol, 0, 0);
- return Tconst;
- }
- for(;;) {
- c = lexc();
- if(c < 0)
- error("%d <eof> eating symbols", line);
- if(c == '\n')
- line++;
- if(c != '_' && c != '$' && c <= '~' && !isalnum(c)) { /* checking against ~ lets UTF names through */
- unlexc(c);
- break;
- }
- *p++ = c;
- }
- *p = '\0';
- s = look(symbol);
- if(s == 0)
- s = enter(symbol, Tid);
- yylval.sym = s;
- return s->lexval;
- }
- Lsym*
- enter(char *name, int t)
- {
- Lsym *s;
- uint h;
- char *p;
- Value *v;
- h = 0;
- for(p = name; *p; p++)
- h = h*3 + *p;
- h %= Hashsize;
- s = gmalloc(sizeof(Lsym));
- memset(s, 0, sizeof(Lsym));
- s->name = strdup(name);
- s->hash = hash[h];
- hash[h] = s;
- s->lexval = t;
- v = gmalloc(sizeof(Value));
- s->v = v;
- v->fmt = 'X';
- v->type = TINT;
- memset(v, 0, sizeof(Value));
- return s;
- }
- Lsym*
- look(char *name)
- {
- Lsym *s;
- uint h;
- char *p;
- h = 0;
- for(p = name; *p; p++)
- h = h*3 + *p;
- h %= Hashsize;
- for(s = hash[h]; s; s = s->hash)
- if(strcmp(name, s->name) == 0)
- return s;
- return 0;
- }
- Lsym*
- mkvar(char *s)
- {
- Lsym *l;
- l = look(s);
- if(l == 0)
- l = enter(s, Tid);
- return l;
- }
|