home *** CD-ROM | disk | FTP | other *** search
- /* parser.c -- derived from the `LALR' parser written by Paul Mann */
-
- #define CLASS Parser
-
- #include <oxbow.h>
-
- object CLASS;
-
- instanceVars {
- PG pg;
- };
- #define HOWBIG 1
- #define DEBUG 1
-
- #if HOWBIG
- static int maxXX_parse;
- static int maxSS_parse;
- static int maxSS_lex;
- static int maxNS_parse;
- static int maxLS_parse;
- static int maxRS_parse;
- #endif
-
-
- /* Built in standard actions */
- static void nullaction();
- static void classify();
- static void require();
- static void doline();
- static void dyntoken();
-
- static void LoadParserPointers();
-
- /* some imported functions */
- char *strchr();
- char *strrchr();
- int atol();
- int _strcpy(void *dst, const void *src);
- void *strcpy(void *dst, const void *src);
- void *strcat(void *dst, const void *src);
- void *memcpy(void *dst, const void *src, int len);
-
-
- /* All chunk types have the same number of bytes */
-
- #define ASTCHUNK (pg->astchunk)
- #define SYMBOLCHUNK (pg->symbolchunk)
- #define TEXTCHUNK (pg->textchunk)
- #define ASTSIZE (pg->astsize)
-
-
- typedef struct _key
- {
- unsigned long key;
- unsigned long hv;
- } KEY, *KEYP;
-
- typedef struct _psym
- {/* Fits in a minimal sized AST node */
- unsigned short dat[4]; /* 8 bytes */
- KEY cat; /* 8 bytes */
- struct _psym *next; /* 4 bytes */
- } Psym, *PsymP;
-
- typedef struct _pbuf
- {/* parser symbol table struct */
- int size;
- void *lastbin; /* for DelLast */
- int headbin; /* for seq access */
- PsymP headptr; /* ditto */
- PG *wpg;
- PsymP bins[0];
- } *PbufP;
-
- void *
- NewParserSymTable(PG *pg, int size)
- {
- PbufP buf = callocC(pg->category, 1, size*sizeof(PsymP) + sizeof(struct _pbuf));
- buf->size = size;
- buf->wpg = pg;
- return buf;
- }
-
- cmethod vobject
- New(object self, char *language, int astsize)
- {
- void *lfile;
- char lodname[200];
- char filename[40];
- char *cp;
- PTABLE *pp;
- LTABLE *lp;
- long *symbase;
- char *symptr;
- char buf[100];
- Item item;
- int i;
- object instance;
- PG *pg;
- int oldload = 0;
- AstP fnode;
-
- if(IsaClass(self))
- instance = cSuper(gNew)(self);
- else {
- instance = self;
- }
- pg = (PG *)ivPtr(instance);
- pg->category = NewMallocCategory();
-
- strcpy(pg->language, language);
- strcpy(filename, language);
- strcat(filename, ".lod");
-
- if((cf_find_file("oxlib.cff", lodname)))
- {/* The archive file */
- strcat(lodname, "/language/");
- strcat(lodname, filename);
- } else {
- pg->errors = 1;
- return instance;
- }
- if(cfqget(MEMTEMP, filename, strlen(filename), &item, 8) == FOUND)
- {/* Parser tables for this language have been loaded earlier */
- pg->lod_table = item.a1;
- oldload = 1;
- }
- else
- {/* Load the parser tables for this language */
- if((lfile = cfopen(lodname, F_STAT, NULL)))
- {
- int size;
- size = cfseek(lfile, 0, S_END);
- pg->lod_table = malloc(size);
- cfseek(lfile, 0, S_SET);
- cfread(lfile, pg->lod_table, size);
- cfclose(lfile);
- item.item = 0;
- item.a1 = pg->lod_table;
- cfinsert(MEMTEMP, filename, strlen(filename), &item);
- }
- else {
- pg->errors = 2;
- return instance;
- }
- }
-
- /* using the size of the caller's AST node, compute suitable chunks */
-
- if(astsize < sizeof(AST_NODE))
- astsize = sizeof(AST_NODE);
-
- if(astsize & 3)
- astsize += 4-(astsize&3);
-
- ASTCHUNK = 8184/astsize;
- TEXTCHUNK = ASTCHUNK * astsize;
- SYMBOLCHUNK = TEXTCHUNK / 4;
- ASTSIZE = astsize;
-
- /* Parser table init */
- pg->ptab = callocC(pg->category, 1, sizeof(PTABLE));
- pp = pg->ptab;
- pp->pg = pg;
- LoadParserPointers(pp, pg->lod_table, 1);
- pp->linksize = SYMBOLCHUNK;
- pp->link = callocC(pg->category, 1, SYMBOLCHUNK*sizeof(void*));
-
-
- /* Lexer table init */
- pg->ltab = callocC(pg->category, 1, sizeof(LTABLE));
- lp = pg->ltab;
- lp->pg = pg;
- LoadParserPointers(lp, (LODTABLE *)(((char *)pg->lod_table) + pg->lod_table->next), 0);
-
- /* Action pointers, applies to both parser and lexer */
- pg->n_actions = lp->n_actions; /* lexer has the best action count */
- pg->ACTIONS = (PACTIONS)lp->ACTIONS;
- pg->ACTIONSTRINGS = lp->ACTIONSTRINGS;
-
- /* Allocate the initial ast space */
- pg->pat.free = callocC(pg->category, 1, ASTCHUNK*astsize);
- pg->pat.freecnt = pg->pat.cnt = ASTCHUNK;
- fnode = pg->pat.free;
- for(i = 0; i < ASTCHUNK-1; ++i)
- {
- fnode->down = (AstP)(((char*)fnode)+ASTSIZE);
- fnode = fnode->down;
- }
-
- /* Allocate and initialize the parser symbol table */
- PARSERSYMBOLS = callocC(pg->category, 1, SYMBOLCHUNK*sizeof(PARSER_SYMBOL));
- pg->symhandle = NewParserSymTable(pg, 2003);
-
- /* Allocate and initialize the first text accumulation chunk */
- pg->chunkbase = callocC(pg->category, 1, TEXTCHUNK);
- pg->chunkend = pg->chunkbase+TEXTCHUNK-1;
- pg->symbase = pg->chunkbase+4;
- pg->symend = pg->symbase;
-
- /* Enter all the terminal symbols of the grammar */
- symbase = pp->G_symbol;
- symptr = (char *)symbase;
-
- for(i = 0; i < pp->n_terms; ++i)
- {
- NewParserSymbol(pg, symptr+symbase[i]);
- }
-
- /* Set the values for the automatic node ids */
- {
- int symnum = -1;
- int symval;
- int subsym = 0;
- char *cp = NULL;
- for(i = 0; i < pp->n_rules; ++i)
- {
- long *vp; /* assume callers node ids are sizeof(long) */
- if(pp->PL[i] & PL_MAKENODE)
- {
- if(pp->Head[i] != symnum)
- {
- subsym = 0;
- symnum = pp->Head[i];
- cp = symptr + symbase[symnum];
- }
- /* e.g. _cInitDeclarator_0 */
- cfsprintf(buf, "_%s%s_%d", pg->language, cp, subsym);
-
- /* use dynamic linker here */
- symval = (symnum<<6) | subsym;
- if((vp = oxlink_find_bare_symb(buf)) != NULL)
- {/* vp is now the address of the symbol in caller memory */
- *vp = symval; /* caller defined a global symbol he wants */
- }
- ++subsym;
- }
- }
- }
- /* Set up the function pointers for actions */
- if(!oldload)
- {/* THIS WOULD WORK WITHOUT TESTING FOR 'oldload', just saving time */
- PACTIONS pa = pg->ACTIONS;
- char *cp;
- int mask;
- int j;
-
- for(i = 0; i < pg->n_actions; ++i, ++pa)
- {
- /*
- pa->func is initially set to an offset into ACTIONSTRINGS
- convert it into a function pointer
- */
- cp = pg->ACTIONSTRINGS + (int)pa->func; /* funcname is first entry */
- if(!strcmp(cp, "classify"))
- pa->func = classify;
- else if(!strcmp(cp, "require"))
- pa->func = require;
- else if(!strcmp(cp, "doline"))
- pa->func = doline;
- else if(!strcmp(cp, "dyntoken"))
- pa->func = dyntoken;
- else
- {/* Concoct the real user action name and find the function */
- /* e.g. _dosomething_ada_ */
- cfsprintf(buf, "_%s_%s_", cp, pg->language);
- if((pa->func = oxlink_find_bare_func(buf)) == NULL)
- {/* Not already in core */
- if((pa->func = oxlink_load_bare_symb(buf, 1)) == NULL)
- {/* And can't load it from the archive, punt to nothing */
- pa->func = nullaction;
- }
- }
- }
- /*
- Set up the args:
- arg[0] contains a bitmask in the high order 16 bits
- and argcnt in the low 16 bits
- */
- mask = (pa->args[0] & 0xffff0000) >> 16;
- pa->args[0] &= 0x0000ffff;
- for(j = 1; j <= pa->args[0]; ++j)
- {
- if(mask & 1)
- {/* This arg is really a pointer to a string */
- pa->args[j] += (int)pg->ACTIONSTRINGS;
- }
- mask >>= 1;
- }
- }
- }
- /* Set a few constants */
- pg->parsecnt = 2;
- pg->ROOT = 0;
- pg->root = 0;
- pg->line_numb = 1;
- pg->line_char = 0;
- #if HOWBIG
- maxXX_parse =
- maxSS_parse =
- maxSS_lex =
- maxNS_parse =
- maxLS_parse =
- maxRS_parse = 0;
- #endif
- return instance;
- }
- imethod void
- Dispose(object self)
- {
- PG *pg = (PG *)ivPtr(self);
-
- freecat(pg->category);
- super(gDispose)(self);
- }
-
-
- static unsigned short bitlist[16] = {
- 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
- 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000
- };
- #define BITSET(a,b,c) ( a[b+(c>>4)] & bitlist[c&0xf] )
-
- static int
- do_parse (PTABLE *ptab)
- {
- short i, x;
- short *r;
- short rule;
- unsigned base;
- short state;
- int token;
- short stacktop, *SS;
- PG *pg;
- int rulesize;
- int debug;
- int xx;
- AstP *link;
- int lexindx;
-
- /* NESTED SUBROUTINE Make AST node and/or call semantic action. */
-
- static void attach ()
- {
- int k, i, j;
- AstP np, lp, p;
- int rulesize;
- AstP newnode;
- int savxx;
- short *pxx;
-
- rulesize = ptab->PL[rule] & 0x000f;
- if(rulesize == 15)
- rulesize = -1;
-
- ptab->NS -= rulesize; /* Reduce the stack. */
- ptab->LS -= rulesize;
-
- for (k=0,np=0,i=rulesize; i >= 0; i--) /* Look at each tail spot. */
- {
- if (ptab->NS[i]) /* If node pointer there. */
- {
- int xxx;
- k++; /* Active node marker. */
- p = ptab->NS[i]; /* Last node in chain */
- xxx = ptab->LS[i];
-
- if (np) /* If one waiting. */
- {
- lp = link[xxx];
- lp->down = np; /* Connect last to next. */
- link[xxx] = link[savxx]; /* Move link */
- #if DEBUG
- if(debug)cfprintf("Parse: Set DOWN at %x to %x\n", lp, np);
- #endif
- }
- np = p; /* Get this ones address. */
- savxx = xxx;
- }
- }
- if (ptab->PL [rule] & PL_MAKENODE)
- {
- newnode = NewAstNode(pg,(ptab->Head[rule]<<6)|(rule-ptab->rBase[rule]),0);
- if(!pg->ROOT)
- pg->ROOT = newnode;
-
- if (k > 0)
- {/* Make branch */
- newnode->right = np; /* Pointer to child. */
- newnode->fileno = (unsigned char)pg->line_file; /* current file */
- newnode->colno = (unsigned char)pg->line_char; /* column of text */
- newnode->lineno = (unsigned short)pg->line_numb;/* Line number. */
- if (np == pg->ROOT) {
- pg->ROOT = newnode; /* Root points to parent. */
- #if DEBUG
- if(debug)cfprintf("Parse: Reset ROOT to %x\n", newnode);
- #endif
- }
- #if DEBUG
- if(debug)cfprintf("Parse: New Branch at %x %s_%d right=%x down=%x\n",
- newnode,GetH_symbol(pg, ptab->Head[rule]),rule-ptab->rBase[rule],np, newnode->down);
- #endif
- }
- else
- {/* Make leaf */
- int lookback = (pg->LSP-lexindx)&3;
- newnode->Tindx = pg->L_stack[lookback+1]; /* Terminal type */
- newnode->symb = pg->L_stack[lookback]; /* Symnum */
- newnode->fileno = (unsigned char)pg->line_file; /* current file */
- newnode->colno = (unsigned char)pg->line_char; /* column of text */
- newnode->lineno = (unsigned short)pg->line_numb;/* Line number. */
- #if DEBUG
- if(debug)cfprintf("Parse: New Leaf at %x %s_%d right=%x down=%x\n",
- newnode,GetH_symbol(pg, ptab->Head[rule]),rule-ptab->rBase[rule], newnode->right, newnode->down);
- #endif
- }
-
- /* Prevent the unconstrained growth of the link array */
- for(pxx = ptab->LStop, xx = 0; pxx <= ptab->LS; ++pxx)
- {
- if(*pxx > xx)
- xx = *pxx;
- }
-
- if(++xx == ptab->linksize)
- {/* Extend the link array */
- ptab->linksize += SYMBOLCHUNK;
- link = reallocC(pg->category, link, ptab->linksize*sizeof(int));
- ptab->link = link;
- }
- np = newnode;
- link[xx] = np;
- }
- *(ptab->NS) = np;
- *(ptab->LS) = xx;
-
- #if HOWBIG
- if(xx > maxXX_parse)
- maxXX_parse = xx;
- #endif
-
- /* Call actions for a rule */
- if (ptab->PL [rule] & PL_ACTION) /* Call action? */
- {
- PACTIONS ap = &pg->ACTIONS[(ptab->PL[rule]>>7)&511];
- #if DEBUG
- if(debug)cfprintf("Parse: Call Action for rule:%d\n", rule);
- #endif
- ptab->node = np;
- pg->actionerr = NULL;
- (*ap->func) (pg, ap->args); /* Call action. */
-
- if (ptab->PL [rule] & PL_DELTREE) /* Delete the subtree? */
- {
- #if DEBUG
- if(debug)cfprintf("Parse: Prune Tree at rule:%d\n",rule);
- #endif
- *(ptab->NS) = 0; /* Reset np to 0. */
- PruneAstTree(pg, np, 0, 0); /* Get rid of all nodes including root */
- pg->ROOT = np; /* will be next node allocated */
- }
- }
- }/* END attach() */
- /* NESTED SUBROUTINE */
- static int procrules()
- {
- /* Attach all currently known rules to the ast */
- ptab->rule = rule;
- for (r = ptab->RStop; r < ptab->Rs; )
- {
- rule = *r++;
- if(rule < 0)
- {/* Shift occured */
- *(++(ptab->NS)) = (AstP)0; /* Set node pointer to zero. */
- *(++(ptab->LS)) = 0;
- lexindx -= 2; /* lex symbol is one token closer */
- }
- else
- {
- attach (); /* Attach node to AST. */
- if(pg->actionerr) {
- #if DEBUG
- if(debug)cfprintf("PARSE action error exit\n");
- #endif
- return 1;
- }
- }
- }
- ptab->Rs = ptab->RStop; /* Reset reduction stk ptr. */
-
- #if HOWBIG
- if((ptab->NS - ptab->NStop) > maxNS_parse)
- maxNS_parse = ptab->NS - ptab->NStop;
- if((ptab->LS - ptab->LStop) > maxLS_parse)
- maxLS_parse = ptab->LS - ptab->LStop;
- #endif
- return 0;
- } /* END: procrules */
-
- /* do_parse */
- pg = ptab->pg;
- SS = ptab->SS;
- state = ptab->state;
- token = ptab->token;
- link = ptab->link;
- xx = ptab->xx;
- debug = pg->debug & 1;
- lexindx = 4;
- #if DEBUG
- if(debug)cfprintf("ParseSTART: state=%d token=%d\n", state, token);
- #endif
- Scan:
- if(token < 0)
- {
- if(procrules())
- return -1;
- /* get new token */
- ptab->state = state;
- ptab->SS = SS;
- ptab->xx = xx;
- return(0);
- }
-
- /* Test for Shift, and Shift-Reduce */
-
- base = state * ptab->bitwords;
- if(BITSET(ptab->M_bits, base, token))
- {
- x = ptab->MT_tran[ ptab->MT_beg[state] + ptab->token];
- *++(SS) = state; /* Put state on parse stack.*/
- #if HOWBIG
- if((SS - ptab->SStop) > maxSS_parse)
- maxSS_parse = SS - ptab->SStop;
- #endif
- if (SS >= ptab->SSmax) /* If parse stack too large.*/
- {
- cfprintf("Parse: stack overflow \n");
- OXPORT_crash("");
- }
- *ptab->Rs++ = -1; /* Mark reduction stack as shifted */
- token = -1; /* Indicate token consumed */
- if(x > 0)
- {
- state = x;
- #if DEBUG
- if(debug)cfprintf("Parse: shift to state %d\n", state);
- #endif
- goto Scan; /* Shift only */
- }
- /* --- REDUCE -----------------------*/
-
- Neg: rule = -x; /* Make positive. */
- Reduce:
- rulesize = ptab->PL [rule] & 0x000f;
- if(rulesize == 15)
- rulesize = -1;
- SS -= rulesize;
- if(rulesize == -1)
- {
- *SS = state; /* Stack current state. */
- }
- stacktop = *SS;
- *ptab->Rs++ = rule;
- #if HOWBIG
- if((ptab->Rs - ptab->RStop) > maxRS_parse)
- maxRS_parse = ptab->Rs - ptab->RStop;
- #endif
- #if DEBUG
- if(debug)cfprintf("Parse: stack rule %d, new state is %d head=%d\n",
- rule, stacktop, ptab->Head[rule]);
- #endif
- /* Check for goal */
- if(rule == 0)
- {
- if(procrules())
- return -1;
- pg->root = pg->ROOT;
- #if DEBUG
- if(debug)cfprintf("PARSE DONE rootnode=%x\n", pg->root);
- #endif
- return 1;
- }
-
- /* Check non terminal transitions for current state */
-
- base = stacktop * ptab->bitwords;
- if(BITSET(ptab->M_bits, base, ptab->Head[rule]))
- {
- x = ptab->MN_tran[ptab->MN_beg[stacktop]+(ptab->Head[rule]-ptab->n_terms)];
- if(x > 0)
- {
- state = x;
- #if DEBUG
- if(debug)cfprintf("Parse: NT trans to state %d\n", state);
- #endif
- goto Scan;
- }
- #if DEBUG
- if(debug)cfprintf("Parse: NT reduce to rule %d, state=%d\n",-x, stacktop);
- #endif
- goto Neg;
- }
- #if DEBUG
- if(debug)cfprintf("Parse: NO nt tran for state %d\n",stacktop);
- #endif
- goto Scan;
-
- }/* END of shift/reduce test */
-
- /* Check for pure reductions */
- #if DEBUG
- if(debug)cfprintf("Parse: check reductions for state %d\n", state);
- #endif
- rule = ptab->D_red [state];
- if(rule >= 0) {
- #if DEBUG
- if(debug)cfprintf("Parse: use default reduction to rule %d\n", rule);
- #endif
- goto Reduce; /* Default reduction */
- }
- if (rule == -32767)
- {
- ptab->state = state;
- ptab->token = token;
- ptab->SS = SS;
- ptab->xx = xx;
- #if DEBUG
- if(debug)cfprintf("PARSE error exit\n");
- #endif
- return(-1);
- }
-
- /* Check multiple reductions */
- #if DEBUG
- if(debug)cfprintf("Parse: check multiple reductions in state %d\n", state);
- #endif
- for (i = ptab->R_start [state]; i < ptab->R_start [state+1]; i++)
- {
- if (ptab->R_symbol [i] == token) /* Found? */
- {
- rule = ptab->R_prod [i];
- #if DEBUG
- if(debug)cfprintf("Parse: multiple reduction to rule %d token=%d\n", rule, token);
- #endif
- goto Reduce;
- }
- }
- rule = -rule; /* Multiple default. */
- #if DEBUG
- if(debug)cfprintf("Parse: use multiple default rule %d\n", rule);
- #endif
- goto Reduce;
-
- }/* END OF do_parse() */
-
- /* THIS LEXER USES PARSER STYLE TABLES [Improve me NDC] */
- static void
- new_chunk(PG *pg, char tok)
- {
- long *tempbase;
- int chunksize;
-
- if(pg->symbase == pg->chunkbase+4)
- {/* The whole current chunk is worthless (monster symbol spans a chunk) */
- tempbase = *(long**)pg->chunkbase; /* pointer to prev chunk */
- freeC(pg->category, pg->chunkbase);
- pg->chunkbase = (char *)tempbase;
- }
- /* Compute size of new chunk */
- if(pg->symspot >= TEXTCHUNK-5)
- chunksize = pg->symspot+TEXTCHUNK+5;
- else chunksize = TEXTCHUNK;
-
- tempbase = mallocC(pg->category, chunksize);
- *tempbase = (long)pg->chunkbase; /* pointer to prev chunk */
- pg->chunkbase = (char*)tempbase;
- pg->chunkend = pg->chunkbase+chunksize-1;
- memcpy(pg->chunkbase+4, pg->symbase, pg->symspot);
- pg->symbase = pg->chunkbase+4;
- pg->symend = pg->symbase+pg->symspot;
- *pg->symend++ = tok;
- *pg->symend = 0;
- ((char*)&pg->symhash)[pg->symspot++ & 3] ^= tok; /* running hash */
- }
- static inline void
- add_token(PG *pg, char tok)
- {
- if(pg->symend < pg->chunkend) {
- *pg->symend++ = tok;
- *pg->symend = 0;
- ((char*)&pg->symhash)[pg->symspot++ & 3] ^= tok; /* running hash */
- }
- else new_chunk(pg, tok);
- }
- static int
- do_lex (LTABLE *ltab)
- {
- short i, x;
- short rule;
- unsigned base;
- short state;
- int token;
- short stacktop;
- short *SS;
- PG *pg;
- int rulesize;
- int debug;
-
- pg = ltab->pg;
- SS = ltab->SS;
- state = ltab->state;
- token = ltab->token;
- debug = pg->debug & 2;
- #if DEBUG
- if(debug)cfprintf("LexSTART: char %c (0x%x)\n", token, token);
- #endif
- Scan:
- if(token < 0)
- {/* get new token */
- ltab->state = state;
- ltab->token = token;
- ltab->SS = SS;
- #if DEBUG
- if(debug)cfprintf("Lex: return for next char\n");
- #endif
- return(0);
- }
-
- /* Test for Shift, and Shift-Reduce */
-
- base = state * ltab->bitwords;
- if(BITSET(ltab->M_bits, base, token))
- {
- x = ltab->MT_tran[ ltab->MT_beg[state] + ltab->token];
- *++(SS) = state; /* Put state on parse stack.*/
- #if 0
- #if HOWBIG
- if((SS - ltab->SStop) > maxSS_lex)
- maxSS_lex = SS - ltab->SStop;
- #endif
- if (SS >= ltab->SSmax) /* If parse stack too large.*/
- {
- cfprintf("Lex: stack overflow \n");
- OXPORT_crash("");
- }
- #endif
- /* Put char in textchunk */
-
- add_token(pg, token);
- #if DEBUG
- if(debug)cfprintf("Lex consume char\n");
- #endif
- token = -1; /* Indicate token consumed */
- if(x > 0)
- {
- state = x;
- #if DEBUG
- if(debug)cfprintf("Lex: shift to state %d\n", state);
- #endif
- goto Scan; /* Shift only */
- }
- /* --- REDUCE -----------------------*/
-
- Neg: rule = -x; /* Make positive. */
- Reduce:
- rulesize = ltab->PL [rule] & 0x000f;
- if(rulesize == 15)
- rulesize = -1;
- SS -= rulesize;
- if(rulesize == -1)
- {
- *SS = state; /* Stack current state. */
- }
- stacktop = *SS;
- #if DEBUG
- if(debug)cfprintf("Lex: reduce to rule %d, new state is %d head=%d\n",
- rule, stacktop, ltab->Head[rule]);
- #endif
- if(rule <= ltab->TM)
- {
- ltab->lextoken = ltab->LGT[rule];
- state = 0;
- SS = ltab->SStop;
- if(ltab->lextoken > 0)
- {
- #if DEBUG
- if(debug)cfprintf("Lex: add symbol %s\n", pg->symbase);
- #endif
- pg->L_stack[pg->LSP] = NewParserSymbol(pg, pg->symbase);
-
- ltab->state = state;
- ltab->SS = SS;
- ltab->token = token;
- ltab->rule = rule;
- if(ltab->PL [rule] & PL_ACTION)
- {
- PACTIONS ap = &pg->ACTIONS[(ltab->PL[rule]>>7)&511];
- (*ap->func) (pg, ap->args);
- }
-
- if(ltab->lextoken > 0) {
- #if DEBUG
- if(debug)cfprintf("Lex: exit with token=%d\n", ltab->lextoken);
- #endif
- pg->LSP = (pg->LSP+1) & 3;
- pg->L_stack[pg->LSP] = ltab->lextoken;
- pg->LSP = (pg->LSP+1) & 3;
-
- return ltab->lextoken;
- }
- else
- {/* Token was cancelled by action */
- goto Scan;
- }
- }
- else
- {/* IGNORE rule */
- #if DEBUG
- if(debug)cfprintf("Lex: ignore rule %d\n", rule);
- #endif
- pg->symend = pg->symbase;
- pg->symhash = 0;
- pg->symspot = 0;
- goto Scan;
- }
- }
- /* Check non terminal transitions for current state */
-
- base = stacktop * ltab->bitwords;
- if(BITSET(ltab->M_bits, base, ltab->Head[rule]))
- {
- x = ltab->MN_tran[ltab->MN_beg[stacktop]+(ltab->Head[rule]-ltab->n_terms)];
- if(x > 0)
- {
- state = x;
- #if DEBUG
- if(debug)cfprintf("Lex: NT trans to state %d\n", state);
- #endif
- goto Scan;
- }
- #if DEBUG
- if(debug)cfprintf("Lex: NT reduce to rule %d, state=%d\n",-x, stacktop);
- #endif
- goto Neg;
- }
- #if DEBUG
- if(debug)cfprintf("Lex: NO nt tran for state %d\n",stacktop);
- #endif
- goto Scan;
-
- }/* END of shift/reduce test */
-
- /* Check for pure reductions */
- #if DEBUG
- if(debug)cfprintf("Lex: check reductions for state %d\n", state);
- #endif
- rule = ltab->D_red [state];
- if(rule >= 0) goto Reduce; /* Default reduction */
- if (rule == -32767)
- {
- pg->symspot = 0;
- pg->symhash = 0;
- pg->symend = pg->symbase;
- ltab->state = 0;
- ltab->SS = ltab->SStop;
- #if DEBUG
- if(debug)cfprintf("Lex: return ERROR\n");
- #endif
- return(-1);
- }
- #if DEBUG
- if(debug)cfprintf("Lex: Check multiple reductions in state %d\n", state);
- #endif
- /* Check multiple reductions */
- for (i = ltab->R_start [state]; i < ltab->R_start [state+1]; i++)
- {
- if (ltab->R_symbol [i] == token) /* Found? */
- {
- rule = ltab->R_prod [i];
- #if DEBUG
- if(debug)cfprintf("Lex: multiple reduction to rule %d token=%d\n", rule, token);
- #endif
- goto Reduce;
- }
- }
- rule = -rule; /* Multiple default. */
- #if DEBUG
- if(debug)cfprintf("Lex: use multiple default rule %d\n", rule);
- #endif
- goto Reduce;
-
- }/* END OF do_lex() */
-
- static short
- read_object(void *obj, PG *pg)
- {
- if(pg->obj_inbufcnt <= 0) {
- pg->obj_inbufsize =
- pg->obj_inbufcnt = (*pg->readfunc)(obj, pg->obj_inbuf, 128);
- }
- if(pg->obj_inbufcnt > 0 )
- return pg->obj_inbuf[pg->obj_inbufsize - pg->obj_inbufcnt--];
- return -1;
- }
-
- imethod int
- Parse(object self, void *is, char *filename)
- {
- PG *pg = (PG *)ivPtr(self);
- LTABLE *lp = pg->ltab;
- PTABLE *pp = pg->ptab;
- int debug = pg->debug & 4;
- int isobject;
-
- pg->in_file = is;
- if(IsObj((object)is))
- {
- isobject = 1;
- pg->readfunc = (void*)imiPointer((object)is, gRead);
- }
- else
- isobject = 0;
-
- for(;;)
- {
- short lextoken = 0;
- int result;
- /* Run the lexer */
- while(lextoken == 0)
- {
- if(lp->token < 0)
- {
- newchr:
- if(isobject)
- lp->token = read_object(is, pg);
- else
- lp->token = cfgetc(((cfFILE*)is));
-
- if(lp->token == 0)
- goto newchr;
- if(lp->token < 0)
- {/* EOF */
- lp->token = 0;
- }
- else lp->token &= lp->maxtoken;
- if(lp->token == '\n')
- {
- ++pg->line_numb;
- pg->line_char = 0;
- if(debug)
- cfeprintf("\n");
- }
- else if(lp->token == '\r')
- {
- goto newchr;
- }
- else
- {
- ++pg->line_char;
- if(debug)
- cfeprintf("%c", lp->token);
- }
- }
- lextoken = do_lex(lp);
- if(lextoken < 0)
- {
- return(lextoken);
- }
- }
- /* Run the parser */
- pp->token = lextoken;
- result = do_parse(pp);
- if(result)
- {
- if(result < 0)
- {
- return(1);
- }
- else
- {
- if(pg->root == 0)
- return 2;
- return(0);
- }
- }
- }
- }
-
- InitMethod()
- {
- if (CLASS)
- return;
- CLASS = gNew(Class, cName, ivSize, 0, END);
-
- cMethod(New);
- iMethod(New);
-
- iMethod(Parse);
- iMethod(Dispose);
- iMethodFor(gDeepDispose, Dispose);
- iMethodFor(gGCDispose, Dispose);
-
- gDontCollect(CLASS);
- }
- /* COMMON STUFF */
-
- static void
- LoadParserPointers(void *yp, LODTABLE *lp, int notlex)
- {
- char *xp = (char *) lp;
- PTABLE *pp = yp;
- #define SPOINTER(a) ((short *)(xp + lp->a))
- #define CPOINTER(a) ((char *)(xp + lp->a))
- #define LPOINTER(a) ((long *)(xp + lp->a))
- #define VALUE(a) ((short)(lp->a))
-
- pp->D_red = SPOINTER(t_D_red);
- pp->R_start = SPOINTER(t_R_start);
- pp->R_symbol = SPOINTER(t_R_symbol);
- pp->R_prod = SPOINTER(t_R_prod);
- pp->Head = SPOINTER(t_Head);
- pp->rBase = SPOINTER(t_rBase);
- pp->MT_beg = SPOINTER(t_MT_beg);
- pp->MT_tran = SPOINTER(t_MT_tran);
- pp->MN_beg = SPOINTER(t_MN_beg);
- pp->MN_tran = SPOINTER(t_MN_tran);
- pp->M_bits = SPOINTER(t_M_bits);
- pp->LGT = SPOINTER(t_LGT);
-
- pp->G_symbol = LPOINTER(t_G_symbol);
- pp->PL = SPOINTER(t_PL);
- pp->ACTIONS = LPOINTER(t_ACTIONS);
- pp->ACTIONSTRINGS = CPOINTER(t_ACTIONSTRINGS);
- pp->bitwords = VALUE(bitwords);
- pp->n_terms = VALUE(n_terms);
- pp->n_vars = VALUE(n_vars);
- pp->n_symbs = VALUE(n_symbs);
- pp->n_states = VALUE(n_states);
- pp->n_rules = VALUE(n_rules);
- pp->n_actions = VALUE(n_actions);
- pp->TM = VALUE(TM);
- pp->maxtoken = VALUE(maxtoken);
- pp->token = '\n';
-
- pp->SS = pp->SStop;
- pp->SSmax = pp->SStop + PARSER_STKSIZE - 2;
- if(notlex)
- {
- pp->NS = pp->NStop;
- pp->LS = pp->LStop;
- pp->Rs = pp->RStop;
- }
- }
-
- /* ========== Access to the parser file stack (nested includes) ==== */
- void
- ParserPush(PG *pg, int data)
- {
- if(pg->fstack_depth < 64)
- {
- pg->fstack[pg->fstack_depth++] = data;
- }
- }
- int
- ParserPop(PG *pg)
- {
- if(pg->fstack_depth > 0)
- {
- return pg->fstack[--pg->fstack_depth];
- }
- return 0;
- }
- int
- ParserStackdepth(PG *pg)
- {
- return pg->fstack_depth;
- }
- /* ================ END access to the parser file stack ================= */
-
- static void
- hash(void *key, KEY *cat)
- {
- cat->key = *((unsigned long *)key);
- cat->hv = (cat->key * 1103515245UL) + 12345;
- }
- static int
- lookup(PG *pg, char *name, void *result)
- {
- char *cp = name;
- unsigned long myhash = 0;
- unsigned int symspot = 0;
- PsymP sp;
- KEY cat;
- PbufP tbl = pg->symhandle;
-
- while(*cp) {
- ((char*)&myhash)[symspot++ & 3] ^= *cp++;
- }
- hash(&myhash, &cat);
- if((sp = tbl->bins[cat.hv % tbl->size]))
- {
- do
- {
- if( sp->cat.hv == cat.hv
- && sp->cat.key == cat.key)
- {
- /* Do final string check */
- if( sp->dat[1] != symspot
- || strcmp(PARSERSYMBOLS[sp->dat[0]].name, name))
- {
- continue;
- }
- *((PsymP *)result) = sp;
- return 1;
- }
- } while((sp = sp->next));
- }
- return 0;
- }
- int
- NewParserSymbol(PG *pg, const char *name)
- {
- KEY cat;
- PsymP *binp;
- PsymP sp;
- PbufP tbl = pg->symhandle;
- int symnum;
-
- if(name != pg->symbase)
- {/* From outside, add this symbol to the textchunk */
- const char *cp = name;
- while(*cp)
- add_token(pg, *cp++);
- }
- hash(&pg->symhash, &cat);
-
- binp = &(tbl->bins[cat.hv % tbl->size]);
-
- if((sp = *binp))
- {
- do
- {
- if( sp->cat.hv == cat.hv
- && sp->cat.key == cat.key)
- {
- /* Do final string check */
- if( sp->dat[1] != pg->symspot
- || strcmp(PARSERSYMBOLS[sp->dat[0]].name, name))
- {
- continue; /* NO MATCH */
- }
-
- /* FOUND */
- /* Flush the string which was built up in the text chunk */
- pg->symend = pg->symbase;
- pg->symspot = 0;
- pg->symhash = 0;
-
- /* Return data stored in the symbol table */
- pg->lastsymnum = sp->dat[0];
- pg->lastclass = sp->dat[2];
- return sp->dat[0];
- }
- } while((sp = sp->next));
- }
-
- /* NOT FOUND, ENTER A NEW SYMBOL */
- symnum = pg->pst.cnt;
- if(symnum && ((symnum % SYMBOLCHUNK) == 0))
- {/* Allocate more contiguous symbol string pointer space */
- PARSERSYMBOLS = reallocC(pg->category, PARSERSYMBOLS,
- (symnum*sizeof(PARSER_SYMBOL))+(SYMBOLCHUNK*sizeof(PARSER_SYMBOL)));
- }
- /* link new symbol to front of bin */
- sp = (PsymP)NewAstNode(pg, 0, 0);
- if((sp->next = *binp) != 0)
- ++pg->hashdups;
- *binp = sp;
- tbl->lastbin = binp; /* used for DelLastParserSymbol */
-
- /* Put data in symbol chunk */
- sp->dat[0] = symnum; /* symbol number */
- sp->dat[1] = pg->symspot; /* length of symbol */
- sp->cat = cat; /* hashing info */
-
- /* Accept the string which was built up in the text chunk */
- PARSERSYMBOLS[symnum].name = pg->symbase; /* save pointer to the string */
- pg->pst.cnt += 1;
- pg->totsymlen += pg->symspot+1;
-
- pg->symbase = ++pg->symend;
- pg->symspot = 0;
- pg->symhash = 0;
-
- /* Return new data */
- pg->lastsymnum = symnum;
- pg->lastclass = 0;
- return symnum;
- }
- void
- DelLastParserSymbol(PG *pg)
- {
- if(pg->pst.cnt > 0)
- {
- void *binp;
- if((binp = ((PbufP)pg->symhandle)->lastbin))
- {
- PsymP p = *((PsymP *)binp);
- pg->totsymlen -= p->dat[1]+1;
- pg->pst.cnt -= 1;
- *((PsymP *)binp) = p->next;
- FreeAstNode(pg, (AstP)p);
- ((PbufP)pg->symhandle)->lastbin = 0;
- }
- }
- }
- char *
- GetH_symbol(PG *pg, int numb)
- {
- PTABLE *pp = pg->ptab;
- long *symbase = pp->G_symbol;
- char *symptr = (char *)symbase;
-
- return symptr + symbase[numb];
- }
- AstP
- NewAstNode(PG *pg, int id, int symb)
- {
- AstP node;
- if(pg->pat.freecnt > 0)
- {
- node = pg->pat.free;
- pg->pat.free = node->down;
- node->down = 0;
- }
- else
- {
- int i;
- AstP fnode;
- node = callocC(pg->category, 1, ASTCHUNK*ASTSIZE);
- pg->pat.cnt += ASTCHUNK;
- pg->pat.freecnt = ASTCHUNK;
- pg->pat.free = (AstP)(((char*)node)+ASTSIZE);
- fnode = (AstP)(((char*)node)+ASTSIZE);
- for(i = 1; i < ASTCHUNK-1; ++i)
- {
- fnode->down = (AstP)(((char*)fnode)+ASTSIZE);
- fnode = fnode->down;
- }
- }
- node->id = id;
- node->symb = symb;
- --pg->pat.freecnt;
- return node;
- }
- void
- FreeAstNode(PG *pg, AstP node)
- {
- if(node > ASTMINADDR)
- {
- memclr(node, ASTSIZE);
- node->down = pg->pat.free;
- pg->pat.free = node;
- ++pg->pat.freecnt;
- }
- }
- void
- PruneAstTree(PG *pg, AstP root, int preserve_root, const AstP top)
- {
- ASTVARS(256);
- int at_top = 1;
-
- if(root > ASTMINADDR)
- {
- if(top > ASTMINADDR)
- at_top = 0;
- curnode = root;
- MARK(stack);
- while(curnode = BOTTOMUP(curnode)) {
- if(!at_top)
- {
- if(curnode == top) {
- at_top = 1;
- continue;
- }
- }
- if(preserve_root && curnode == root)
- break;
- if(at_top)
- FreeAstNode(pg, curnode);
- }
- }
- }
-
-
- /*--- Print Abstract Syntax Tree - courtesy of Paul Mann ------------------ */
-
- static void
- prt_node (char *indent, AstP node, PG *pg, void *file, int ptrs)
- {
- char *nodename;
-
- if(node->id == 0)
- nodename = "NullNode";
- else
- nodename = GetH_symbol(pg, node->id>>6);
-
- if(ptrs) {
- if(node->right < ASTMINADDR)
- (*pg->writefunc) (file, " %6x %6d %6x %s%s_%d",
- node, node->lineno, node->down, indent, nodename, node->id & 0x3f);
- else
- (*pg->writefunc) (file, " %6x %6x %6x %s%s_%d",
- node, node->right, node->down, indent, nodename, node->id & 0x3f);
- }
- else
- (*pg->writefunc) (file, "%s%s_%d", indent, nodename, node->id & 0x3f);
-
- if (node->symb > 0)
- {
- char *symbname = PARSERSYMBOLS [node->symb].name;
-
- if(symbname)
- {
- if(*symbname != EOF_MARK)
- (*pg->writefunc) (file, " %s", symbname);
- if(node->Tindx)
- {
- symbname = PARSERSYMBOLS [node->Tindx].name;
- (*pg->writefunc) (file, " %s", symbname);
- }
- }
- else (*pg->writefunc) (file, " [%d]", node->symb);
- }
- (*pg->writefunc) (file, "\n");
- }
- static void
- traverse (char *indent, AstP node, PG *pg, void *file, int ptrs)
- {
- while (node->down)
- {
- strcat (indent, "├─");
- prt_node (indent, node, pg, file, ptrs);
- indent [strlen(indent)-2] = 0; /* BACK UP */
- if (node->right > ASTMINADDR)
- {
- strcat (indent, "│ ");
- traverse (indent, node->right, pg, file, ptrs);
- indent [strlen(indent)-2] = 0; /* BACK UP */
- }
- node = node->down;
- }
-
- /* Last node on this level. */
- strcat (indent, "└─");
- prt_node (indent, node, pg, file, ptrs);
- indent [strlen(indent)-2] = 0;
- if (node->right > ASTMINADDR)
- {
- strcat (indent, "· ");
- traverse (indent, node->right, pg, file, ptrs);
- indent [strlen(indent)-2] = 0;
- }
- }
-
- void
- PrintAst (PG *pg, const AstP root, void *file, int ptrs)
- {
- char indent [512];
- indent[0] = '\0';
-
- if(IsObj(file))
- {
- pg->writefunc = (void*)imiPointer((object)file, gPrintf);
- }
- else
- {
- pg->writefunc = (void*)cffprintf;
- }
- if (root)
- {
- if(ptrs) (*pg->writefunc) (file, " numb right down\n");
- traverse (indent, root, pg, file, ptrs);
- }
- else (*pg->writefunc) (file, " No AST available.\n");
- (*pg->writefunc) (file, "\n");
- }
-
-
- #if HOWBIG
- void
- HowBigAst(PG *pg, void *file)
- {
- if(IsObj(file))
- {
- pg->writefunc = (void*)imiPointer((object)file, gPrintf);
- }
- else pg->writefunc = (void*)cffprintf;
-
- (*pg->writefunc) (file,"xx=%d SSp=%d SSl=%d NS=%d LS=%d RS=%d\nn_nodes=%d nsyms=%d hdups=%d\n",
- maxXX_parse, maxSS_parse, maxSS_lex, maxNS_parse,
- maxLS_parse, maxRS_parse, pg->pat.cnt - pg->pat.freecnt,
- pg->pst.cnt - pg->ptab->n_terms, pg->hashdups);
- }
- #endif
-
- /*--- Scan Within an AST from the top down ------------------------------ */
- #define PUSH(sp) (*(++(*sp)))
- #define POP(sp) (*((*sp)--))
- AstP
- AstTopDown(AstP **sp, const AstP curnode, PG *pg)
- {
- AstP temp;
-
- if(curnode <= ASTMINADDR)
- {
- if((temp = STACKTOP(sp)))
- {
- if(NODEDOWN(STACKTOP(sp)))
- STACKTOP(sp) = NODEDOWN(STACKTOP(sp));
- else (void)POP(sp);
- }
- else (void)POP(sp);
- }
- else if(NODERIGHT(curnode) > ASTMINADDR)
- {
- if(NODEDOWN(NODERIGHT(curnode)))
- PUSH(sp) = NODEDOWN(NODERIGHT(curnode));
- temp = NODERIGHT(curnode);
- }
- else
- {
- if((temp = POP(sp))) {/* Keep these braces, compiler opti bug */
- if(NODEDOWN(temp)) {
- PUSH(sp) = NODEDOWN(temp);
- }
- }
- }
- if(temp > ASTMINADDR)
- {
- if(temp->id == pg->blockinID)
- pg->blocklevel++;
- else if(temp->id == pg->blockoutID)
- pg->blocklevel--;
- }
- return temp;
- }
- /*--- Scan Within an AST from the bottom up ------------------------------- */
- /* Subroutine for bottom up */
- static __inline__ AstP
- bu_follow(AstP **sp, AstP curnode)
- {
- if(NODEDOWN(curnode))
- PUSH(sp) = NODEDOWN(curnode);
- if(NODERIGHT(curnode) > ASTMINADDR)
- return NODERIGHT(curnode);
- return POP(sp);
- }
-
- AstP
- AstBottomUp(AstP **sp, const AstP start_node, PG *pg)
- {
- AstP temp;
- if(STACKTOP(sp) == (AstP)0)
- {/* First entry from a MARK(sp), find the bottom of this thread */
- AstP *stack;
- AstP *nexts = calloc(1, 4000);
- AstP curnode = start_node;
- AstP stop_node = NODEDOWN(start_node);
-
- PUSH(sp) = (AstP)-1; /* Mark the top */
- stack = nexts;
- *stack++ = (AstP)0;
- for(;;)
- {
- curnode = bu_follow(&stack, curnode);
- if(curnode == (AstP)0 || curnode == stop_node)
- break;
- PUSH(sp) = curnode;
- }
- free(nexts);
- }
- if(STACKTOP(sp) == (AstP)-1)
- {/* Hit the mark */
- (void)POP(sp); /* Clear it -- next should (better!) be a 0 */
- }
- temp = POP(sp);
- if(temp > ASTMINADDR)
- {
- if(temp->id == pg->blockinID)
- pg->blocklevel--;
- else if(temp->id == pg->blockoutID)
- pg->blocklevel++;
- }
- return temp;
- }
- int
- AstPackSize(PG *pg)
- {
- int astsize = ASTSIZE*(pg->pat.cnt-pg->pat.freecnt);
- int symptrsize = pg->pst.cnt*sizeof(PARSER_SYMBOL);
- int bufsize = sizeof(PG) + symptrsize + astsize + pg->totsymlen;
-
- bufsize += (bufsize&3) ? 4-(bufsize&3) : 0;
- return bufsize;
- }
- void *
- PackAst(PG *pg, void *buf)
- {
- ASTVARS(256);
- PG *pk;
- int astsize;
- int symptrsize;
- AstP pnode;
- PARSER_SYMBOL *pptr;
- char *ptext;
- int i, xx, recovered;
- AstP ddstack[256];
- AstP *dstack = ddstack;
-
- astsize = ASTSIZE*(pg->pat.cnt-pg->pat.freecnt);
- symptrsize = pg->pst.cnt*sizeof(PARSER_SYMBOL);
- pk = buf;
- if(pk == NULL)
- {
- int bufsize =
- sizeof(PG) + symptrsize + astsize + pg->totsymlen;
-
- bufsize += (bufsize&3) ? 4-(bufsize&3) : 0;
- pk = calloc(1,bufsize);
- }
- memcpy(pk, pg, sizeof(PG));
- pk->pat.freecnt = 0;
- pk->pat.free = 0;
- pnode = (AstP)((char*)pk + sizeof(PG)); /* ast nodes */
- pptr = (PARSER_SYMBOL*)((char *)pnode + astsize); /* symbol pointers */
- ptext = (char *)pptr + symptrsize; /* symbol text */
- pk->pst.ptr = pptr;
- pk->root = pnode;
-
- /* MOVE THE SYMBOL POINTERS AND STRINGS */
- for(i = 0; i < pg->pst.cnt; ++i)
- {
- pptr[i].name = ptext;
- xx = _strcpy(ptext, pg->pst.ptr[i].name);
- ptext += xx + 1;
- }
-
- /* MOVE THE NODES */
- MARKAST;
- recovered = 0;
- curnode = pg->root;
- *pnode = *curnode;
-
- if(curnode->down)
- *(++dstack) = pnode;
- if(curnode->right > ASTMINADDR) {
- pnode->right = pnode+1;
- ++pnode;
- }
- else {
- ++pnode;
- recovered = 1;
- }
- while(DOWNAST)
- {
- *pnode = *curnode;
- if(recovered) {
- AstP prev = *dstack--;
- prev->down = pnode;
- recovered = 0;
- }
- if(curnode->down) {
- *(++dstack) = pnode;
- }
- if(curnode->right > ASTMINADDR) {
- pnode->right = pnode+1;
- ++pnode;
- } else {
- ++pnode;
- recovered = 1;
- }
- }
- return pk;
- }
-
- /* ----- PARSER ACTIONS AVAILABLE TO GRAMMAR WRITERS ----- */
-
- /*
- Standard action which does nothing.
- */
- static void
- nullaction(PG *pg, long *args)
- {
- return;
- }
- /*
- Standard action to classify a symbol -- called from the parser
- arg[0] is the argcnt;
- arg[1] is the type of branch to look for (terminal index)
- arg[2] is an optional branch(1) to the right (nodeid)
- arg[3] is an alternate optional branch(2) to the right (nodeid)
- arg[4] if branch(1) branch again if encountered (nodeid)
- arg[5] if branch(1) terminate here and check leaf (nodeid)
- arg[6] is the type of leaf to look for (terminal index)
- arg[7] is the classification to apply
- arg[8] is the sub classification (a shift count)
-
- Apply the classification codes to the high 32 bits of the
- symbol item in the database.
- */
- static void
- classify(PG *pg, long *args)
- {
- AstP curnode = pg->ptab->node;
- AstP inode;
-
- if(args[0] != 8)
- {
- pg->actionerr = "classify: incorrect number of args.";
- return;
- }
- if((curnode = curnode->right) < ASTMINADDR)
- return;
- if(curnode->Tindx != args[1])
- return;
-
- while(curnode && (curnode = curnode->down))
- {
- if ((curnode->id & 0xffc0) == args[2])
- {/* InitDeclarator */
- inode = curnode->right;
- do {
- if(inode->id == args[4]) /* ParenDeclarator */
- inode = inode->right;
- if(inode->id == args[5]) /* DeclID */
- {
- unsigned short *item;
- if(lookup(pg, PARSERSYMBOLS[inode->symb].name, &item))
- {
- if(item[2] == 0)
- { /* don't re-classify */
- item[2] = (unsigned short)args[7];/* class */
- item[3] |= (unsigned short)(1<<(args[8]-args[7]-1));/* sub-class */
- }
- }
- else
- {
- pg->actionerr = "classify: symbol not found.";
- }
- }
- } while((inode = inode->down));
- }
- else if ((curnode->id & 0xffc0) == args[3])
- {/* TypeAgain */
- inode = curnode->right;
- do {
- if(inode->Tindx == args[6]) /* <identifier> */
- {
- unsigned short *item;
- if(lookup(pg, PARSERSYMBOLS[inode->symb].name, &item))
- {
- if(item[2] == 0)
- { /* don't re-classify */
- item[2] = (unsigned short)args[7];/* class */
- item[3] |= (unsigned short)(1<<(args[8]-args[7]-1));/* sub-class */
- }
- }
- else
- {
- pg->actionerr = "classify: symbol not found.";
- }
- }
- } while((inode = inode->down));
- }
- else continue;
- }
- }
-
- /*
- Standard action to require a particular subclass of a classified symbol.
- */
- static void
- require(PG *pg, long *args)
- {
- AstP curnode = pg->ptab->node;
- int ok = 0;
-
- if(args[0] != 2)
- {
- pg->actionerr = "require: incorrect number of args.";
- return;
- }
-
- if(curnode->Tindx == args[1])
- {
- ok = 1;
- }
- else
- {
- if((curnode = curnode->right) > ASTMINADDR)
- if(curnode->Tindx == args[1])
- ok = 1;
- }
- while(ok)
- {
- unsigned short *item;
- if(lookup(pg, PARSERSYMBOLS[curnode->symb].name, &item))
- {
- if(item[2] == (unsigned short)args[1])
- {
- if(!(item[3] & (unsigned short)(1<<(args[2]-args[1]-1))))
- pg->actionerr = "require: symbol not member of subclass.";
- }
- else
- {
- pg->actionerr = "require: symbol not classified correctly.";
- }
- }
- else
- {
- pg->actionerr = "require: symbol not found.";
- }
- break;
- }
- if(!ok)
- {
- pg->actionerr = "require: invalid ast configuration.";
- }
- }
- /*
- Standard lexical action to handle the '#line' directive.
- #line 123 "filename" [flagchar] [identchar]
- */
- static void
- doline(PG *pg, long *args)
- {
- char *lnbeg;
- char *fnbeg;
- char *fnend;
- int newfile = 0;
-
- pg->ltab->lextoken = 0; /* kill the token */
- lnbeg = strchr(PARSERSYMBOLS[pg->lastsymnum].name, 'e');
- DelLastParserSymbol(pg); /* The whole line was entered as a symbol */
- if(lnbeg)
- {
- pg->line_numb = atol(++lnbeg); /* Current line number */
- if((fnbeg = strchr(lnbeg, '"'))) /* Check for filename */
- {
- if((fnend = strrchr(fnbeg+1, '"')))
- {
- char *flbeg = fnend+1;
-
- while(*flbeg && !isdigit(*flbeg)) ++flbeg;
- if(*flbeg)
- {
- if(*flbeg == '1')
- {/* enter file */
- goto enter_file;
- }
- else if(*flbeg == '2')
- {/* leave file */
- pg->line_file = ParserPop(pg);
- return;
- }
- }
- /* '3' or 0 in the first flag field */
- if(pg->line_file > 0)
- return ;
- enter_file:
- *fnbeg = '{'; /* Ensure uniqueness of the symbol */
- *fnend++ = '}';
- *fnend = 0;
- pg->curfile = NewParserSymbol(pg, fnbeg);
- if(pg->curfile > pg->maxfile)
- {
- pg->maxfile = pg->curfile;
- pg->files[++pg->numfiles] = (short)pg->curfile;
- newfile = pg->numfiles;
- }
- else
- {
- int i;
- for(i = 1; i <= pg->numfiles; ++i) {
- if(pg->curfile == pg->files[i]) {
- newfile = i;
- break;
- }
- }
- }
- if(pg->line_file)
- ParserPush(pg, pg->line_file);
- pg->line_file = newfile;
- } /* END: fnbeg == '"' */
- } /* END: fnend == '"' */
- } /* END: lnbeg */
- }
-
- /*
- Standard lexical action to convert symbols to terminals of the grammar.
- It is usually called when <identifier> or some such is detected.
- The symbol has already been entered in the symbol table (which was
- filled with the terminals of the grammar at init time). If the
- symbol number is less than the number of grammar terminals, then
- this symbol is a reserved word, the token for which is not <identifier>
- but the symbol number itself. Other <identifier> symbols may
- have been classified (such as {typedef-name} or {class-name}).
- */
- static void
- dyntoken(PG *pg, long *args )
- {
- int symnum = pg->L_stack[pg->LSP];
-
- if(symnum < pg->ptab->n_terms)
- {/* This symbol really a reserved word */
- pg->ltab->lextoken = symnum;
- }
- else if(pg->lastclass)
- {/* This symbol has been classified */
- pg->ltab->lextoken = pg->lastclass;
- }
- }
-