12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include <ctype.h>
- #define Bungetrune Bungetc /* ok for now. */
- /*
- * all these are 32 bit
- */
- #define TBITSET ((32+NTERMS)/32) /* BOTCH?? +31 */
- #define BIT(a,i) ((a)[(i)>>5] & (1<<((i)&037)))
- #define SETBIT(a,i) ((a)[(i)>>5] |= (1<<((i)&037)))
- #define NWORDS(n) (((n)+32)/32)
- #define PARSER "/sys/lib/yaccpar"
- #define PARSERS "/sys/lib/yaccpars"
- #define TEMPNAME "y.tmp.XXXXXX"
- #define ACTNAME "y.acts.XXXXXX"
- #define OFILE "tab.c"
- #define FILEU "output"
- #define FILED "tab.h"
- #define FILEDEBUG "debug"
- enum
- {
- /*
- * the following are adjustable
- * according to memory size
- */
- ACTSIZE = 40000,
- MEMSIZE = 40000,
- NSTATES = 2000,
- NTERMS = 511,
- NPROD = 1600,
- NNONTERM = 600,
- TEMPSIZE = 2000,
- CNAMSZ = 10000,
- LSETSIZE = 2400,
- WSETSIZE = 350,
- NAMESIZE = 50,
- NTYPES = 63,
- ISIZE = 400,
- PRIVATE = 0xE000, /* unicode private use */
- /* relationships which must hold:
- TBITSET ints must hold NTERMS+1 bits...
- WSETSIZE >= NNONTERM
- LSETSIZE >= NNONTERM
- TEMPSIZE >= NTERMS + NNONTERM + 1
- TEMPSIZE >= NSTATES
- */
- NTBASE = 010000,
- ERRCODE = 8190,
- ACCEPTCODE = 8191,
- NOASC = 0, /* no assoc. */
- LASC = 1, /* left assoc. */
- RASC = 2, /* right assoc. */
- BASC = 3, /* binary assoc. */
- /* flags for state generation */
- DONE = 0,
- MUSTDO = 1,
- MUSTLOOKAHEAD = 2,
- /* flags for a rule having an action, and being reduced */
- ACTFLAG = 04,
- REDFLAG = 010,
- /* output parser flags */
- YYFLAG1 = -1000,
- /* parse tokens */
- IDENTIFIER = PRIVATE,
- MARK,
- TERM,
- LEFT,
- RIGHT,
- BINARY,
- PREC,
- LCURLY,
- IDENTCOLON,
- NUMBER,
- START,
- TYPEDEF,
- TYPENAME,
- UNION,
- ENDFILE = 0,
- EMPTY = 1,
- WHOKNOWS = 0,
- OK = 1,
- NOMORE = -1000,
- };
- /* macros for getting associativity and precedence levels */
- #define ASSOC(i) ((i)&03)
- #define PLEVEL(i) (((i)>>4)&077)
- #define TYPE(i) (((i)>>10)&077)
- /* macros for setting associativity and precedence levels */
- #define SETASC(i,j) i |= j
- #define SETPLEV(i,j) i |= (j<<4)
- #define SETTYPE(i,j) i |= (j<<10)
- /* looping macros */
- #define TLOOP(i) for(i=1; i<=ntokens; i++)
- #define NTLOOP(i) for(i=0; i<=nnonter; i++)
- #define PLOOP(s,i) for(i=s; i<nprod; i++)
- #define SLOOP(i) for(i=0; i<nstate; i++)
- #define WSBUMP(x) x++
- #define WSLOOP(s,j) for(j=s; j<cwp; j++)
- #define ITMLOOP(i,p,q) for(q=pstate[i+1], p=pstate[i]; p<q; p++)
- #define SETLOOP(i) for(i=0; i<tbitset; i++)
- /* command to clobber tempfiles after use */
- #define ZAPFILE(x) if(x) remove(x)
- /* I/O descriptors */
- Biobuf* faction; /* file for saving actions */
- Biobuf* fdefine; /* file for #defines */
- Biobuf* fdebug; /* y.debug for strings for debugging */
- Biobuf* ftable; /* y.tab.c file */
- Biobuf* ftemp; /* tempfile to pass 2 */
- Biobuf* finput; /* input file */
- Biobuf* foutput; /* y.output file */
- /* communication variables between various I/O routines */
- char* infile; /* input file name */
- int numbval; /* value of an input number */
- char tokname[NAMESIZE+UTFmax+1]; /* input token name, slop for runes and 0 */
- /* structure declarations */
- typedef
- struct
- {
- int lset[TBITSET];
- } Lkset;
- typedef
- struct
- {
- int* pitem;
- Lkset* look;
- } Item;
- typedef
- struct
- {
- char* name;
- int value;
- } Symb;
- typedef
- struct
- {
- int* pitem;
- int flag;
- Lkset ws;
- } Wset;
- /* storage of names */
- char cnames[CNAMSZ]; /* place where token and nonterminal names are stored */
- int cnamsz = CNAMSZ; /* size of cnames */
- char* cnamp = cnames; /* place where next name is to be put in */
- int ndefout = 4; /* number of defined symbols output */
- char* tempname;
- char* actname;
- char ttempname[] = TEMPNAME;
- char tactname[] = ACTNAME;
- char* parser = PARSER;
- char* yydebug;
- /* storage of types */
- int ntypes; /* number of types defined */
- char* typeset[NTYPES]; /* pointers to type tags */
- /* token information */
- int ntokens = 0 ; /* number of tokens */
- Symb tokset[NTERMS];
- int toklev[NTERMS]; /* vector with the precedence of the terminals */
- /* nonterminal information */
- int nnonter = -1; /* the number of nonterminals */
- Symb nontrst[NNONTERM];
- int start; /* start symbol */
- /* assigned token type values */
- int extval = 0;
- char* ytabc = OFILE; /* name of y.tab.c */
- /* grammar rule information */
- int mem0[MEMSIZE] ; /* production storage */
- int* mem = mem0;
- int nprod = 1; /* number of productions */
- int* prdptr[NPROD]; /* pointers to descriptions of productions */
- int levprd[NPROD]; /* precedence levels for the productions */
- int rlines[NPROD]; /* line number for this rule */
- /* state information */
- int nstate = 0; /* number of states */
- Item* pstate[NSTATES+2]; /* pointers to the descriptions of the states */
- int tystate[NSTATES]; /* contains type information about the states */
- int defact[NSTATES]; /* the default actions of states */
- int tstates[NTERMS]; /* states generated by terminal gotos */
- int ntstates[NNONTERM]; /* states generated by nonterminal gotos */
- int mstates[NSTATES]; /* chain of overflows of term/nonterm generation lists */
- int lastred; /* the number of the last reduction of a state */
- /* lookahead set information */
- Lkset lkst[LSETSIZE];
- int nolook; /* flag to turn off lookahead computations */
- int tbitset; /* size of lookahead sets */
- int nlset = 0; /* next lookahead set index */
- int nolook = 0; /* flag to suppress lookahead computations */
- Lkset clset; /* temporary storage for lookahead computations */
- /* working set information */
- Wset wsets[WSETSIZE];
- Wset* cwp;
- /* storage for action table */
- int amem[ACTSIZE]; /* action table storage */
- int* memp = amem; /* next free action table position */
- int indgo[NSTATES]; /* index to the stored goto table */
- /* temporary vector, indexable by states, terms, or ntokens */
- int temp1[TEMPSIZE]; /* temporary storage, indexed by terms + ntokens or states */
- int lineno = 1; /* current input line number */
- int fatfl = 1; /* if on, error is fatal */
- int nerrors = 0; /* number of errors */
- /* statistics collection variables */
- int zzgoent;
- int zzgobest;
- int zzacent;
- int zzexcp;
- int zzclose;
- int zzrrconf;
- int zzsrconf;
- int* ggreed = lkst[0].lset;
- int* pgo = wsets[0].ws.lset;
- int* yypgo = &nontrst[0].value;
- int maxspr = 0; /* maximum spread of any entry */
- int maxoff = 0; /* maximum offset into a array */
- int* pmem = mem0;
- int* maxa;
- int nxdb = 0;
- int adb = 0;
- /* storage for information about the nonterminals */
- int** pres[NNONTERM+2]; /* vector of pointers to productions yielding each nonterminal */
- Lkset* pfirst[NNONTERM+2]; /* vector of pointers to first sets for each nonterminal */
- int pempty[NNONTERM+1]; /* vector of nonterminals nontrivially deriving e */
- /* random stuff picked out from between functions */
- int indebug = 0;
- Wset* zzcwp = wsets;
- int zzgoent = 0;
- int zzgobest = 0;
- int zzacent = 0;
- int zzexcp = 0;
- int zzclose = 0;
- int zzsrconf = 0;
- int* zzmemsz = mem0;
- int zzrrconf = 0;
- int pidebug = 0; /* debugging flag for putitem */
- int gsdebug = 0;
- int cldebug = 0; /* debugging flag for closure */
- int pkdebug = 0;
- int g2debug = 0;
- struct
- {
- char* name;
- long value;
- } resrv[] =
- {
- "binary", BINARY,
- "left", LEFT,
- "nonassoc", BINARY,
- "prec", PREC,
- "right", RIGHT,
- "start", START,
- "term", TERM,
- "token", TERM,
- "type", TYPEDEF,
- "union", UNION,
- 0,
- };
- /* define functions */
- void main(int, char**);
- void others(void);
- char* chcopy(char*, char*);
- char* writem(int*);
- char* symnam(int);
- void summary(void);
- void error(char*, ...);
- void aryfil(int*, int, int);
- int setunion(int*, int*);
- void prlook(Lkset*);
- void cpres(void);
- void cpfir(void);
- int state(int);
- void putitem(int*, Lkset*);
- void cempty(void);
- void stagen(void);
- void closure(int);
- Lkset* flset(Lkset*);
- void cleantmp(void);
- void intr(void);
- void setup(int, char**);
- void finact(void);
- int defin(int, char*);
- void defout(int);
- char* cstash(char*);
- long gettok(void);
- int fdtype(int);
- int chfind(int, char*);
- void cpyunion(void);
- void cpycode(void);
- int skipcom(void);
- void cpyact(int);
- void openup(char*, int, int, int, char*);
- void output(void);
- int apack(int*, int);
- void go2out(void);
- void go2gen(int);
- void precftn(int, int, int);
- void wract(int);
- void wrstate(int);
- void warray(char*, int*, int);
- void hideprod(void);
- void callopt(void);
- void gin(int);
- void stin(int);
- int nxti(void);
- void osummary(void);
- void aoutput(void);
- void arout(char*, int*, int);
- int gtnm(void);
- void
- main(int argc, char *argv[])
- {
- setup(argc, argv); /* initialize and read productions */
- tbitset = NWORDS(ntokens);
- cpres(); /* make table of which productions yield a given nonterminal */
- cempty(); /* make a table of which nonterminals can match the empty string */
- cpfir(); /* make a table of firsts of nonterminals */
- stagen(); /* generate the states */
- output(); /* write the states and the tables */
- go2out();
- hideprod();
- summary();
- callopt();
- others();
- exits(0);
- }
- /*
- * put out other arrays, copy the parsers
- */
- void
- others(void)
- {
- int c, i, j;
- finput = Bopen(parser, OREAD);
- if(finput == 0)
- error("cannot find parser %s", parser);
- warray("yyr1", levprd, nprod);
- aryfil(temp1, nprod, 0);
- PLOOP(1, i)
- temp1[i] = prdptr[i+1]-prdptr[i]-2;
- warray("yyr2", temp1, nprod);
- aryfil(temp1, nstate, -1000);
- TLOOP(i)
- for(j=tstates[i]; j!=0; j=mstates[j])
- temp1[j] = i;
- NTLOOP(i)
- for(j=ntstates[i]; j!=0; j=mstates[j])
- temp1[j] = -i;
- warray("yychk", temp1, nstate);
- warray("yydef", defact, nstate);
- /* put out token translation tables */
- /* table 1 has 0-256 */
- aryfil(temp1, 256, 0);
- c = 0;
- TLOOP(i) {
- j = tokset[i].value;
- if(j >= 0 && j < 256) {
- if(temp1[j]) {
- print("yacc bug -- cant have 2 different Ts with same value\n");
- print(" %s and %s\n", tokset[i].name, tokset[temp1[j]].name);
- nerrors++;
- }
- temp1[j] = i;
- if(j > c)
- c = j;
- }
- }
- warray("yytok1", temp1, c+1);
- /* table 2 has PRIVATE-PRIVATE+256 */
- aryfil(temp1, 256, 0);
- c = 0;
- TLOOP(i) {
- j = tokset[i].value - PRIVATE;
- if(j >= 0 && j < 256) {
- if(temp1[j]) {
- print("yacc bug -- cant have 2 different Ts with same value\n");
- print(" %s and %s\n", tokset[i].name, tokset[temp1[j]].name);
- nerrors++;
- }
- temp1[j] = i;
- if(j > c)
- c = j;
- }
- }
- warray("yytok2", temp1, c+1);
- /* table 3 has everything else */
- Bprint(ftable, "long yytok3[] =\n{\n");
- c = 0;
- TLOOP(i) {
- j = tokset[i].value;
- if(j >= 0 && j < 256)
- continue;
- if(j >= PRIVATE && j < 256+PRIVATE)
- continue;
- Bprint(ftable, "%4d,%4d,", j, i);
- c++;
- if(c%5 == 0)
- Bprint(ftable, "\n");
- }
- Bprint(ftable, "%4d\n};\n", 0);
- /* copy parser text */
- while((c=Bgetrune(finput)) != Beof) {
- if(c == '$') {
- if((c = Bgetrune(finput)) != 'A')
- Bputrune(ftable, '$');
- else { /* copy actions */
- faction = Bopen(actname, OREAD);
- if(faction == 0)
- error("cannot reopen action tempfile");
- while((c=Bgetrune(faction)) != Beof)
- Bputrune(ftable, c);
- Bterm(faction);
- ZAPFILE(actname);
- c = Bgetrune(finput);
- }
- }
- Bputrune(ftable, c);
- }
- Bterm(ftable);
- }
- /*
- * copies string q into p, returning next free char ptr
- */
- char*
- chcopy(char* p, char* q)
- {
- int c;
- while(c = *q) {
- if(c == '"')
- *p++ = '\\';
- *p++ = c;
- q++;
- }
- *p = 0;
- return p;
- }
- /*
- * creates output string for item pointed to by pp
- */
- char*
- writem(int *pp)
- {
- int i,*p;
- static char sarr[ISIZE];
- char* q;
- for(p=pp; *p>0; p++)
- ;
- p = prdptr[-*p];
- q = chcopy(sarr, nontrst[*p-NTBASE].name);
- q = chcopy(q, ": ");
- for(;;) {
- *q = ' ';
- p++;
- if(p == pp)
- *q = '.';
- q++;
- *q = '\0';
- i = *p;
- if(i <= 0)
- break;
- q = chcopy(q, symnam(i));
- if(q > &sarr[ISIZE-30])
- error("item too big");
- }
- /* an item calling for a reduction */
- i = *pp;
- if(i < 0 ) {
- q = chcopy(q, " (");
- sprint(q, "%d)", -i);
- }
- return sarr;
- }
- /*
- * return a pointer to the name of symbol i
- */
- char*
- symnam(int i)
- {
- char* cp;
- cp = (i >= NTBASE)? nontrst[i-NTBASE].name: tokset[i].name;
- if(*cp == ' ')
- cp++;
- return cp;
- }
- /*
- * output the summary on y.output
- */
- void
- summary(void)
- {
- if(foutput != 0) {
- Bprint(foutput, "\n%d/%d terminals, %d/%d nonterminals\n",
- ntokens, NTERMS, nnonter, NNONTERM);
- Bprint(foutput, "%d/%d grammar rules, %d/%d states\n",
- nprod, NPROD, nstate, NSTATES);
- Bprint(foutput, "%d shift/reduce, %d reduce/reduce conflicts reported\n",
- zzsrconf, zzrrconf);
- Bprint(foutput, "%d/%d working sets used\n",
- (int)(zzcwp-wsets), WSETSIZE);
- Bprint(foutput, "memory: states,etc. %d/%d, parser %d/%d\n",
- (int)(zzmemsz-mem0), MEMSIZE, (int)(memp-amem), ACTSIZE);
- Bprint(foutput, "%d/%d distinct lookahead sets\n", nlset, LSETSIZE);
- Bprint(foutput, "%d extra closures\n", zzclose - 2*nstate);
- Bprint(foutput, "%d shift entries, %d exceptions\n", zzacent, zzexcp);
- Bprint(foutput, "%d goto entries\n", zzgoent);
- Bprint(foutput, "%d entries saved by goto default\n", zzgobest);
- }
- if(zzsrconf != 0 || zzrrconf != 0) {
- print("\nconflicts: ");
- if(zzsrconf)
- print("%d shift/reduce", zzsrconf);
- if(zzsrconf && zzrrconf)
- print(", ");
- if(zzrrconf)
- print("%d reduce/reduce", zzrrconf);
- print("\n");
- }
- if(ftemp != 0) {
- Bterm(ftemp);
- ftemp = 0;
- }
- if(fdefine != 0) {
- Bterm(fdefine);
- fdefine = 0;
- }
- }
- /*
- * write out error comment -- NEEDS WORK
- */
- void
- error(char *s, ...)
- {
- nerrors++;
- fprint(2, "\n fatal error:");
- fprint(2, s, (&s)[1]);
- fprint(2, ", %s:%d\n", infile, lineno);
- if(!fatfl)
- return;
- summary();
- cleantmp();
- exits("error");
- }
- /*
- * set elements 0 through n-1 to c
- */
- void
- aryfil(int *v, int n, int c)
- {
- int i;
- for(i=0; i<n; i++)
- v[i] = c;
- }
- /*
- * set a to the union of a and b
- * return 1 if b is not a subset of a, 0 otherwise
- */
- int
- setunion(int *a, int *b)
- {
- int i, x, sub;
- sub = 0;
- SETLOOP(i) {
- x = *a;
- *a |= *b;
- if(*a != x)
- sub = 1;
- a++;
- b++;
- }
- return sub;
- }
- void
- prlook(Lkset* p)
- {
- int j, *pp;
- pp = p->lset;
- if(pp == 0)
- Bprint(foutput, "\tNULL");
- else {
- Bprint(foutput, " { ");
- TLOOP(j)
- if(BIT(pp,j))
- Bprint(foutput, "%s ", symnam(j));
- Bprint(foutput, "}");
- }
- }
- /*
- * compute an array with the beginnings of productions yielding given nonterminals
- * The array pres points to these lists
- * the array pyield has the lists: the total size is only NPROD+1
- */
- void
- cpres(void)
- {
- int c, j, i, **pmem;
- static int *pyield[NPROD];
- pmem = pyield;
- NTLOOP(i) {
- c = i+NTBASE;
- pres[i] = pmem;
- fatfl = 0; /* make undefined symbols nonfatal */
- PLOOP(0, j)
- if(*prdptr[j] == c)
- *pmem++ = prdptr[j]+1;
- if(pres[i] == pmem)
- error("nonterminal %s not defined!", nontrst[i].name);
- }
- pres[i] = pmem;
- fatfl = 1;
- if(nerrors) {
- summary();
- cleantmp();
- exits("error");
- }
- if(pmem != &pyield[nprod])
- error("internal Yacc error: pyield %d", pmem-&pyield[nprod]);
- }
- /*
- * compute an array with the first of nonterminals
- */
- void
- cpfir(void)
- {
- int *p, **s, i, **t, ch, changes;
- zzcwp = &wsets[nnonter];
- NTLOOP(i) {
- aryfil(wsets[i].ws.lset, tbitset, 0);
- t = pres[i+1];
- /* initially fill the sets */
- for(s=pres[i]; s<t; ++s)
- for(p = *s; (ch = *p) > 0; ++p) {
- if(ch < NTBASE) {
- SETBIT(wsets[i].ws.lset, ch);
- break;
- }
- if(!pempty[ch-NTBASE])
- break;
- }
- }
- /* now, reflect transitivity */
- changes = 1;
- while(changes) {
- changes = 0;
- NTLOOP(i) {
- t = pres[i+1];
- for(s = pres[i]; s < t; ++s)
- for(p = *s; (ch = (*p-NTBASE)) >= 0; ++p) {
- changes |= setunion(wsets[i].ws.lset, wsets[ch].ws.lset);
- if(!pempty[ch])
- break;
- }
- }
- }
- NTLOOP(i)
- pfirst[i] = flset(&wsets[i].ws);
- if(!indebug)
- return;
- if(foutput != 0)
- NTLOOP(i) {
- Bprint(foutput, "\n%s: ", nontrst[i].name);
- prlook(pfirst[i]);
- Bprint(foutput, " %d\n", pempty[i]);
- }
- }
- /*
- * sorts last state,and sees if it equals earlier ones. returns state number
- */
- int
- state(int c)
- {
- Item *p1, *p2, *k, *l, *q1, *q2;
- int size1, size2, i;
- p1 = pstate[nstate];
- p2 = pstate[nstate+1];
- if(p1 == p2)
- return 0; /* null state */
- /* sort the items */
- for(k = p2-1; k > p1; k--) /* make k the biggest */
- for(l = k-1; l >= p1; --l)
- if(l->pitem > k->pitem) {
- int *s;
- Lkset *ss;
- s = k->pitem;
- k->pitem = l->pitem;
- l->pitem = s;
- ss = k->look;
- k->look = l->look;
- l->look = ss;
- }
- size1 = p2 - p1; /* size of state */
- for(i = (c>=NTBASE)? ntstates[c-NTBASE]: tstates[c]; i != 0; i = mstates[i]) {
- /* get ith state */
- q1 = pstate[i];
- q2 = pstate[i+1];
- size2 = q2 - q1;
- if(size1 != size2)
- continue;
- k = p1;
- for(l = q1; l < q2; l++) {
- if(l->pitem != k->pitem)
- break;
- k++;
- }
- if(l != q2)
- continue;
- /* found it */
- pstate[nstate+1] = pstate[nstate]; /* delete last state */
- /* fix up lookaheads */
- if(nolook)
- return i;
- for(l = q1, k = p1; l < q2; ++l, ++k ) {
- int s;
- SETLOOP(s)
- clset.lset[s] = l->look->lset[s];
- if(setunion(clset.lset, k->look->lset)) {
- tystate[i] = MUSTDO;
- /* register the new set */
- l->look = flset( &clset );
- }
- }
- return i;
- }
- /* state is new */
- if(nolook)
- error("yacc state/nolook error");
- pstate[nstate+2] = p2;
- if(nstate+1 >= NSTATES)
- error("too many states");
- if(c >= NTBASE) {
- mstates[nstate] = ntstates[c-NTBASE];
- ntstates[c-NTBASE] = nstate;
- } else {
- mstates[nstate] = tstates[c];
- tstates[c] = nstate;
- }
- tystate[nstate] = MUSTDO;
- return nstate++;
- }
- void
- putitem(int *ptr, Lkset *lptr)
- {
- Item *j;
- if(pidebug && foutput != 0)
- Bprint(foutput, "putitem(%s), state %d\n", writem(ptr), nstate);
- j = pstate[nstate+1];
- j->pitem = ptr;
- if(!nolook)
- j->look = flset(lptr);
- pstate[nstate+1] = ++j;
- if((int*)j > zzmemsz) {
- zzmemsz = (int*)j;
- if(zzmemsz >= &mem0[MEMSIZE])
- error("out of state space");
- }
- }
- /*
- * mark nonterminals which derive the empty string
- * also, look for nonterminals which don't derive any token strings
- */
- void
- cempty(void)
- {
- int i, *p;
- /* first, use the array pempty to detect productions that can never be reduced */
- /* set pempty to WHONOWS */
- aryfil(pempty, nnonter+1, WHOKNOWS);
- /* now, look at productions, marking nonterminals which derive something */
- more:
- PLOOP(0, i) {
- if(pempty[*prdptr[i] - NTBASE])
- continue;
- for(p = prdptr[i]+1; *p >= 0; ++p)
- if(*p >= NTBASE && pempty[*p-NTBASE] == WHOKNOWS)
- break;
- /* production can be derived */
- if(*p < 0) {
- pempty[*prdptr[i]-NTBASE] = OK;
- goto more;
- }
- }
- /* now, look at the nonterminals, to see if they are all OK */
- NTLOOP(i) {
- /* the added production rises or falls as the start symbol ... */
- if(i == 0)
- continue;
- if(pempty[i] != OK) {
- fatfl = 0;
- error("nonterminal %s never derives any token string", nontrst[i].name);
- }
- }
- if(nerrors) {
- summary();
- cleantmp();
- exits("error");
- }
- /* now, compute the pempty array, to see which nonterminals derive the empty string */
- /* set pempty to WHOKNOWS */
- aryfil( pempty, nnonter+1, WHOKNOWS);
- /* loop as long as we keep finding empty nonterminals */
- again:
- PLOOP(1, i) {
- /* not known to be empty */
- if(pempty[*prdptr[i]-NTBASE] == WHOKNOWS) {
- for(p = prdptr[i]+1; *p >= NTBASE && pempty[*p-NTBASE] == EMPTY ; ++p)
- ;
- /* we have a nontrivially empty nonterminal */
- if(*p < 0) {
- pempty[*prdptr[i]-NTBASE] = EMPTY;
- /* got one ... try for another */
- goto again;
- }
- }
- }
- }
- /*
- * generate the states
- */
- void
- stagen(void)
- {
- int c, i, j, more;
- Wset *p, *q;
- /* initialize */
- nstate = 0;
- /* THIS IS FUNNY from the standpoint of portability
- * it represents the magic moment when the mem0 array, which has
- * been holding the productions, starts to hold item pointers, of a
- * different type...
- * someday, alloc should be used to allocate all this stuff... for now, we
- * accept that if pointers don't fit in integers, there is a problem...
- */
- pstate[0] = pstate[1] = (Item*)mem;
- aryfil(clset.lset, tbitset, 0);
- putitem(prdptr[0]+1, &clset);
- tystate[0] = MUSTDO;
- nstate = 1;
- pstate[2] = pstate[1];
- aryfil(amem, ACTSIZE, 0);
- /* now, the main state generation loop */
- for(more=1; more;) {
- more = 0;
- SLOOP(i) {
- if(tystate[i] != MUSTDO)
- continue;
- tystate[i] = DONE;
- aryfil(temp1, nnonter+1, 0);
- /* take state i, close it, and do gotos */
- closure(i);
- /* generate goto's */
- WSLOOP(wsets, p) {
- if(p->flag)
- continue;
- p->flag = 1;
- c = *(p->pitem);
- if(c <= 1) {
- if(pstate[i+1]-pstate[i] <= p-wsets)
- tystate[i] = MUSTLOOKAHEAD;
- continue;
- }
- /* do a goto on c */
- WSLOOP(p, q)
- /* this item contributes to the goto */
- if(c == *(q->pitem)) {
- putitem(q->pitem+1, &q->ws);
- q->flag = 1;
- }
- if(c < NTBASE)
- state(c); /* register new state */
- else
- temp1[c-NTBASE] = state(c);
- }
- if(gsdebug && foutput != 0) {
- Bprint(foutput, "%d: ", i);
- NTLOOP(j)
- if(temp1[j])
- Bprint(foutput, "%s %d, ",
- nontrst[j].name, temp1[j]);
- Bprint(foutput, "\n");
- }
- indgo[i] = apack(&temp1[1], nnonter-1) - 1;
- /* do some more */
- more = 1;
- }
- }
- }
- /*
- * generate the closure of state i
- */
- void
- closure(int i)
- {
- Wset *u, *v;
- Item *p, *q;
- int c, ch, work, k, *pi, **s, **t;
- zzclose++;
- /* first, copy kernel of state i to wsets */
- cwp = wsets;
- ITMLOOP(i, p, q) {
- cwp->pitem = p->pitem;
- cwp->flag = 1; /* this item must get closed */
- SETLOOP(k)
- cwp->ws.lset[k] = p->look->lset[k];
- WSBUMP(cwp);
- }
- /* now, go through the loop, closing each item */
- work = 1;
- while(work) {
- work = 0;
- WSLOOP(wsets, u) {
- if(u->flag == 0)
- continue;
- /* dot is before c */
- c = *(u->pitem);
- if(c < NTBASE) {
- u->flag = 0;
- /* only interesting case is where . is before nonterminal */
- continue;
- }
- /* compute the lookahead */
- aryfil(clset.lset, tbitset, 0);
- /* find items involving c */
- WSLOOP(u, v)
- if(v->flag == 1 && *(pi=v->pitem) == c) {
- v->flag = 0;
- if(nolook)
- continue;
- while((ch = *++pi) > 0) {
- /* terminal symbol */
- if(ch < NTBASE) {
- SETBIT(clset.lset, ch);
- break;
- }
- /* nonterminal symbol */
- setunion(clset.lset, pfirst[ch-NTBASE]->lset);
- if(!pempty[ch-NTBASE])
- break;
- }
- if(ch <= 0)
- setunion(clset.lset, v->ws.lset);
- }
- /*
- * now loop over productions derived from c
- * c is now nonterminal number
- */
- c -= NTBASE;
- t = pres[c+1];
- for(s = pres[c]; s < t; ++s) {
- /*
- * put these items into the closure
- * is the item there
- */
- WSLOOP(wsets, v)
- /* yes, it is there */
- if(v->pitem == *s) {
- if(nolook)
- goto nexts;
- if(setunion(v->ws.lset, clset.lset))
- v->flag = work = 1;
- goto nexts;
- }
- /* not there; make a new entry */
- if(cwp-wsets+1 >= WSETSIZE)
- error( "working set overflow");
- cwp->pitem = *s;
- cwp->flag = 1;
- if(!nolook) {
- work = 1;
- SETLOOP(k) cwp->ws.lset[k] = clset.lset[k];
- }
- WSBUMP(cwp);
- nexts:;
- }
- }
- }
- /* have computed closure; flags are reset; return */
- if(cwp > zzcwp)
- zzcwp = cwp;
- if(cldebug && foutput != 0) {
- Bprint(foutput, "\nState %d, nolook = %d\n", i, nolook);
- WSLOOP(wsets, u) {
- if(u->flag)
- Bprint(foutput, "flag set!\n");
- u->flag = 0;
- Bprint(foutput, "\t%s", writem(u->pitem));
- prlook(&u->ws);
- Bprint(foutput, "\n");
- }
- }
- }
- /*
- * decide if the lookahead set pointed to by p is known
- * return pointer to a perminent location for the set
- */
- Lkset*
- flset(Lkset *p)
- {
- Lkset *q;
- int *u, *v, *w, j;
- for(q = &lkst[nlset]; q-- > lkst;) {
- u = p->lset;
- v = q->lset;
- w = &v[tbitset];
- while(v < w)
- if(*u++ != *v++)
- goto more;
- /* we have matched */
- return q;
- more:;
- }
- /* add a new one */
- q = &lkst[nlset++];
- if(nlset >= LSETSIZE)
- error("too many lookahead sets");
- SETLOOP(j)
- q->lset[j] = p->lset[j];
- return q;
- }
- void
- cleantmp(void)
- {
- ZAPFILE(actname);
- ZAPFILE(tempname);
- }
- void
- intr(void)
- {
- cleantmp();
- exits("interrupted");
- }
- void
- usage(void)
- {
- fprint(2, "usage: yacc [-Dn] [-vdS] [-o outputfile] [-s stem] grammar\n");
- exits("usage");
- }
- void
- setup(int argc, char *argv[])
- {
- long c, t;
- int i, j, lev, ty, ytab, *p;
- int vflag, dflag, stem;
- char actnm[8], *stemc, *s, dirbuf[128];
- ytab = 0;
- vflag = 0;
- dflag = 0;
- stem = 0;
- stemc = "y";
- foutput = 0;
- fdefine = 0;
- fdebug = 0;
- ARGBEGIN{
- case 'v':
- case 'V':
- vflag++;
- break;
- case 'D':
- yydebug = EARGF(usage());
- break;
- case 'd':
- dflag++;
- break;
- case 'o':
- ytab++;
- ytabc = EARGF(usage());
- break;
- case 's':
- stem++;
- stemc = ARGF();
- break;
- case 'S':
- parser = PARSERS;
- break;
- default:
- error("illegal option: %c", ARGC());
- }ARGEND
- openup(stemc, dflag, vflag, ytab, ytabc);
- ftemp = Bopen(tempname = mktemp(ttempname), OWRITE);
- faction = Bopen(actname = mktemp(tactname), OWRITE);
- if(ftemp == 0 || faction == 0)
- error("cannot open temp file");
- if(argc < 1)
- error("no input file");
- infile = argv[0];
- if(infile[0] != '/' && getwd(dirbuf, sizeof dirbuf)!=nil){
- i = strlen(infile)+1+strlen(dirbuf)+1+10;
- s = malloc(i);
- if(s != nil){
- snprint(s, i, "%s/%s", dirbuf, infile);
- cleanname(s);
- infile = s;
- }
- }
- finput = Bopen(infile, OREAD);
- if(finput == 0)
- error("cannot open '%s'", argv[0]);
- cnamp = cnames;
- defin(0, "$end");
- extval = PRIVATE; /* tokens start in unicode 'private use' */
- defin(0, "error");
- defin(1, "$accept");
- defin(0, "$unk");
- mem = mem0;
- i = 0;
- for(t = gettok(); t != MARK && t != ENDFILE;)
- switch(t) {
- case ';':
- t = gettok();
- break;
- case START:
- if(gettok() != IDENTIFIER)
- error("bad %%start construction");
- start = chfind(1, tokname);
- t = gettok();
- continue;
- case TYPEDEF:
- if(gettok() != TYPENAME)
- error("bad syntax in %%type");
- ty = numbval;
- for(;;) {
- t = gettok();
- switch(t) {
- case IDENTIFIER:
- if((t=chfind(1, tokname)) < NTBASE) {
- j = TYPE(toklev[t]);
- if(j != 0 && j != ty)
- error("type redeclaration of token %s",
- tokset[t].name);
- else
- SETTYPE(toklev[t], ty);
- } else {
- j = nontrst[t-NTBASE].value;
- if(j != 0 && j != ty)
- error("type redeclaration of nonterminal %s",
- nontrst[t-NTBASE].name );
- else
- nontrst[t-NTBASE].value = ty;
- }
- case ',':
- continue;
- case ';':
- t = gettok();
- default:
- break;
- }
- break;
- }
- continue;
- case UNION:
- /* copy the union declaration to the output */
- cpyunion();
- t = gettok();
- continue;
- case LEFT:
- case BINARY:
- case RIGHT:
- i++;
- case TERM:
- /* nonzero means new prec. and assoc. */
- lev = t-TERM;
- ty = 0;
- /* get identifiers so defined */
- t = gettok();
- /* there is a type defined */
- if(t == TYPENAME) {
- ty = numbval;
- t = gettok();
- }
- for(;;) {
- switch(t) {
- case ',':
- t = gettok();
- continue;
- case ';':
- break;
- case IDENTIFIER:
- j = chfind(0, tokname);
- if(j >= NTBASE)
- error("%s defined earlier as nonterminal", tokname);
- if(lev) {
- if(ASSOC(toklev[j]))
- error("redeclaration of precedence of %s", tokname);
- SETASC(toklev[j], lev);
- SETPLEV(toklev[j], i);
- }
- if(ty) {
- if(TYPE(toklev[j]))
- error("redeclaration of type of %s", tokname);
- SETTYPE(toklev[j],ty);
- }
- t = gettok();
- if(t == NUMBER) {
- tokset[j].value = numbval;
- if(j < ndefout && j > 3)
- error("please define type number of %s earlier",
- tokset[j].name);
- t = gettok();
- }
- continue;
- }
- break;
- }
- continue;
- case LCURLY:
- defout(0);
- cpycode();
- t = gettok();
- continue;
- default:
- error("syntax error");
- }
- if(t == ENDFILE)
- error("unexpected EOF before %%");
- /* t is MARK */
- Bprint(ftable, "extern int yyerrflag;\n");
- Bprint(ftable, "#ifndef YYMAXDEPTH\n");
- Bprint(ftable, "#define YYMAXDEPTH 150\n");
- Bprint(ftable, "#endif\n" );
- if(!ntypes) {
- Bprint(ftable, "#ifndef YYSTYPE\n");
- Bprint(ftable, "#define YYSTYPE int\n");
- Bprint(ftable, "#endif\n");
- }
- Bprint(ftable, "YYSTYPE yylval;\n");
- Bprint(ftable, "YYSTYPE yyval;\n");
- prdptr[0] = mem;
- /* added production */
- *mem++ = NTBASE;
- /* if start is 0, we will overwrite with the lhs of the first rule */
- *mem++ = start;
- *mem++ = 1;
- *mem++ = 0;
- prdptr[1] = mem;
- while((t=gettok()) == LCURLY)
- cpycode();
- if(t != IDENTCOLON)
- error("bad syntax on first rule");
- if(!start)
- prdptr[0][1] = chfind(1, tokname);
- /* read rules */
- while(t != MARK && t != ENDFILE) {
- /* process a rule */
- rlines[nprod] = lineno;
- if(t == '|')
- *mem++ = *prdptr[nprod-1];
- else
- if(t == IDENTCOLON) {
- *mem = chfind(1, tokname);
- if(*mem < NTBASE)
- error("token illegal on LHS of grammar rule");
- mem++;
- } else
- error("illegal rule: missing semicolon or | ?");
- /* read rule body */
- t = gettok();
- more_rule:
- while(t == IDENTIFIER) {
- *mem = chfind(1, tokname);
- if(*mem < NTBASE)
- levprd[nprod] = toklev[*mem];
- mem++;
- t = gettok();
- }
- if(t == PREC) {
- if(gettok() != IDENTIFIER)
- error("illegal %%prec syntax");
- j = chfind(2, tokname);
- if(j >= NTBASE)
- error("nonterminal %s illegal after %%prec",
- nontrst[j-NTBASE].name);
- levprd[nprod] = toklev[j];
- t = gettok();
- }
- if(t == '=') {
- levprd[nprod] |= ACTFLAG;
- Bprint(faction, "\ncase %d:", nprod);
- cpyact(mem-prdptr[nprod]-1);
- Bprint(faction, " break;");
- if((t=gettok()) == IDENTIFIER) {
- /* action within rule... */
- sprint(actnm, "$$%d", nprod);
- /* make it a nonterminal */
- j = chfind(1, actnm);
- /*
- * the current rule will become rule number nprod+1
- * move the contents down, and make room for the null
- */
- for(p = mem; p >= prdptr[nprod]; --p)
- p[2] = *p;
- mem += 2;
- /* enter null production for action */
- p = prdptr[nprod];
- *p++ = j;
- *p++ = -nprod;
- /* update the production information */
- levprd[nprod+1] = levprd[nprod] & ~ACTFLAG;
- levprd[nprod] = ACTFLAG;
- if(++nprod >= NPROD)
- error("more than %d rules", NPROD);
- prdptr[nprod] = p;
- /* make the action appear in the original rule */
- *mem++ = j;
- /* get some more of the rule */
- goto more_rule;
- }
- }
- while(t == ';')
- t = gettok();
- *mem++ = -nprod;
- /* check that default action is reasonable */
- if(ntypes && !(levprd[nprod]&ACTFLAG) && nontrst[*prdptr[nprod]-NTBASE].value) {
- /* no explicit action, LHS has value */
- int tempty;
- tempty = prdptr[nprod][1];
- if(tempty < 0)
- error("must return a value, since LHS has a type");
- else
- if(tempty >= NTBASE)
- tempty = nontrst[tempty-NTBASE].value;
- else
- tempty = TYPE(toklev[tempty]);
- if(tempty != nontrst[*prdptr[nprod]-NTBASE].value)
- error("default action causes potential type clash");
- }
- nprod++;
- if(nprod >= NPROD)
- error("more than %d rules", NPROD);
- prdptr[nprod] = mem;
- levprd[nprod] = 0;
- }
- /* end of all rules */
- defout(1);
- finact();
- if(t == MARK) {
- Bprint(ftable, "\n#line\t%d\t\"%s\"\n", lineno, infile);
- while((c=Bgetrune(finput)) != Beof)
- Bputrune(ftable, c);
- }
- Bterm(finput);
- }
- /*
- * finish action routine
- */
- void
- finact(void)
- {
- Bterm(faction);
- Bprint(ftable, "#define YYEOFCODE %d\n", 1);
- Bprint(ftable, "#define YYERRCODE %d\n", 2);
- }
- /*
- * define s to be a terminal if t=0
- * or a nonterminal if t=1
- */
- int
- defin(int nt, char *s)
- {
- int val;
- Rune rune;
- val = 0;
- if(nt) {
- nnonter++;
- if(nnonter >= NNONTERM)
- error("too many nonterminals, limit %d",NNONTERM);
- nontrst[nnonter].name = cstash(s);
- return NTBASE + nnonter;
- }
- /* must be a token */
- ntokens++;
- if(ntokens >= NTERMS)
- error("too many terminals, limit %d", NTERMS);
- tokset[ntokens].name = cstash(s);
- /* establish value for token */
- /* single character literal */
- if(s[0] == ' ') {
- val = chartorune(&rune, &s[1]);
- if(s[val+1] == 0) {
- val = rune;
- goto out;
- }
- }
- /* escape sequence */
- if(s[0] == ' ' && s[1] == '\\') {
- if(s[3] == 0) {
- /* single character escape sequence */
- switch(s[2]) {
- case 'n': val = '\n'; break;
- case 'r': val = '\r'; break;
- case 'b': val = '\b'; break;
- case 't': val = '\t'; break;
- case 'f': val = '\f'; break;
- case '\'': val = '\''; break;
- case '"': val = '"'; break;
- case '\\': val = '\\'; break;
- default: error("invalid escape");
- }
- goto out;
- }
- /* \nnn sequence */
- if(s[2] >= '0' && s[2] <= '7') {
- if(s[3] < '0' ||
- s[3] > '7' ||
- s[4] < '0' ||
- s[4] > '7' ||
- s[5] != 0)
- error("illegal \\nnn construction");
- val = 64*s[2] + 8*s[3] + s[4] - 73*'0';
- if(val == 0)
- error("'\\000' is illegal");
- goto out;
- }
- error("unknown escape");
- }
- val = extval++;
- out:
- tokset[ntokens].value = val;
- toklev[ntokens] = 0;
- return ntokens;
- }
- /*
- * write out the defines (at the end of the declaration section)
- */
- void
- defout(int last)
- {
- int i, c;
- char sar[NAMESIZE+10];
- for(i=ndefout; i<=ntokens; i++) {
- /* non-literals */
- c = tokset[i].name[0];
- if(c != ' ' && c != '$') {
- Bprint(ftable, "#define %s %d\n",
- tokset[i].name, tokset[i].value);
- if(fdefine)
- Bprint(fdefine, "#define\t%s\t%d\n",
- tokset[i].name, tokset[i].value);
- }
- }
- ndefout = ntokens+1;
- if(last && fdebug) {
- Bprint(fdebug, "char* yytoknames[] =\n{\n");
- TLOOP(i) {
- if(tokset[i].name) {
- chcopy(sar, tokset[i].name);
- Bprint(fdebug, "\t\"%s\",\n", sar);
- continue;
- }
- Bprint(fdebug, "\t0,\n");
- }
- Bprint(fdebug, "};\n");
- }
- }
- char*
- cstash(char *s)
- {
- char *temp;
- temp = cnamp;
- do {
- if(cnamp >= &cnames[cnamsz])
- error("too many characters in id's and literals");
- else
- *cnamp++ = *s;
- } while(*s++);
- return temp;
- }
- long
- gettok(void)
- {
- long c;
- Rune rune;
- int i, base, match, reserve;
- static int peekline;
- begin:
- reserve = 0;
- lineno += peekline;
- peekline = 0;
- c = Bgetrune(finput);
- while(c == ' ' || c == '\n' || c == '\t' || c == '\f') {
- if(c == '\n')
- lineno++;
- c = Bgetrune(finput);
- }
- /* skip comment */
- if(c == '/') {
- lineno += skipcom();
- goto begin;
- }
- switch(c) {
- case Beof:
- return ENDFILE;
- case '{':
- Bungetrune(finput);
- return '=';
- case '<':
- /* get, and look up, a type name (union member name) */
- i = 0;
- while((c=Bgetrune(finput)) != '>' && c >= 0 && c != '\n') {
- rune = c;
- c = runetochar(&tokname[i], &rune);
- if(i < NAMESIZE)
- i += c;
- }
- if(c != '>')
- error("unterminated < ... > clause");
- tokname[i] = 0;
- for(i=1; i<=ntypes; i++)
- if(!strcmp(typeset[i], tokname)) {
- numbval = i;
- return TYPENAME;
- }
- ntypes++;
- numbval = ntypes;
- typeset[numbval] = cstash(tokname);
- return TYPENAME;
- case '"':
- case '\'':
- match = c;
- tokname[0] = ' ';
- i = 1;
- for(;;) {
- c = Bgetrune(finput);
- if(c == '\n' || c <= 0)
- error("illegal or missing ' or \"" );
- if(c == '\\') {
- tokname[i] = '\\';
- if(i < NAMESIZE)
- i++;
- c = Bgetrune(finput);
- } else
- if(c == match)
- break;
- rune = c;
- c = runetochar(&tokname[i], &rune);
- if(i < NAMESIZE)
- i += c;
- }
- break;
- case '%':
- case '\\':
- switch(c = Bgetrune(finput)) {
- case '0': return TERM;
- case '<': return LEFT;
- case '2': return BINARY;
- case '>': return RIGHT;
- case '%':
- case '\\': return MARK;
- case '=': return PREC;
- case '{': return LCURLY;
- default: reserve = 1;
- }
- default:
- /* number */
- if(isdigit(c)) {
- numbval = c-'0';
- base = (c=='0')? 8: 10;
- for(c = Bgetrune(finput); isdigit(c); c = Bgetrune(finput))
- numbval = numbval*base + (c-'0');
- Bungetrune(finput);
- return NUMBER;
- }
- if(islower(c) || isupper(c) || c=='_' || c=='.' || c=='$') {
- i = 0;
- while(islower(c) || isupper(c) || isdigit(c) ||
- c == '-' || c=='_' || c=='.' || c=='$') {
- if(reserve && isupper(c))
- c += 'a'-'A';
- rune = c;
- c = runetochar(&tokname[i], &rune);
- if(i < NAMESIZE)
- i += c;
- c = Bgetrune(finput);
- }
- } else
- return c;
- Bungetrune(finput);
- }
- tokname[i] = 0;
- /* find a reserved word */
- if(reserve) {
- for(c=0; resrv[c].name; c++)
- if(strcmp(tokname, resrv[c].name) == 0)
- return resrv[c].value;
- error("invalid escape, or illegal reserved word: %s", tokname);
- }
- /* look ahead to distinguish IDENTIFIER from IDENTCOLON */
- c = Bgetrune(finput);
- while(c == ' ' || c == '\t'|| c == '\n' || c == '\f' || c == '/') {
- if(c == '\n')
- peekline++;
- /* look for comments */
- if(c == '/')
- peekline += skipcom();
- c = Bgetrune(finput);
- }
- if(c == ':')
- return IDENTCOLON;
- Bungetrune(finput);
- return IDENTIFIER;
- }
- /*
- * determine the type of a symbol
- */
- int
- fdtype(int t)
- {
- int v;
- if(t >= NTBASE)
- v = nontrst[t-NTBASE].value;
- else
- v = TYPE(toklev[t]);
- if(v <= 0)
- error("must specify type for %s", (t>=NTBASE)?
- nontrst[t-NTBASE].name: tokset[t].name);
- return v;
- }
- int
- chfind(int t, char *s)
- {
- int i;
- if(s[0] == ' ')
- t = 0;
- TLOOP(i)
- if(!strcmp(s, tokset[i].name))
- return i;
- NTLOOP(i)
- if(!strcmp(s, nontrst[i].name))
- return NTBASE+i;
- /* cannot find name */
- if(t > 1)
- error("%s should have been defined earlier", s);
- return defin(t, s);
- }
- /*
- * copy the union declaration to the output, and the define file if present
- */
- void
- cpyunion(void)
- {
- long c;
- int level;
- Bprint(ftable, "\n#line\t%d\t\"%s\"\n", lineno, infile);
- Bprint(ftable, "typedef union ");
- if(fdefine != 0)
- Bprint(fdefine, "\ntypedef union ");
- level = 0;
- for(;;) {
- if((c=Bgetrune(finput)) == Beof)
- error("EOF encountered while processing %%union");
- Bputrune(ftable, c);
- if(fdefine != 0)
- Bputrune(fdefine, c);
- switch(c) {
- case '\n':
- lineno++;
- break;
- case '{':
- level++;
- break;
- case '}':
- level--;
- /* we are finished copying */
- if(level == 0) {
- Bprint(ftable, " YYSTYPE;\n");
- if(fdefine != 0)
- Bprint(fdefine, "\tYYSTYPE;\nextern\tYYSTYPE\tyylval;\n");
- return;
- }
- }
- }
- }
- /*
- * copies code between \{ and \}
- */
- void
- cpycode(void)
- {
- long c;
- c = Bgetrune(finput);
- if(c == '\n') {
- c = Bgetrune(finput);
- lineno++;
- }
- Bprint(ftable, "\n#line\t%d\t\"%s\"\n", lineno, infile);
- while(c != Beof) {
- if(c == '\\') {
- if((c=Bgetrune(finput)) == '}')
- return;
- Bputc(ftable, '\\');
- }
- if(c == '%') {
- if((c=Bgetrune(finput)) == '}')
- return;
- Bputc(ftable, '%');
- }
- Bputrune(ftable, c);
- if(c == '\n')
- lineno++;
- c = Bgetrune(finput);
- }
- error("eof before %%}");
- }
- /*
- * skip over comments
- * skipcom is called after reading a '/'
- */
- int
- skipcom(void)
- {
- long c;
- int i;
- /* i is the number of lines skipped */
- i = 0;
- c = Bgetrune(finput);
- if(c == '/'){ /* C++ //: skip to end of line */
- while((c = Bgetrune(finput)) != Beof)
- if(c == '\n')
- return 1;
- }else if(c == '*'){ /* normal C comment */
- while((c = Bgetrune(finput)) != Beof) {
- while(c == '*')
- if((c = Bgetrune(finput)) == '/')
- return i;
- if(c == '\n')
- i++;
- }
- }else
- error("illegal comment");
- error("EOF inside comment");
- return 0;
- }
- /*
- * copy C action to the next ; or closing }
- */
- void
- cpyact(int offset)
- {
- long c;
- int brac, match, j, s, fnd, tok;
- Bprint(faction, "\n#line\t%d\t\"%s\"\n", lineno, infile);
- brac = 0;
- loop:
- c = Bgetrune(finput);
- swt:
- switch(c) {
- case ';':
- if(brac == 0) {
- Bputrune(faction, c);
- return;
- }
- goto lcopy;
- case '{':
- brac++;
- goto lcopy;
- case '$':
- s = 1;
- tok = -1;
- c = Bgetrune(finput);
- /* type description */
- if(c == '<') {
- Bungetrune(finput);
- if(gettok() != TYPENAME)
- error("bad syntax on $<ident> clause");
- tok = numbval;
- c = Bgetrune(finput);
- }
- if(c == '$') {
- Bprint(faction, "yyval");
- /* put out the proper tag... */
- if(ntypes) {
- if(tok < 0)
- tok = fdtype(*prdptr[nprod]);
- Bprint(faction, ".%s", typeset[tok]);
- }
- goto loop;
- }
- if(c == '-') {
- s = -s;
- c = Bgetrune(finput);
- }
- if(isdigit(c)) {
- j = 0;
- while(isdigit(c)) {
- j = j*10 + (c-'0');
- c = Bgetrune(finput);
- }
- Bungetrune(finput);
- j = j*s - offset;
- if(j > 0)
- error("Illegal use of $%d", j+offset);
- dollar:
- Bprint(faction, "yypt[-%d].yyv", -j);
- /* put out the proper tag */
- if(ntypes) {
- if(j+offset <= 0 && tok < 0)
- error("must specify type of $%d", j+offset);
- if(tok < 0)
- tok = fdtype(prdptr[nprod][j+offset]);
- Bprint(faction, ".%s", typeset[tok]);
- }
- goto loop;
- }
- if(isupper(c) || islower(c) || c == '_' || c == '.') {
- int tok; /* tok used oustide for type info */
- /* look for $name */
- Bungetrune(finput);
- if(gettok() != IDENTIFIER)
- error("$ must be followed by an identifier");
- tok = chfind(2, tokname);
- if((c = Bgetrune(finput)) != '#') {
- Bungetrune(finput);
- fnd = -1;
- } else
- if(gettok() != NUMBER) {
- error("# must be followed by number");
- fnd = -1;
- } else
- fnd = numbval;
- for(j=1; j<=offset; ++j)
- if(tok == prdptr[nprod][j]) {
- if(--fnd <= 0) {
- j -= offset;
- goto dollar;
- }
- }
- error("$name or $name#number not found");
- }
- Bputc(faction, '$');
- if(s < 0 )
- Bputc(faction, '-');
- goto swt;
- case '}':
- brac--;
- if(brac)
- goto lcopy;
- Bputrune(faction, c);
- return;
- case '/':
- /* look for comments */
- Bputrune(faction, c);
- c = Bgetrune(finput);
- if(c != '*')
- goto swt;
- /* it really is a comment; copy it */
- Bputrune(faction, c);
- c = Bgetrune(finput);
- while(c >= 0) {
- while(c == '*') {
- Bputrune(faction, c);
- if((c=Bgetrune(finput)) == '/')
- goto lcopy;
- }
- Bputrune(faction, c);
- if(c == '\n')
- lineno++;
- c = Bgetrune(finput);
- }
- error("EOF inside comment");
- case '\'':
- /* character constant */
- match = '\'';
- goto string;
- case '"':
- /* character string */
- match = '"';
- string:
- Bputrune(faction, c);
- while(c = Bgetrune(finput)) {
- if(c == '\\') {
- Bputrune(faction, c);
- c = Bgetrune(finput);
- if(c == '\n')
- lineno++;
- } else
- if(c == match)
- goto lcopy;
- if(c == '\n')
- error("newline in string or char. const.");
- Bputrune(faction, c);
- }
- error("EOF in string or character constant");
- case Beof:
- error("action does not terminate");
- case '\n':
- lineno++;
- goto lcopy;
- }
- lcopy:
- Bputrune(faction, c);
- goto loop;
- }
- void
- openup(char *stem, int dflag, int vflag, int ytab, char *ytabc)
- {
- char buf[256];
- if(vflag) {
- snprint(buf, sizeof buf, "%s.%s", stem, FILEU);
- foutput = Bopen(buf, OWRITE);
- if(foutput == 0)
- error("cannot open %s", buf);
- }
- if(yydebug) {
- snprint(buf, sizeof buf, "%s.%s", stem, FILEDEBUG);
- if((fdebug = Bopen(buf, OWRITE)) == 0)
- error("can't open %s", buf);
- }
- if(dflag) {
- snprint(buf, sizeof buf, "%s.%s", stem, FILED);
- fdefine = Bopen(buf, OWRITE);
- if(fdefine == 0)
- error("can't create %s", buf);
- }
- if(ytab == 0)
- snprint(buf, sizeof buf, "%s.%s", stem, OFILE);
- else
- strecpy(buf, buf+sizeof buf, ytabc);
- ftable = Bopen(buf, OWRITE);
- if(ftable == 0)
- error("cannot open table file %s", buf);
- }
- /*
- * print the output for the states
- */
- void
- output(void)
- {
- int i, k, c;
- Wset *u, *v;
- Bprint(ftable, "short yyexca[] =\n{");
- if(fdebug)
- Bprint(fdebug, "char* yystates[] =\n{\n");
- /* output the stuff for state i */
- SLOOP(i) {
- nolook = tystate[i]!=MUSTLOOKAHEAD;
- closure(i);
- /* output actions */
- nolook = 1;
- aryfil(temp1, ntokens+nnonter+1, 0);
- WSLOOP(wsets, u) {
- c = *(u->pitem);
- if(c > 1 && c < NTBASE && temp1[c] == 0) {
- WSLOOP(u, v)
- if(c == *(v->pitem))
- putitem(v->pitem+1, (Lkset*)0);
- temp1[c] = state(c);
- } else
- if(c > NTBASE && temp1[(c -= NTBASE) + ntokens] == 0)
- temp1[c+ntokens] = amem[indgo[i]+c];
- }
- if(i == 1)
- temp1[1] = ACCEPTCODE;
- /* now, we have the shifts; look at the reductions */
- lastred = 0;
- WSLOOP(wsets, u) {
- c = *u->pitem;
- /* reduction */
- if(c <= 0) {
- lastred = -c;
- TLOOP(k)
- if(BIT(u->ws.lset, k)) {
- if(temp1[k] == 0)
- temp1[k] = c;
- else
- if(temp1[k] < 0) { /* reduce/reduce conflict */
- if(foutput)
- Bprint(foutput,
- "\n%d: reduce/reduce conflict"
- " (red'ns %d and %d ) on %s",
- i, -temp1[k], lastred,
- symnam(k));
- if(-temp1[k] > lastred)
- temp1[k] = -lastred;
- zzrrconf++;
- } else
- /* potential shift/reduce conflict */
- precftn( lastred, k, i );
- }
- }
- }
- wract(i);
- }
- if(fdebug)
- Bprint(fdebug, "};\n");
- Bprint(ftable, "};\n");
- Bprint(ftable, "#define YYNPROD %d\n", nprod);
- Bprint(ftable, "#define YYPRIVATE %d\n", PRIVATE);
- if(yydebug)
- Bprint(ftable, "#define yydebug %s\n", yydebug);
- }
- /*
- * pack state i from temp1 into amem
- */
- int
- apack(int *p, int n)
- {
- int *pp, *qq, *rr, off, *q, *r;
- /* we don't need to worry about checking because
- * we will only look at entries known to be there...
- * eliminate leading and trailing 0's
- */
- q = p+n;
- for(pp = p, off = 0; *pp == 0 && pp <= q; ++pp, --off)
- ;
- /* no actions */
- if(pp > q)
- return 0;
- p = pp;
- /* now, find a place for the elements from p to q, inclusive */
- r = &amem[ACTSIZE-1];
- for(rr = amem; rr <= r; rr++, off++) {
- for(qq = rr, pp = p; pp <= q; pp++, qq++)
- if(*pp != 0)
- if(*pp != *qq && *qq != 0)
- goto nextk;
- /* we have found an acceptable k */
- if(pkdebug && foutput != 0)
- Bprint(foutput, "off = %d, k = %d\n", off, (int)(rr-amem));
- for(qq = rr, pp = p; pp <= q; pp++, qq++)
- if(*pp) {
- if(qq > r)
- error("action table overflow");
- if(qq > memp)
- memp = qq;
- *qq = *pp;
- }
- if(pkdebug && foutput != 0)
- for(pp = amem; pp <= memp; pp += 10) {
- Bprint(foutput, "\t");
- for(qq = pp; qq <= pp+9; qq++)
- Bprint(foutput, "%d ", *qq);
- Bprint(foutput, "\n");
- }
- return(off);
- nextk:;
- }
- error("no space in action table");
- return 0;
- }
- /*
- * output the gotos for the nontermninals
- */
- void
- go2out(void)
- {
- int i, j, k, best, count, cbest, times;
- /* mark begining of gotos */
- Bprint(ftemp, "$\n");
- for(i = 1; i <= nnonter; i++) {
- go2gen(i);
- /* find the best one to make default */
- best = -1;
- times = 0;
- /* is j the most frequent */
- for(j = 0; j <= nstate; j++) {
- if(tystate[j] == 0)
- continue;
- if(tystate[j] == best)
- continue;
- /* is tystate[j] the most frequent */
- count = 0;
- cbest = tystate[j];
- for(k = j; k <= nstate; k++)
- if(tystate[k] == cbest)
- count++;
- if(count > times) {
- best = cbest;
- times = count;
- }
- }
- /* best is now the default entry */
- zzgobest += times-1;
- for(j = 0; j <= nstate; j++)
- if(tystate[j] != 0 && tystate[j] != best) {
- Bprint(ftemp, "%d,%d,", j, tystate[j]);
- zzgoent++;
- }
- /* now, the default */
- if(best == -1)
- best = 0;
- zzgoent++;
- Bprint(ftemp, "%d\n", best);
- }
- }
- /*
- * output the gotos for nonterminal c
- */
- void
- go2gen(int c)
- {
- int i, work, cc;
- Item *p, *q;
- /* first, find nonterminals with gotos on c */
- aryfil(temp1, nnonter+1, 0);
- temp1[c] = 1;
- work = 1;
- while(work) {
- work = 0;
- PLOOP(0, i)
- /* cc is a nonterminal */
- if((cc=prdptr[i][1]-NTBASE) >= 0)
- /* cc has a goto on c */
- if(temp1[cc] != 0) {
- /* thus, the left side of production i does too */
- cc = *prdptr[i]-NTBASE;
- if(temp1[cc] == 0) {
- work = 1;
- temp1[cc] = 1;
- }
- }
- }
- /* now, we have temp1[c] = 1 if a goto on c in closure of cc */
- if(g2debug && foutput != 0) {
- Bprint(foutput, "%s: gotos on ", nontrst[c].name);
- NTLOOP(i)
- if(temp1[i])
- Bprint(foutput, "%s ", nontrst[i].name);
- Bprint(foutput, "\n");
- }
- /* now, go through and put gotos into tystate */
- aryfil(tystate, nstate, 0);
- SLOOP(i)
- ITMLOOP(i, p, q)
- if((cc = *p->pitem) >= NTBASE)
- /* goto on c is possible */
- if(temp1[cc-NTBASE]) {
- tystate[i] = amem[indgo[i]+c];
- break;
- }
- }
- /*
- * decide a shift/reduce conflict by precedence.
- * r is a rule number, t a token number
- * the conflict is in state s
- * temp1[t] is changed to reflect the action
- */
- void
- precftn(int r, int t, int s)
- {
- int lp, lt, action;
- lp = levprd[r];
- lt = toklev[t];
- if(PLEVEL(lt) == 0 || PLEVEL(lp) == 0) {
- /* conflict */
- if(foutput != 0)
- Bprint(foutput,
- "\n%d: shift/reduce conflict (shift %d(%d), red'n %d(%d)) on %s",
- s, temp1[t], PLEVEL(lt), r, PLEVEL(lp), symnam(t));
- zzsrconf++;
- return;
- }
- if(PLEVEL(lt) == PLEVEL(lp))
- action = ASSOC(lt);
- else
- if(PLEVEL(lt) > PLEVEL(lp))
- action = RASC; /* shift */
- else
- action = LASC; /* reduce */
- switch(action) {
- case BASC: /* error action */
- temp1[t] = ERRCODE;
- break;
- case LASC: /* reduce */
- temp1[t] = -r;
- break;
- }
- }
- /*
- * output state i
- * temp1 has the actions, lastred the default
- */
- void
- wract(int i)
- {
- int p, p0, p1, ntimes, tred, count, j, flag;
- /* find the best choice for lastred */
- lastred = 0;
- ntimes = 0;
- TLOOP(j) {
- if(temp1[j] >= 0)
- continue;
- if(temp1[j]+lastred == 0)
- continue;
- /* count the number of appearances of temp1[j] */
- count = 0;
- tred = -temp1[j];
- levprd[tred] |= REDFLAG;
- TLOOP(p)
- if(temp1[p]+tred == 0)
- count++;
- if(count > ntimes) {
- lastred = tred;
- ntimes = count;
- }
- }
- /*
- * for error recovery, arrange that, if there is a shift on the
- * error recovery token, `error', that the default be the error action
- */
- if(temp1[2] > 0)
- lastred = 0;
- /* clear out entries in temp1 which equal lastred */
- TLOOP(p)
- if(temp1[p]+lastred == 0)
- temp1[p] = 0;
- wrstate(i);
- defact[i] = lastred;
- flag = 0;
- TLOOP(p0)
- if((p1=temp1[p0]) != 0) {
- if(p1 < 0) {
- p1 = -p1;
- goto exc;
- }
- if(p1 == ACCEPTCODE) {
- p1 = -1;
- goto exc;
- }
- if(p1 == ERRCODE) {
- p1 = 0;
- exc:
- if(flag++ == 0)
- Bprint(ftable, "-1, %d,\n", i);
- Bprint(ftable, "\t%d, %d,\n", p0, p1);
- zzexcp++;
- continue;
- }
- Bprint(ftemp, "%d,%d,", p0, p1);
- zzacent++;
- }
- if(flag) {
- defact[i] = -2;
- Bprint(ftable, "\t-2, %d,\n", lastred);
- }
- Bprint(ftemp, "\n");
- }
- /*
- * writes state i
- */
- void
- wrstate(int i)
- {
- int j0, j1;
- Item *pp, *qq;
- Wset *u;
- if(fdebug) {
- if(lastred) {
- Bprint(fdebug, " 0, /*%d*/\n", i);
- } else {
- Bprint(fdebug, " \"");
- ITMLOOP(i, pp, qq)
- Bprint(fdebug, "%s\\n", writem(pp->pitem));
- if(tystate[i] == MUSTLOOKAHEAD)
- WSLOOP(wsets + (pstate[i+1] - pstate[i]), u)
- if(*u->pitem < 0)
- Bprint(fdebug, "%s\\n", writem(u->pitem));
- Bprint(fdebug, "\", /*%d*/\n", i);
- }
- }
- if(foutput == 0)
- return;
- Bprint(foutput, "\nstate %d\n", i);
- ITMLOOP(i, pp, qq)
- Bprint(foutput, "\t%s\n", writem(pp->pitem));
- if(tystate[i] == MUSTLOOKAHEAD)
- /* print out empty productions in closure */
- WSLOOP(wsets+(pstate[i+1]-pstate[i]), u)
- if(*u->pitem < 0)
- Bprint(foutput, "\t%s\n", writem(u->pitem));
- /* check for state equal to another */
- TLOOP(j0)
- if((j1=temp1[j0]) != 0) {
- Bprint(foutput, "\n\t%s ", symnam(j0));
- /* shift, error, or accept */
- if(j1 > 0) {
- if(j1 == ACCEPTCODE)
- Bprint(foutput, "accept");
- else
- if(j1 == ERRCODE)
- Bprint(foutput, "error");
- else
- Bprint(foutput, "shift %d", j1);
- } else
- Bprint(foutput, "reduce %d (src line %d)", -j1, rlines[-j1]);
- }
- /* output the final production */
- if(lastred)
- Bprint(foutput, "\n\t. reduce %d (src line %d)\n\n",
- lastred, rlines[lastred]);
- else
- Bprint(foutput, "\n\t. error\n\n");
- /* now, output nonterminal actions */
- j1 = ntokens;
- for(j0 = 1; j0 <= nnonter; j0++) {
- j1++;
- if(temp1[j1])
- Bprint(foutput, "\t%s goto %d\n", symnam(j0+NTBASE), temp1[j1]);
- }
- }
- void
- warray(char *s, int *v, int n)
- {
- int i;
- Bprint(ftable, "short %s[] =\n{", s);
- for(i=0;;) {
- if(i%10 == 0)
- Bprint(ftable, "\n");
- Bprint(ftable, "%4d", v[i]);
- i++;
- if(i >= n) {
- Bprint(ftable, "\n};\n");
- break;
- }
- Bprint(ftable, ",");
- }
- }
- /*
- * in order to free up the mem and amem arrays for the optimizer,
- * and still be able to output yyr1, etc., after the sizes of
- * the action array is known, we hide the nonterminals
- * derived by productions in levprd.
- */
- void
- hideprod(void)
- {
- int i, j;
- j = 0;
- levprd[0] = 0;
- PLOOP(1, i) {
- if(!(levprd[i] & REDFLAG)) {
- j++;
- if(foutput != 0)
- Bprint(foutput, "Rule not reduced: %s\n", writem(prdptr[i]));
- }
- levprd[i] = *prdptr[i] - NTBASE;
- }
- if(j)
- print("%d rules never reduced\n", j);
- }
- void
- callopt(void)
- {
- int i, *p, j, k, *q;
- /* read the arrays from tempfile and set parameters */
- finput = Bopen(tempname, OREAD);
- if(finput == 0)
- error("optimizer cannot open tempfile");
- pgo[0] = 0;
- temp1[0] = 0;
- nstate = 0;
- nnonter = 0;
- for(;;) {
- switch(gtnm()) {
- case '\n':
- nstate++;
- pmem--;
- temp1[nstate] = pmem - mem0;
- case ',':
- continue;
- case '$':
- break;
- default:
- error("bad tempfile");
- }
- break;
- }
- pmem--;
- temp1[nstate] = yypgo[0] = pmem - mem0;
- for(;;) {
- switch(gtnm()) {
- case '\n':
- nnonter++;
- yypgo[nnonter] = pmem-mem0;
- case ',':
- continue;
- case -1:
- break;
- default:
- error("bad tempfile");
- }
- break;
- }
- pmem--;
- yypgo[nnonter--] = pmem - mem0;
- for(i = 0; i < nstate; i++) {
- k = 32000;
- j = 0;
- q = mem0 + temp1[i+1];
- for(p = mem0 + temp1[i]; p < q ; p += 2) {
- if(*p > j)
- j = *p;
- if(*p < k)
- k = *p;
- }
- /* nontrivial situation */
- if(k <= j) {
- /* j is now the range */
- /* j -= k; /* call scj */
- if(k > maxoff)
- maxoff = k;
- }
- tystate[i] = (temp1[i+1]-temp1[i]) + 2*j;
- if(j > maxspr)
- maxspr = j;
- }
- /* initialize ggreed table */
- for(i = 1; i <= nnonter; i++) {
- ggreed[i] = 1;
- j = 0;
- /* minimum entry index is always 0 */
- q = mem0 + yypgo[i+1] - 1;
- for(p = mem0+yypgo[i]; p < q ; p += 2) {
- ggreed[i] += 2;
- if(*p > j)
- j = *p;
- }
- ggreed[i] = ggreed[i] + 2*j;
- if(j > maxoff)
- maxoff = j;
- }
- /* now, prepare to put the shift actions into the amem array */
- for(i = 0; i < ACTSIZE; i++)
- amem[i] = 0;
- maxa = amem;
- for(i = 0; i < nstate; i++) {
- if(tystate[i] == 0 && adb > 1)
- Bprint(ftable, "State %d: null\n", i);
- indgo[i] = YYFLAG1;
- }
- while((i = nxti()) != NOMORE)
- if(i >= 0)
- stin(i);
- else
- gin(-i);
- /* print amem array */
- if(adb > 2 )
- for(p = amem; p <= maxa; p += 10) {
- Bprint(ftable, "%4d ", (int)(p-amem));
- for(i = 0; i < 10; ++i)
- Bprint(ftable, "%4d ", p[i]);
- Bprint(ftable, "\n");
- }
- /* write out the output appropriate to the language */
- aoutput();
- osummary();
- ZAPFILE(tempname);
- }
- void
- gin(int i)
- {
- int *p, *r, *s, *q1, *q2;
- /* enter gotos on nonterminal i into array amem */
- ggreed[i] = 0;
- q2 = mem0+ yypgo[i+1] - 1;
- q1 = mem0 + yypgo[i];
- /* now, find amem place for it */
- for(p = amem; p < &amem[ACTSIZE]; p++) {
- if(*p)
- continue;
- for(r = q1; r < q2; r += 2) {
- s = p + *r + 1;
- if(*s)
- goto nextgp;
- if(s > maxa)
- if((maxa = s) > &amem[ACTSIZE])
- error("a array overflow");
- }
- /* we have found amem spot */
- *p = *q2;
- if(p > maxa)
- if((maxa = p) > &amem[ACTSIZE])
- error("a array overflow");
- for(r = q1; r < q2; r += 2) {
- s = p + *r + 1;
- *s = r[1];
- }
- pgo[i] = p-amem;
- if(adb > 1)
- Bprint(ftable, "Nonterminal %d, entry at %d\n", i, pgo[i]);
- return;
- nextgp:;
- }
- error("cannot place goto %d\n", i);
- }
- void
- stin(int i)
- {
- int *r, *s, n, flag, j, *q1, *q2;
- tystate[i] = 0;
- /* enter state i into the amem array */
- q2 = mem0+temp1[i+1];
- q1 = mem0+temp1[i];
- /* find an acceptable place */
- for(n = -maxoff; n < ACTSIZE; n++) {
- flag = 0;
- for(r = q1; r < q2; r += 2) {
- if((s = *r + n + amem) < amem)
- goto nextn;
- if(*s == 0)
- flag++;
- else
- if(*s != r[1])
- goto nextn;
- }
- /* check that the position equals another only if the states are identical */
- for(j=0; j<nstate; j++) {
- if(indgo[j] == n) {
- /* we have some disagreement */
- if(flag)
- goto nextn;
- if(temp1[j+1]+temp1[i] == temp1[j]+temp1[i+1]) {
- /* states are equal */
- indgo[i] = n;
- if(adb > 1)
- Bprint(ftable,
- "State %d: entry at %d equals state %d\n",
- i, n, j);
- return;
- }
- /* we have some disagreement */
- goto nextn;
- }
- }
- for(r = q1; r < q2; r += 2) {
- if((s = *r+n+amem) >= &amem[ACTSIZE])
- error("out of space in optimizer a array");
- if(s > maxa)
- maxa = s;
- if(*s != 0 && *s != r[1])
- error("clobber of a array, pos'n %d, by %d", s-amem, r[1]);
- *s = r[1];
- }
- indgo[i] = n;
- if(adb > 1)
- Bprint(ftable, "State %d: entry at %d\n", i, indgo[i]);
- return;
- nextn:;
- }
- error("Error; failure to place state %d\n", i);
- }
- /*
- * finds the next i
- */
- int
- nxti(void)
- {
- int i, max, maxi;
- max = 0;
- maxi = 0;
- for(i = 1; i <= nnonter; i++)
- if(ggreed[i] >= max) {
- max = ggreed[i];
- maxi = -i;
- }
- for(i = 0; i < nstate; ++i)
- if(tystate[i] >= max) {
- max = tystate[i];
- maxi = i;
- }
- if(nxdb)
- Bprint(ftable, "nxti = %d, max = %d\n", maxi, max);
- if(max == 0)
- return NOMORE;
- return maxi;
- }
- /*
- * write summary
- */
- void
- osummary(void)
- {
- int i, *p;
- if(foutput == 0)
- return;
- i = 0;
- for(p = maxa; p >= amem; p--)
- if(*p == 0)
- i++;
- Bprint(foutput, "Optimizer space used: input %d/%d, output %d/%d\n",
- (int)(pmem-mem0+1), MEMSIZE, (int)(maxa-amem+1), ACTSIZE);
- Bprint(foutput, "%d table entries, %d zero\n", (int)(maxa-amem+1), i);
- Bprint(foutput, "maximum spread: %d, maximum offset: %d\n", maxspr, maxoff);
- }
- /*
- * this version is for C
- * write out the optimized parser
- */
- void
- aoutput(void)
- {
- Bprint(ftable, "#define\tYYLAST\t%d\n", (int)(maxa-amem+1));
- arout("yyact", amem, (maxa-amem)+1);
- arout("yypact", indgo, nstate);
- arout("yypgo", pgo, nnonter+1);
- }
- void
- arout(char *s, int *v, int n)
- {
- int i;
- Bprint(ftable, "short %s[] =\n{", s);
- for(i = 0; i < n;) {
- if(i%10 == 0)
- Bprint(ftable, "\n");
- Bprint(ftable, "%4d", v[i]);
- i++;
- if(i == n)
- Bprint(ftable, "\n};\n");
- else
- Bprint(ftable, ",");
- }
- }
- /*
- * read and convert an integer from the standard input
- * return the terminating character
- * blanks, tabs, and newlines are ignored
- */
- int
- gtnm(void)
- {
- int sign, val, c;
- sign = 0;
- val = 0;
- while((c=Bgetrune(finput)) != Beof) {
- if(isdigit(c)) {
- val = val*10 + c-'0';
- continue;
- }
- if(c == '-') {
- sign = 1;
- continue;
- }
- break;
- }
- if(sign)
- val = -val;
- *pmem++ = val;
- if(pmem >= &mem0[MEMSIZE])
- error("out of space");
- return c;
- }
|