NetBSD/sys/netiso/xebec/llparse.c
2001-11-13 00:56:55 +00:00

381 lines
7.3 KiB
C

/* $NetBSD: llparse.c,v 1.6 2001/11/13 01:10:52 lukem Exp $ */
/*
* ************************* NOTICE *******************************
* This code is in the public domain. It cannot be copyrighted.
* This ll parser was originally written by Keith Thompson for the
* University of Wisconsin Crystal project.
* It was based on an FMQ lr parser written by Jon Mauney at the
* University of Wisconsin.
* It was subsequently modified very slightly by Nancy Hall at the
* University of Wisconsin for the Crystal project.
* ****************************************************************
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: llparse.c,v 1.6 2001/11/13 01:10:52 lukem Exp $");
#include "xebec.h"
#include "llparse.h"
#include "main.h"
#include <stdio.h>
#include "debug.h"
#define LLMINACTION -LLINF
short llparsestack[STACKSIZE];
short llstackptr = 0;
LLtoken lltoken;
void prt_token();
int
llparse()
{
register int havetoken = FALSE;
register int sym;
register LLtoken *t = &lltoken;
register int parseaction;
register int accepted = FALSE;
llpushprod(llnprods-1); /* $$$ ::= <start symbol> */
do {
sym = llparsestack[llstackptr];
IFDEBUG(L)
printf("llparse() top of loop, llstackptr=%d, sym=%d\n",
llstackptr, sym);
ENDDEBUG
if(sym < 0) {
/* action symbol */
if(sym <= LLMINACTION) {
for(;sym<=LLMINACTION;sym++) {
llaction(1, t); /* calls llfinprod */
}
llstackptr--;
continue;
} else { llaction(-sym, t);
llstackptr--;
continue;
}
}
if(sym < llnterms) {
/* it's a terminal symbol */
if(!havetoken) {
llgettoken(t);
havetoken = TRUE;
}
if(sym == t->llterm) {
llpushattr(t->llattrib);
llaccept(t);
llstackptr--; /* pop terminal */
if(t->llterm == llnterms-1) { /* end symbol $$$ */
accepted = TRUE;
} else {
havetoken = FALSE;
}
} else {
llparsererror(t); /* wrong terminal on input */
havetoken = FALSE;
}
continue;
}
/* non terminal */
if(!havetoken) {
llgettoken(t);
havetoken = TRUE;
}
/* consult parse table for new production */
parseaction = llfindaction(sym, t->llterm);
if(parseaction == 0) {
/* error entry */
llparsererror(t);
havetoken = FALSE;
continue;
}
if(llepsilon[parseaction]) {
/* epsilon production */
if(llepsilonok(t->llterm)) {
llstackptr--; /* pop nonterminal */
llpushprod(parseaction); /* push rhs of production */
} else {
llparsererror(t);
havetoken = FALSE;
}
} else {
llstackptr--; /* pop nonterminal */
llpushprod(parseaction); /* push rhs of production */
}
} while(!accepted);
return(0);
}
void
llpushprod(prod) /* recognize production prod - push rhs on stack */
short prod;
{
register int start;
register int length;
register int count;
start = llprodindex[prod].llprodstart;
length = llprodindex[prod].llprodlength;
IFDEBUG(L)
printf("llpushprod(%d) llstackptr=0x%x(%d), length = 0x%x(%d)\n",
prod, llstackptr, llstackptr, length , length);
/*
dump_parse_stack();
*/
ENDDEBUG
if(llstackptr+length >= STACKSIZE) {
fprintf(stderr,"Parse stack overflow. llstackptr=0x%x, length=0x%x\n",
llstackptr, length);
Exit(-1);
}
llsetattr(llprodindex[prod].llprodtlen);
/* put a marker on the stack to mark beginning of production */
if(llparsestack[llstackptr] <= LLMINACTION) {
(llparsestack[llstackptr]) --; /* if there's already one there, don't
put another on; just let it represent all of
the adjacent markers */
}
else {
llstackptr++;
llparsestack[llstackptr] = LLMINACTION;
}
for(count=0; count<length; count++) {
llstackptr++;
llparsestack[llstackptr] = llproductions[start++];
}
if(llstackptr > STACKSIZE) {
fprintf(stderr, "PARSE STACK OVERFLOW! \n"); Exit(-1);
Exit(-1);
}
}
int
llepsilonok(term)
{
register int ptr;
register int sym;
register int pact;
register int nomore;
register int rval;
IFDEBUG(L)
printf("llepsilonok() enter\n");
ENDDEBUG
rval = TRUE;
ptr = llstackptr;
do {
sym = llparsestack[ptr];
if(sym < 0) {
ptr--;
nomore = ptr == 0;
continue;
}
if(sym < llnterms) {
nomore = TRUE;
rval = sym == term;
continue;
}
pact = llfindaction(sym, term);
if(pact == 0) {
nomore = TRUE;
rval = FALSE;
continue;
}
if(llepsilon[pact] == TRUE) {
ptr--;
nomore = ptr == 0;
}
else {
nomore = TRUE;
}
} while(!nomore);
return(rval);
}
short
llfindaction(sym, term)
{
register int index;
IFDEBUG(L)
printf("llfindaction(sym=%d, term=%d) enter \n", sym, term);
ENDDEBUG
index = llparseindex[sym];
while(llparsetable[index].llterm != 0) {
if(llparsetable[index].llterm == term) {
return(llparsetable[index].llprod);
}
index++;
}
return(0);
}
void
llparsererror(token)
LLtoken *token;
{
IFDEBUG(L)
fprintf(stderr,"llparsererror() enter\n");
prt_token(token);
ENDDEBUG
fprintf(stderr, "Syntax error: ");
prt_token(token);
dump_buffer();
Exit(-1);
}
void
llgettoken(token)
LLtoken *token;
{
llscan(token);
token->llstate = NORMAL;
IFDEBUG(L)
printf("llgettoken(): ");
prt_token(token);
ENDDEBUG
}
/******************************************************************************
Attribute support routines
******************************************************************************/
/*
** attribute stack
**
** AttrStack = stack of record
** values : array of values;
** ptr : index;
** end;
**
*/
LLattrib llattributes[LLMAXATTR];
int llattrtop = 0;
struct llattr llattrdesc[LLMAXDESC];
int lldescindex = 1;
void
llsetattr(n)
int n;
{
register struct llattr *ptr;
IFDEBUG(L)
printf("llsetattr(%d) enter\n",n);
ENDDEBUG
if(lldescindex >= LLMAXDESC) {
fprintf(stdout, "llattribute stack overflow: desc\n");
fprintf(stdout,
"lldescindex=0x%x, llattrtop=0x%x\n",lldescindex, llattrtop);
Exit(-1);
}
ptr = &llattrdesc[lldescindex];
ptr->llabase = &llattributes[llattrtop];
ptr->lloldtop = ++llattrtop;
ptr->llaindex = 1;
ptr->llacnt = n+1; /* the lhs ALWAYS uses an attr; it remains on the
stack when the production is recognized */
lldescindex++;
}
void
llpushattr(attr)
LLattrib attr;
{
struct llattr *a;
IFDEBUG(L)
printf("llpushattr() enter\n");
ENDDEBUG
if(llattrtop + 1 > LLMAXATTR) {
fprintf(stderr, "ATTRIBUTE STACK OVERFLOW!\n");
Exit(-1);
}
a = &llattrdesc[lldescindex-1];
llattributes[llattrtop++] = attr;
a->llaindex++; /* inc count of attrs on the stack for this prod */
}
void
llfinprod()
{
IFDEBUG(L)
printf("llfinprod() enter\n");
ENDDEBUG
lldescindex--;
llattrtop = llattrdesc[lldescindex].lloldtop;
llattrdesc[lldescindex-1].llaindex++; /* lhs-of-prod.attr stays on
the stack; it is now one of the rhs attrs of the now-top production
on the stack */
}
#ifndef LINT
#ifdef DEBUG
void
dump_parse_stack()
{
int ind;
printf("PARSE STACK:\n");
for(ind=llstackptr; ind>=0; ind--) {
printf("%d\t%d\t%s\n",
ind, llparsestack[ind],
llparsestack[ind]<0? "Action symbol" : llstrings[llparsestack[ind]]);
}
}
#endif DEBUG
#endif LINT
void
prt_token(t)
LLtoken *t;
{
fprintf(stdout, "t at 0x%p\n", t);
fprintf(stdout, "t->llterm=0x%x\n", t->llterm); (void) fflush(stdout);
fprintf(stdout, "TOK: %s\n", llstrings[t->llterm]);
(void) fflush(stdout);
#ifdef LINT
/* to make lint shut up */
fprintf(stdout, "", llnterms, llnsyms, llnprods, llinfinite);
#endif LINT
}