1331 lines · 28.0 KB · Text
RawDownload
%{#define YYERROR_VERBOSE#define YYDEBUG 1 #include <stdlib.h>#include <stdio.h>#include <stdarg.h>#include <inttypes.h>#include <ctype.h>#include <string.h>#include <assert.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h> #include "util.h"#include "parse.h"  #define LBLSTKSZ 64static Node **lbls[LBLSTKSZ];static size_t nlbls[LBLSTKSZ];Stab *curscope; /* the first time we see a label, we increment to 0 */static int lbldepth = -1; void yyerror(const char *s);int yylex(void); static Op binop(int);static Node *mkpseudodecl(Srcloc, Type *);static void installucons(Stab *, Type *);static void setattrs(Node *, char **attrs, size_t);static void setwith(Type *, Traitspec **, size_t);static void mergeenv(Node *, Node *);static void mangleautocall(Node *, char *);static void addinit(Node *, Node *);static void setuname(Type *); %} %token<tok> Tplus	/* + */%token<tok> Tminus	/* - */%token<tok> Tmul	/* * */%token<tok> Tdiv	/* / */%token<tok> Tinc	/* ++ */%token<tok> Tdec	/* -- */%token<tok> Tmod	/* % */%token<tok> Tasn	/* = */%token<tok> Taddeq	/* += */%token<tok> Tsubeq	/* -= */%token<tok> Tmuleq	/* *= */%token<tok> Tdiveq	/* /= */%token<tok> Tmodeq	/* %= */%token<tok> Tboreq	/* |= */%token<tok> Tbxoreq	/* ^= */%token<tok> Tbandeq	/* &= */%token<tok> Tbsleq	/* <<= */%token<tok> Tbsreq	/* >>= */ %token<tok> Tbor	/* | */%token<tok> Tbxor	/* ^ */%token<tok> Tband	/* & */%token<tok> Tbsl	/* << */%token<tok> Tbsr	/* >> */%token<tok> Tbnot	/* ~ */ %token<tok> Teq		/* == */%token<tok> Tgt		/* > */%token<tok> Tlt		/* < */%token<tok> Tge		/* >= */%token<tok> Tle		/* <= */%token<tok> Tne		/* != */ %token<tok> Tlor	/* || */%token<tok> Tland	/* && */%token<tok> Tlnot	/* ! */ %token<tok> Tobrace	/* { */%token<tok> Tcbrace	/* } */%token<tok> Toparen	/* ( */%token<tok> Tcparen	/* ) */%token<tok> Tosqbrac	/* [ */%token<tok> Tcsqbrac	/* ] */%token<tok> Ttick	/* ` */%token<tok> Tderef	/* # */%token<tok> Tqmark	/* ? */ %token<tok> Ttype	/* type */%token<tok> Tfor	/* for */%token<tok> Twhile	/* while */%token<tok> Tif		/* if */%token<tok> Telse	/* else */%token<tok> Telif	/* else */%token<tok> Tmatch	/* match */%token<tok> Tgoto	/* goto */%token<tok> Tbreak	/* break */%token<tok> Tcontinue	/* continue */%token<tok> Tauto	/* auto */ %token<tok> Tintlit%token<tok> Tstrlit%token<tok> Tfloatlit%token<tok> Tchrlit%token<tok> Tboollit%token<tok> Tvoidlit %token<tok> Ttrait	/* trait */%token<tok> Timpl	/* trait */%token<tok> Tstruct	/* struct */%token<tok> Tunion	/* union */%token<tok> Ttyparam	/* @typename */ %token<tok> Tconst	/* const */%token<tok> Tvar	/* var */%token<tok> Tgeneric	/* generic */ %token<tok> Tgap	/* _ */%token<tok> Tellipsis	/* ... */%token<tok> Tendln	/* ; or \n */%token<tok> Tendblk	/* ;; */%token<tok> Tcolon	/* : */%token<tok> Twith	/* :: */%token<tok> Tdot	/* . */%token<tok> Tcomma	/* , */%token<tok> Tret	/* -> */%token<tok> Tuse	/* use */%token<tok> Tpkg	/* pkg */%token<tok> Tattr	/* $attr */%token<tok> Tsizeof	/* sizeof */ %token<tok> Tident %start file %type <ty> type structdef uniondef tupledef compoundtype functype funcsig%type <ty> generictype%type <tylist> typelist typarams optauxtypes%type <traitspecs> traitspec traits%type <traitspec> traitvar%type <nodelist> traitlist %type <tok> asnop cmpop addop mulop shiftop optident obrace %type <tydef> tydef pkgtydef typeid%type <trait> traitdef %type<node> exprln retexpr goto continue break expr atomicexpr%type<node> littok literal lorexpr landexpr borexpr strlit bandexpr%type<node> cmpexpr addexpr mulexpr shiftexpr prefixexpr ternexpr%type<node> postfixexpr funclit seqlit tuplit name block stmt label%type<node> use fnparam declbody declcore typedeclcore structent%type<node> arrayelt structelt tuphead ifstmt forstmt whilestmt%type<node> matchstmt elifs optexprln loopcond optexpr match %type <ucon> unionelt%type <node> blkbody%type <node> implstmt %type <nodelist> arglist argdefs params matches%type <nodelist> structbody structelts arrayelts%type <nodelist> tupbody tuprest%type <nodelist> decl decllist%type <nodelist> traitbody implbody%type <strlist> attrs %type <uconlist> unionbody /*We want to bind more tightly to `Foo unaryexprthan to binary operators around it. Eg: 	`Foo +bar should be interpreted as 	(`Foo (+bar)) and not 	(`Foo) + (bar) The default action of shifting does the right thing,but warnings suck.*/%left Ttick%left Tplus Tminus Tband %union {	struct {		Srcloc loc;		Node **nl;		size_t nn;	} nodelist;	struct {		char **str;		size_t nstr;	} strlist;	struct {		Srcloc loc;		Ucon **ucl;		size_t nucl;	} uconlist;	struct {		Srcloc loc;		Type **types;		size_t ntypes;	} tylist;	struct { /* FIXME: unused */		Srcloc loc;		char *name;		Type *type;		Type **params;		size_t nparams;	} tydef;	struct {		Traitspec **spec;		size_t nspec;	} traitspecs;	Traitspec *traitspec;	Trait *trait;	Node *node;	Tok  *tok;	Type *ty;	Ucon *ucon;} %% file	: toplev	| file Tendln toplev	; toplev	: package	| use {lappend(&file.uses, &file.nuses, $1);}	| implstmt {		lappend(&file.stmts, &file.nstmts, $1);	}	| traitdef {		size_t i;		puttrait(file.globls, $1->name, $1);		for (i = 0; i < $1->nproto; i++)			putdcl(file.globls, $1->proto[i]);	}	| tydef {		puttype(file.globls, mkname($1.loc, $1.name), $1.type);		installucons(file.globls, $1.type);	}	| decl {		size_t i;		Node *n, *d; 		for (i = 0; i < $1.nn; i++) {			d = $1.nl[i];			/* putdcl can merge, so we need to getdcl after */			mangleautocall(d, declname(d));			putdcl(file.globls, d);			n = getdcl(file.globls, d->decl.name);			lappend(&file.stmts, &file.nstmts, n);			d->decl.isglobl = 1;			if (d->decl.isinit)				file.localinit = d;			if (d->decl.isfini)				file.localfini = d;		}	}	| /* empty */	; decl	: attrs Tvar decllist traitspec {		size_t i; 		for (i = 0; i < $3.nn; i++)			setattrs($3.nl[i], $1.str, $1.nstr);		$$ = $3;	}	| attrs Tconst decllist traitspec {		size_t i;		for (i = 0; i < $3.nn; i++) {			setattrs($3.nl[i], $1.str, $1.nstr);			$3.nl[i]->decl.isconst = 1;		}		$$ = $3;	}	| attrs Tgeneric decllist traitspec {		size_t i; 		for (i = 0; i < $3.nn; i++) {			setattrs($3.nl[i], $1.str, $1.nstr);			setwith($3.nl[i]->decl.type, $4.spec, $4.nspec);			$3.nl[i]->decl.isconst = 1;			$3.nl[i]->decl.isgeneric = 1;		}		$$ = $3;	}        ; attrs	: /* empty */ {$$.nstr = 0; $$.str = NULL;}	| Tattr attrs {		$$ = $2;		lappend(&$$.str, &$$.nstr, strdup($1->id));	}	; traitspec	: Twith traits	{$$ = $2;}	| /* nothing */ {$$.nspec = 0;}	; traits	: traitvar {       		$$.spec = NULL;       		$$.nspec = 0;		lappend(&$$.spec, &$$.nspec, $1);	}	| traits listsep traitvar {		$$ = $1;		lappend(&$$.spec, &$$.nspec, $3);	}	; traitvar	: traitlist generictype {		$$ = calloc(sizeof(Traitspec), 1);		$$->trait = $1.nl;		$$->ntrait = $1.nn;		$$->param = $2;		$$->aux = NULL;	}	| traitlist generictype Tret type {		$$ = calloc(sizeof(Traitspec), 1);		$$->trait = $1.nl;		$$->ntrait = $1.nn;		$$->param = $2;		$$->aux = $4;	}	; traitlist	: name {		$$.nl = 0;		$$.nn = 0;		lappend(&$$.nl, &$$.nn, $1);	}	| traitlist listsep name {		lappend(&$$.nl, &$$.nn, $3);	}	; decllist: declbody {		$$.loc = $1->loc; $$.nl = NULL; $$.nn = 0;		lappend(&$$.nl, &$$.nn, $1);	}	| declbody listsep decllist {		linsert(&$3.nl, &$3.nn, 0, $1);		$$=$3;	}	; use	: Tuse Tident {$$ = mkuse($1->loc, $2->id, 0);}	| Tuse Tstrlit {$$ = mkuse($1->loc, $2->strval.buf, 1);}	; optident: Tident      {$$ = $1;}	| /* empty */ {$$ = NULL;}	; package : Tpkg optident Tasn pkgbody Tendblk {		if (file.globls->name)			lfatal($1->loc, "Package already declared\n");		if ($2) {			updatens(file.globls, $2->id);		}	}	; pkgbody : pkgitem	| pkgbody Tendln pkgitem	; pkgitem : decl {		size_t i;		for (i = 0; i < $1.nn; i++) {			$1.nl[i]->decl.vis = Visexport;			$1.nl[i]->decl.isglobl = 1;			putdcl(file.globls, $1.nl[i]);			if ($1.nl[i]->decl.init)				lappend(&file.stmts, &file.nstmts, $1.nl[i]);		}	}	| pkgtydef {		/* the type may only be null in a package context, so we		can set the type when merging in this case. 		FIXME: clean up the fucking special cases. */		if ($1.type)			$1.type->vis = Visexport;		puttype(file.globls, mkname($1.loc, $1.name), $1.type);		installucons(file.globls, $1.type);	}	| traitdef {		size_t i;		$1->vis = Visexport;		puttrait(file.globls, $1->name, $1);		for (i = 0; i < $1->nproto; i++)			putdcl(file.globls, $1->proto[i]);	}	| implstmt {		$1->impl.vis = Visexport;		lappend(&file.stmts, &file.nstmts, $1);	}	| /* empty */	; pkgtydef: attrs tydef {		size_t i;		$$ = $2;		for (i = 0; i < $1.nstr; i++) {			if (!strcmp($1.str[i], "pkglocal"))				$$.type->ispkglocal = 1;			else				lfatal($$.loc, "invalid type attribute '%s'", $1.str[i]);		}	}	; declbody: declcore	| declcore Tasn expr {		$$ = $1;		$1->decl.init = $3;		mergeenv($1, $3);	}	; declcore: name {$$ = mkdecl($1->loc, $1, mktyvar($1->loc));}	| typedeclcore {$$ = $1;}	; typedeclcore	: name Tcolon type {$$ = mkdecl($1->loc, $1, $3);}	; name	: Tident {$$ = mkname($1->loc, $1->id);}	| Tident Tdot Tident {		$$ = mknsname($3->loc, $1->id, $3->id);	}	; implstmt	: Timpl name type optauxtypes traitspec {		size_t i; 		$$ = mkimplstmt($1->loc, $2, $3, $4.types, $4.ntypes, NULL, 0);		$$->impl.isproto = 1;		setwith($3, $5.spec, $5.nspec);		for (i = 0; i < $4.ntypes; i++)			setwith($4.types[i], $5.spec, $5.nspec);	}	| Timpl name type optauxtypes traitspec Tasn Tendln implbody Tendblk {		size_t i; 		$$ = mkimplstmt($1->loc, $2, $3, $4.types, $4.ntypes, $8.nl, $8.nn);		setwith($3, $5.spec, $5.nspec);		for (i = 0; i < $4.ntypes; i++)			setwith($4.types[i], $5.spec, $5.nspec);	}	; implbody	: optendlns {$$.nl = NULL; $$.nn = 0;}	| implbody Tident Tasn exprln optendlns {		Node *d;		$$ = $1;		d = mkdecl($2->loc, mkname($2->loc, $2->id), mktyvar($2->loc));		d->decl.init = $4;		d->decl.isconst = 1;		d->decl.isglobl = 1;		mergeenv(d, $4);		lappend(&$$.nl, &$$.nn, d);	}	; traitdef	: Ttrait Tident generictype optauxtypes traitspec { /* trait prototype */		size_t i;		$$ = mktrait($1->loc,			mkname($2->loc, $2->id), $3,			$4.types, $4.ntypes,			NULL, 0,			1);		setwith($3, $5.spec, $5.nspec);		for (i = 0; i < $4.ntypes; i++)			setwith($4.types[i], $5.spec, $5.nspec);	}	| Ttrait Tident generictype optauxtypes traitspec Tasn traitbody Tendblk /* trait definition */ {		size_t i;		$$ = mktrait($1->loc,			mkname($2->loc, $2->id), $3,			$4.types, $4.ntypes,

Lines 1–500 of 1331.