1
0
mirror of https://github.com/golang/go synced 2024-10-04 07:11:21 -06:00
go/src/cmd/gc/lex.c

1330 lines
21 KiB
C
Raw Normal View History

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#define EXTERN
#include "go.h"
#include "y.tab.h"
#include <ar.h>
#define DBG if(!debug['x']);else print
enum
{
EOF = -1,
};
int
main(int argc, char *argv[])
{
int c;
outfile = nil;
package = "____";
ARGBEGIN {
default:
c = ARGC();
if(c >= 0 && c < sizeof(debug))
debug[c]++;
break;
case 'o':
outfile = ARGF();
break;
case 'k':
package = ARGF();
break;
case 'I':
addidir(ARGF());
break;
} ARGEND
if(argc != 1)
goto usage;
pathname = mal(100);
if(getwd(pathname, 99) == 0)
strcpy(pathname, "/???");
fmtinstall('O', Oconv); // node opcodes
fmtinstall('E', Econv); // etype opcodes
fmtinstall('J', Jconv); // all the node flags
fmtinstall('S', Sconv); // sym pointer
fmtinstall('T', Tconv); // type pointer
fmtinstall('N', Nconv); // node pointer
fmtinstall('Z', Zconv); // escaped string
fmtinstall('L', Lconv); // line number
fmtinstall('B', Bconv); // big numbers
fmtinstall('F', Fconv); // big float numbers
betypeinit();
if(maxround == 0 || widthptr == 0)
fatal("betypeinit failed");
lexinit();
typeinit(LBASETYPE);
lineno = 1;
block = 1;
blockgen = 1;
setfilename(argv[0]);
2008-06-05 20:38:39 -06:00
infile = argv[0];
linehist(infile, 0, 0);
curio.infile = infile;
curio.bin = Bopen(infile, OREAD);
if(curio.bin == nil)
fatal("cant open: %s", infile);
curio.peekc = 0;
curio.peekc1 = 0;
externdcl = mal(sizeof(*externdcl));
externdcl->back = externdcl;
dclcontext = PEXTERN;
exportlist = mal(sizeof(*exportlist));
exportlist->back = exportlist;
typelist = mal(sizeof(*typelist));
typelist->back = typelist;
// function field skeleton
fskel = nod(OLIST, N, nod(OLIST, N, N));
fskel->left = nod(ODCLFIELD, N, N);
fskel->right->left = nod(ODCLFIELD, N, N);
fskel->right->right = nod(ODCLFIELD, N, N);
nerrors = 0;
yyparse();
runifacechecks();
linehist(nil, 0, 0);
2008-07-05 18:43:25 -06:00
if(curio.bin != nil)
Bterm(curio.bin);
if(nerrors)
errorexit();
dumpobj();
if(nerrors)
errorexit();
exit(0);
return 0;
usage:
print("flags:\n");
print(" -I DIR search for packages in DIR\n");
print(" -d print declarations\n");
print(" -e no limit on number of errors printed\n");
print(" -f print stack frame structure\n");
print(" -h panic on an error\n");
print(" -k name specify package name\n");
print(" -o file specify output file\n");
print(" -p print the assembly language\n");
print(" -w print the parse tree after typing\n");
print(" -x print lex tokens\n");
exit(0);
return 0;
}
void
setfilename(char *file)
{
char *p;
int c;
p = strrchr(file, '/');
if(p != nil)
file = p+1;
strncpy(namebuf, file, sizeof(namebuf));
p = strrchr(namebuf, '.');
if(p != nil && strcmp(p, ".go") == 0)
*p = 0;
filename = strdup(namebuf);
// turn invalid identifier chars into _
for(p=filename; *p; p++) {
c = *p & 0xFF;
if(c < 0x80 && !isalpha(c) && !isdigit(c) && c != '_')
*p = '_';
}
}
int
arsize(Biobuf *b, char *name)
{
struct ar_hdr *a;
if((a = Brdline(b, '\n')) == nil)
return -1;
if(Blinelen(b) != sizeof(struct ar_hdr))
return -1;
if(strncmp(a->name, name, strlen(name)) != 0)
return -1;
return atoi(a->size);
}
int
skiptopkgdef(Biobuf *b)
{
char *p;
int sz;
/* archive header */
if((p = Brdline(b, '\n')) == nil)
return 0;
if(Blinelen(b) != 8)
return 0;
if(memcmp(p, "!<arch>\n", 8) != 0)
return 0;
/* symbol table is first; skip it */
sz = arsize(b, "__.SYMDEF");
if(sz < 0)
return 0;
Bseek(b, sz, 1);
/* package export block is second */
sz = arsize(b, "__.PKGDEF");
if(sz <= 0)
return 0;
return 1;
}
void
addidir(char* dir)
{
Idir** pp;
if(dir == nil)
return;
for(pp = &idirs; *pp != nil; pp = &(*pp)->link)
;
*pp = mal(sizeof(Idir));
(*pp)->link = nil;
(*pp)->dir = dir;
}
int
findpkg(Strlit *name)
{
static char* goroot;
Idir* p;
if(goroot == nil) {
goroot = getenv("GOROOT");
}
// try .a before .6. important for building libraries:
// if there is an array.6 in the array.a library,
// want to find all of array.a, not just array.6.
for(p = idirs; p != nil; p = p->link) {
snprint(namebuf, sizeof(namebuf), "%s/%Z.a", p->dir, name);
if(access(namebuf, 0) >= 0)
return 1;
snprint(namebuf, sizeof(namebuf), "%s/%Z.%c", p->dir, name, thechar);
if(access(namebuf, 0) >= 0)
return 1;
}
snprint(namebuf, sizeof(namebuf), "%Z.a", name);
if(access(namebuf, 0) >= 0)
return 1;
snprint(namebuf, sizeof(namebuf), "%Z.%c", name, thechar);
if(access(namebuf, 0) >= 0)
return 1;
if(goroot != nil) {
snprint(namebuf, sizeof(namebuf), "%s/pkg/%Z.a", goroot, name);
if(access(namebuf, 0) >= 0)
return 1;
snprint(namebuf, sizeof(namebuf), "%s/pkg/%Z.%c", goroot, name, thechar);
if(access(namebuf, 0) >= 0)
return 1;
}
return 0;
}
void
importfile(Val *f)
{
Biobuf *imp;
char *file, *p;
int32 c;
int len;
if(f->ctype != CTSTR) {
yyerror("import statement not a string");
return;
}
if(strcmp(f->u.sval->s, "unsafe") == 0) {
cannedimports("unsafe.6", unsafeimport);
return;
}
if(strcmp(f->u.sval->s, "runtime") == 0) {
cannedimports("runtime.6", runtimeimport);
return;
}
if(!findpkg(f->u.sval))
fatal("can't find import: %Z", f->u.sval);
imp = Bopen(namebuf, OREAD);
if(imp == nil)
fatal("can't open import: %Z", f->u.sval);
file = strdup(namebuf);
len = strlen(namebuf);
if(len > 2 && namebuf[len-2] == '.' && namebuf[len-1] == 'a') {
if(!skiptopkgdef(imp))
fatal("import not package file: %s", namebuf);
// assume .a files move (get installed)
// so don't record the full path.
p = file + len - f->u.sval->len - 2;
linehist(p, 0, 0);
linehist(p, -1, 1); // acts as #pragma lib
} else {
// assume .6 files don't move around
// so do record the full path
linehist(file, 0, 0);
linehist(file, -1, 0);
}
/*
* position the input right
* after $$ and return
*/
pushedio = curio;
curio.bin = imp;
curio.peekc = 0;
curio.peekc1 = 0;
curio.infile = file;
for(;;) {
c = getc();
if(c == EOF)
break;
if(c != '$')
continue;
c = getc();
if(c == EOF)
break;
if(c != '$')
continue;
return;
}
yyerror("no import in: %Z", f->u.sval);
unimportfile();
}
void
unimportfile(void)
{
linehist(nil, 0, 0);
if(curio.bin != nil) {
Bterm(curio.bin);
curio.bin = nil;
2008-06-28 18:27:39 -06:00
} else
lineno--; // re correct sys.6 line number
curio = pushedio;
pushedio.bin = nil;
2008-06-11 22:06:26 -06:00
inimportsys = 0;
}
void
cannedimports(char *file, char *cp)
{
2008-06-28 18:27:39 -06:00
lineno++; // if sys.6 is included on line 1,
linehist(file, 0, 0); // the debugger gets confused
pushedio = curio;
curio.bin = nil;
curio.peekc = 0;
curio.peekc1 = 0;
curio.infile = file;
curio.cp = cp;
pkgmyname = S;
2008-06-11 22:06:26 -06:00
inimportsys = 1;
}
int
isfrog(int c)
{
// complain about possibly invisible control characters
if(c < 0)
return 1;
if(c < ' ') {
if(c == '\n' || c== '\r' || c == '\t') // good white space
return 0;
return 1;
}
if(0x80 <= c && c <= 0xa0) // unicode block including unbreakable space.
return 1;
return 0;
}
int32
yylex(void)
{
int c, c1, clen;
2008-06-06 20:16:18 -06:00
vlong v;
char *cp;
Rune rune;
2008-06-08 20:02:27 -06:00
int escflag;
Sym *s;
prevlineno = lineno;
l0:
c = getc();
if(isspace(c))
goto l0;
if(c >= Runeself) {
/* all multibyte runes are alpha */
cp = lexbuf;
goto talph;
}
if(isalpha(c)) {
cp = lexbuf;
goto talph;
}
if(isdigit(c))
goto tnum;
switch(c) {
case EOF:
ungetc(EOF);
return -1;
case '_':
cp = lexbuf;
goto talph;
case '.':
c1 = getc();
if(isdigit(c1)) {
cp = lexbuf;
*cp++ = c;
c = c1;
c1 = 0;
goto casedot;
}
if(c1 == '.') {
c1 = getc();
if(c1 == '.') {
c = LDDD;
goto lx;
}
ungetc(c1);
c1 = '.';
}
break;
case '"':
/* "..." */
strcpy(lexbuf, "\"<string>\"");
cp = mal(sizeof(int32));
clen = sizeof(int32);
caseq:
for(;;) {
2008-06-08 20:02:27 -06:00
if(escchar('"', &escflag, &v))
break;
2008-06-09 14:16:50 -06:00
if(v < Runeself || escflag) {
cp = remal(cp, clen, 1);
cp[clen++] = v;
2008-06-08 20:02:27 -06:00
} else {
2008-06-06 20:16:18 -06:00
// botch - this limits size of runes
rune = v;
c = runelen(rune);
cp = remal(cp, clen, c);
runetochar(cp+clen, &rune);
clen += c;
}
}
goto catem;
case '`':
/* `...` */
strcpy(lexbuf, "`<string>`");
cp = mal(sizeof(int32));
clen = sizeof(int32);
casebq:
for(;;) {
c = getc();
if(c == EOF || c == '`')
break;
cp = remal(cp, clen, 1);
cp[clen++] = c;
}
goto catem;
catem:
c = getc();
if(isspace(c))
goto catem;
// skip comments
if(c == '/') {
c1 = getc();
if(c1 == '*') {
for(;;) {
c = getr();
while(c == '*') {
c = getr();
if(c == '/')
goto catem;
}
if(c == EOF) {
yyerror("eof in comment");
errorexit();
}
}
}
if(c1 == '/') {
for(;;) {
c = getr();
if(c == '\n')
goto catem;
if(c == EOF) {
yyerror("eof in comment");
errorexit();
}
}
}
ungetc(c1);
}
// cat adjacent strings
if(c == '"')
goto caseq;
if(c == '`')
goto casebq;
ungetc(c);
*(int32*)cp = clen-sizeof(int32); // length
do {
cp = remal(cp, clen, 1);
cp[clen++] = 0;
} while(clen & MAXALIGN);
yylval.val.u.sval = (Strlit*)cp;
yylval.val.ctype = CTSTR;
DBG("lex: string literal\n");
return LLITERAL;
case '\'':
/* '.' */
2008-06-08 20:02:27 -06:00
if(escchar('\'', &escflag, &v))
2008-06-06 20:16:18 -06:00
v = '\''; // allow '''
2008-06-08 20:02:27 -06:00
if(!escchar('\'', &escflag, &v)) {
yyerror("missing '");
2008-06-06 20:16:18 -06:00
ungetc(v);
}
yylval.val.u.xval = mal(sizeof(*yylval.val.u.xval));
mpmovecfix(yylval.val.u.xval, v);
yylval.val.ctype = CTINT;
DBG("lex: codepoint literal\n");
return LLITERAL;
case '/':
c1 = getc();
if(c1 == '*') {
for(;;) {
c = getr();
while(c == '*') {
c = getr();
if(c == '/')
goto l0;
}
if(c == EOF) {
yyerror("eof in comment");
errorexit();
}
}
}
if(c1 == '/') {
for(;;) {
c = getr();
if(c == '\n')
goto l0;
if(c == EOF) {
yyerror("eof in comment");
errorexit();
}
}
}
if(c1 == '=') {
c = ODIV;
goto asop;
}
break;
case ':':
c1 = getc();
if(c1 == '=') {
c = LCOLAS;
goto lx;
}
break;
case '*':
c1 = getc();
if(c1 == '=') {
c = OMUL;
goto asop;
}
break;
case '%':
c1 = getc();
if(c1 == '=') {
c = OMOD;
goto asop;
}
break;
case '+':
c1 = getc();
if(c1 == '+') {
c = LINC;
goto lx;
}
if(c1 == '=') {
c = OADD;
goto asop;
}
break;
case '-':
c1 = getc();
if(c1 == '-') {
c = LDEC;
goto lx;
}
if(c1 == '=') {
c = OSUB;
goto asop;
}
break;
case '>':
c1 = getc();
if(c1 == '>') {
c = LRSH;
c1 = getc();
if(c1 == '=') {
c = ORSH;
goto asop;
}
break;
}
if(c1 == '=') {
c = LGE;
goto lx;
}
c = LGT;
break;
case '<':
c1 = getc();
if(c1 == '<') {
c = LLSH;
c1 = getc();
if(c1 == '=') {
c = OLSH;
goto asop;
}
break;
}
if(c1 == '=') {
c = LLE;
goto lx;
}
2008-07-15 22:07:59 -06:00
if(c1 == '-') {
c = LCOMM;
2008-07-15 22:07:59 -06:00
goto lx;
}
c = LLT;
break;
case '=':
c1 = getc();
if(c1 == '=') {
c = LEQ;
goto lx;
}
break;
case '!':
c1 = getc();
if(c1 == '=') {
c = LNE;
goto lx;
}
break;
case '&':
c1 = getc();
if(c1 == '&') {
c = LANDAND;
goto lx;
}
if(c1 == '^') {
c = LANDNOT;
c1 = getc();
if(c1 == '=') {
c = OANDNOT;
goto asop;
}
break;
}
if(c1 == '=') {
c = OAND;
goto asop;
}
break;
case '|':
c1 = getc();
if(c1 == '|') {
c = LOROR;
goto lx;
}
if(c1 == '=') {
c = OOR;
goto asop;
}
break;
case '^':
c1 = getc();
if(c1 == '=') {
c = OXOR;
goto asop;
}
break;
default:
goto lx;
}
ungetc(c1);
lx:
if(c > 0xff)
DBG("%L lex: TOKEN %s\n", lineno, lexname(c));
else
DBG("%L lex: TOKEN '%c'\n", lineno, c);
if(isfrog(c)) {
yyerror("illegal character 0x%ux", c);
goto l0;
}
return c;
asop:
yylval.lint = c; // rathole to hold which asop
DBG("lex: TOKEN ASOP %c\n", c);
return LASOP;
talph:
/*
* cp is set to lexbuf and some
* prefix has been stored
*/
for(;;) {
if(c >= Runeself) {
for(c1=0;;) {
cp[c1++] = c;
if(fullrune(cp, c1)) {
chartorune(&rune, cp);
if(isfrog(rune)) {
yyerror("illegal character 0x%ux", rune);
goto l0;
}
break;
}
c = getc();
}
cp += c1;
c = getc();
continue;
}
if(!isalnum(c) && c != '_')
break;
*cp++ = c;
c = getc();
}
*cp = 0;
ungetc(c);
s = lookup(lexbuf);
if(s->lexical == LIGNORE)
goto l0;
if(context != nil) {
s = pkglookup(s->name, context);
if(s->lexical == LIGNORE)
goto l0;
if(!exportname(s->name) && strcmp(package, s->opackage) != 0)
s = pkglookup(s->name, ".private");
}
DBG("lex: %S %s\n", s, lexname(s->lexical));
yylval.sym = s;
if(s->lexical == LBASETYPE)
return LATYPE;
return s->lexical;
tnum:
c1 = 0;
cp = lexbuf;
if(c != '0') {
for(;;) {
*cp++ = c;
c = getc();
if(isdigit(c))
continue;
goto dc;
}
}
*cp++ = c;
c = getc();
if(c == 'x' || c == 'X') {
for(;;) {
*cp++ = c;
c = getc();
if(isdigit(c))
continue;
if(c >= 'a' && c <= 'f')
continue;
if(c >= 'A' && c <= 'F')
continue;
if(cp == lexbuf+2)
yyerror("malformed hex constant");
goto ncu;
}
}
c1 = 0;
for(;;) {
if(!isdigit(c))
break;
if(c < '0' || c > '7')
c1 = 1; // not octal
*cp++ = c;
c = getc();
}
if(c == '.')
goto casedot;
if(c == 'e' || c == 'E')
goto casee;
if(c1)
yyerror("malformed octal constant");
goto ncu;
dc:
if(c == '.')
goto casedot;
if(c == 'e' || c == 'E')
goto casee;
if(c == 'p' || c == 'P')
goto casep;
ncu:
*cp = 0;
ungetc(c);
yylval.val.u.xval = mal(sizeof(*yylval.val.u.xval));
mpatofix(yylval.val.u.xval, lexbuf);
if(yylval.val.u.xval->ovf) {
yyerror("overflow in constant");
mpmovecfix(yylval.val.u.xval, 0);
}
yylval.val.ctype = CTINT;
DBG("lex: integer literal\n");
return LLITERAL;
casedot:
for(;;) {
*cp++ = c;
c = getc();
if(!isdigit(c))
break;
}
if(c != 'e' && c != 'E')
goto caseout;
casee:
*cp++ = 'e';
c = getc();
if(c == '+' || c == '-') {
*cp++ = c;
c = getc();
}
if(!isdigit(c))
yyerror("malformed fp constant exponent");
while(isdigit(c)) {
*cp++ = c;
c = getc();
}
goto caseout;
casep:
*cp++ = 'p';
c = getc();
if(c == '+' || c == '-') {
*cp++ = c;
c = getc();
}
if(!isdigit(c))
yyerror("malformed fp constant exponent");
while(isdigit(c)) {
*cp++ = c;
c = getc();
}
goto caseout;
caseout:
*cp = 0;
ungetc(c);
yylval.val.u.fval = mal(sizeof(*yylval.val.u.fval));
mpatoflt(yylval.val.u.fval, lexbuf);
if(yylval.val.u.fval->val.ovf) {
yyerror("overflow in float constant");
mpmovecflt(yylval.val.u.fval, 0.0);
}
yylval.val.ctype = CTFLT;
DBG("lex: floating literal\n");
return LLITERAL;
}
int
getc(void)
{
int c;
c = curio.peekc;
if(c != 0) {
curio.peekc = curio.peekc1;
curio.peekc1 = 0;
if(c == '\n')
lineno++;
return c;
}
if(curio.bin == nil) {
c = *curio.cp & 0xff;
if(c != 0)
curio.cp++;
} else
c = Bgetc(curio.bin);
switch(c) {
case 0:
if(curio.bin != nil)
break;
case EOF:
return EOF;
case '\n':
lineno++;
break;
}
return c;
}
void
ungetc(int c)
{
curio.peekc1 = curio.peekc;
curio.peekc = c;
if(c == '\n')
lineno--;
}
int32
getr(void)
{
int c, i;
char str[UTFmax+1];
Rune rune;
c = getc();
if(c < Runeself)
return c;
i = 0;
str[i++] = c;
loop:
c = getc();
str[i++] = c;
if(!fullrune(str, i))
goto loop;
c = chartorune(&rune, str);
if(rune == Runeerror && c == 1) {
yyerror("illegal rune in string");
for(c=0; c<i; c++)
print(" %.2x", *(uchar*)(str+c));
print("\n");
}
return rune;
}
int
getnsc(void)
{
int c;
c = getc();
for(;;) {
if(!isspace(c))
return c;
if(c == '\n') {
lineno++;
return c;
}
c = getc();
}
return 0;
}
2008-06-06 20:16:18 -06:00
int
2008-06-08 20:02:27 -06:00
escchar(int e, int *escflg, vlong *val)
{
2008-06-08 20:02:27 -06:00
int i, c;
2008-06-06 20:16:18 -06:00
vlong l;
2008-06-08 20:02:27 -06:00
*escflg = 0;
loop:
c = getr();
if(c == '\n') {
yyerror("newline in string");
2008-06-06 20:16:18 -06:00
return 1;
}
if(c != '\\') {
if(c == e)
2008-06-06 20:16:18 -06:00
return 1;
*val = c;
return 0;
}
2008-06-06 20:16:18 -06:00
c = getr();
switch(c) {
case '\n':
goto loop;
case 'x':
2008-06-08 20:02:27 -06:00
*escflg = 1; // it's a byte
i = 2;
goto hex;
case 'u':
i = 4;
goto hex;
case 'U':
i = 8;
goto hex;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
2008-06-08 20:02:27 -06:00
*escflg = 1; // it's a byte
goto oct;
2008-06-06 20:16:18 -06:00
case 'a': c = '\a'; break;
case 'b': c = '\b'; break;
case 'f': c = '\f'; break;
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
case 'v': c = '\v'; break;
case '\\': c = '\\'; break;
default:
if(c != e)
yyerror("unknown escape sequence: %c", c);
}
2008-06-06 20:16:18 -06:00
*val = c;
return 0;
hex:
l = 0;
for(; i>0; i--) {
c = getc();
if(c >= '0' && c <= '9') {
l = l*16 + c-'0';
continue;
}
if(c >= 'a' && c <= 'f') {
l = l*16 + c-'a' + 10;
continue;
}
if(c >= 'A' && c <= 'F') {
l = l*16 + c-'A' + 10;
continue;
}
yyerror("non-hex character in escape sequence: %c", c);
ungetc(c);
break;
}
2008-06-06 20:16:18 -06:00
*val = l;
return 0;
oct:
l = c - '0';
for(i=2; i>0; i--) {
c = getc();
if(c >= '0' && c <= '7') {
l = l*8 + c-'0';
continue;
}
yyerror("non-oct character in escape sequence: %c", c);
ungetc(c);
}
if(l > 255)
yyerror("oct escape value > 255: %d", l);
2008-06-08 20:02:27 -06:00
2008-06-06 20:16:18 -06:00
*val = l;
return 0;
}
static struct
{
char* name;
int lexical;
int etype;
} syms[] =
{
/* name lexical etype
*/
/* basic types */
"int8", LBASETYPE, TINT8,
"int16", LBASETYPE, TINT16,
"int32", LBASETYPE, TINT32,
"int64", LBASETYPE, TINT64,
"uint8", LBASETYPE, TUINT8,
"uint16", LBASETYPE, TUINT16,
"uint32", LBASETYPE, TUINT32,
"uint64", LBASETYPE, TUINT64,
"float32", LBASETYPE, TFLOAT32,
"float64", LBASETYPE, TFLOAT64,
"float80", LBASETYPE, TFLOAT80,
"bool", LBASETYPE, TBOOL,
"byte", LBASETYPE, TUINT8,
"string", LBASETYPE, TSTRING,
"any", LBASETYPE, TANY,
"sys", LPACK, Txxx,
"break", LBREAK, Txxx,
"case", LCASE, Txxx,
"chan", LCHAN, Txxx,
"const", LCONST, Txxx,
"continue", LCONTINUE, Txxx,
"default", LDEFAULT, Txxx,
"else", LELSE, Txxx,
2009-01-27 13:03:53 -07:00
"defer", LDEFER, Txxx,
"fallthrough", LFALL, Txxx,
2008-08-12 17:36:18 -06:00
"false", LFALSE, Txxx,
"for", LFOR, Txxx,
"func", LFUNC, Txxx,
"go", LGO, Txxx,
"goto", LGOTO, Txxx,
"if", LIF, Txxx,
"import", LIMPORT, Txxx,
"interface", LINTERFACE, Txxx,
"iota", LIOTA, Txxx,
"make", LMAKE, Txxx,
"map", LMAP, Txxx,
2008-08-12 17:36:18 -06:00
"new", LNEW, Txxx,
"len", LLEN, Txxx,
2008-08-27 18:28:30 -06:00
"cap", LCAP, Txxx,
2008-08-12 17:36:18 -06:00
"nil", LNIL, Txxx,
"package", LPACKAGE, Txxx,
2008-08-12 17:36:18 -06:00
"panic", LPANIC, Txxx,
"panicln", LPANICN, Txxx,
2008-08-12 17:36:18 -06:00
"print", LPRINT, Txxx,
"println", LPRINTN, Txxx,
"range", LRANGE, Txxx,
"return", LRETURN, Txxx,
"select", LSELECT, Txxx,
"struct", LSTRUCT, Txxx,
"switch", LSWITCH, Txxx,
2008-08-12 17:36:18 -06:00
"true", LTRUE, Txxx,
"type", LTYPE, Txxx,
"var", LVAR, Txxx,
"close", LCLOSE, Txxx,
"closed", LCLOSED, Txxx,
"notwithstanding", LIGNORE, Txxx,
"thetruthofthematter", LIGNORE, Txxx,
"despiteallobjections", LIGNORE, Txxx,
"whereas", LIGNORE, Txxx,
"insofaras", LIGNORE, Txxx,
};
void
lexinit(void)
{
int i, lex;
Sym *s;
Type *t;
int etype;
/*
* initialize basic types array
* initialize known symbols
*/
for(i=0; i<nelem(syms); i++) {
lex = syms[i].lexical;
s = lookup(syms[i].name);
s->lexical = lex;
if(lex != LBASETYPE)
continue;
etype = syms[i].etype;
if(etype < 0 || etype >= nelem(types))
fatal("lexinit: %s bad etype", s->name);
t = types[etype];
if(t != T) {
s->otype = t;
continue;
}
t = typ(etype);
t->sym = s;
dowidth(t);
types[etype] = t;
s->otype = t;
}
}
struct
{
int lex;
char* name;
} lexn[] =
{
LANDAND, "ANDAND",
LASOP, "ASOP",
LACONST, "ACONST",
LATYPE, "ATYPE",
LBASETYPE, "BASETYPE",
LBREAK, "BREAK",
LCASE, "CASE",
LCHAN, "CHAN",
LCOLAS, "COLAS",
LCONST, "CONST",
LCONTINUE, "CONTINUE",
LDEC, "DEC",
LELSE, "ELSE",
LEQ, "EQ",
LFUNC, "FUNC",
LGE, "GE",
LGO, "GO",
LGOTO, "GOTO",
LGT, "GT",
LIF, "IF",
LINC, "INC",
LINTERFACE, "INTERFACE",
LLE, "LE",
LLITERAL, "LITERAL",
LLSH, "LSH",
LLT, "LT",
LMAP, "MAP",
LNAME, "NAME",
LNE, "NE",
LOROR, "OROR",
LPACK, "PACK",
LRANGE, "RANGE",
LRETURN, "RETURN",
LRSH, "RSH",
LSTRUCT, "STRUCT",
LSWITCH, "SWITCH",
LTYPE, "TYPE",
LVAR, "VAR",
LFOR, "FOR",
LNEW, "NEW",
LLEN, "LEN",
LFALL, "FALL",
LIOTA, "IOTA",
LPRINT, "PRINT",
LPACKAGE, "PACKAGE",
LIMPORT, "IMPORT",
2009-01-27 13:03:53 -07:00
LDEFER, "DEFER",
LPANIC, "PANIC",
};
char*
lexname(int lex)
{
int i;
static char buf[100];
for(i=0; i<nelem(lexn); i++)
if(lexn[i].lex == lex)
return lexn[i].name;
snprint(buf, sizeof(buf), "LEX-%d", lex);
return buf;
}
void
mkpackage(char* pkg)
{
Sym *s;
int32 h;
2008-06-05 20:38:39 -06:00
char *p;
if(bout != nil) {
yyerror("mkpackage: called again %s %s", pkg, package);
return;
}
// redefine all names to be this package
package = pkg;
for(h=0; h<NHASH; h++)
for(s = hash[h]; s != S; s = s->link) {
s->package = package;
s->opackage = package;
}
2009-03-05 16:57:03 -07:00
// declare this name as a package
lookup(package)->lexical = LPACK;
if(outfile == nil) {
2008-06-05 20:38:39 -06:00
p = strrchr(infile, '/');
if(p == nil)
p = infile;
else
p = p+1;
snprint(namebuf, sizeof(namebuf), "%s", p);
p = strrchr(namebuf, '.');
if(p != nil)
*p = 0;
outfile = smprint("%s.%c", namebuf, thechar);
}
}