📄 lemon.c
字号:
spy = apy->x.rp->precsym; if( spy==0 || spx->prec<0 || spy->prec<0 ){ /* Not enough precedence information. */ apy->type = CONFLICT; errcnt++; }else if( spx->prec>spy->prec ){ /* Lower precedence wins */ apy->type = RD_RESOLVED; }else if( spx->prec<spy->prec ){ apx->type = SH_RESOLVED; }else if( spx->prec==spy->prec && spx->assoc==RIGHT ){ /* Use operator */ apy->type = RD_RESOLVED; /* associativity */ }else if( spx->prec==spy->prec && spx->assoc==LEFT ){ /* to break tie */ apx->type = SH_RESOLVED; }else{ assert( spx->prec==spy->prec && spx->assoc==NONE ); apy->type = CONFLICT; errcnt++; } }else if( apx->type==REDUCE && apy->type==REDUCE ){ spx = apx->x.rp->precsym; spy = apy->x.rp->precsym; if( spx==0 || spy==0 || spx->prec<0 || spy->prec<0 || spx->prec==spy->prec ){ apy->type = CONFLICT; errcnt++; }else if( spx->prec>spy->prec ){ apy->type = RD_RESOLVED; }else if( spx->prec<spy->prec ){ apx->type = RD_RESOLVED; } }else{ /* Can't happen. Shifts have to come before Reduces on the ** list because the reduces were added last. Hence, if apx->type==REDUCE ** then it is impossible for apy->type==SHIFT */ } return errcnt;}/********************* From the file "configlist.c" *************************//*** Routines to processing a configuration list and building a state** in the LEMON parser generator.*/static struct config *freelist = 0; /* List of free configurations */static struct config *current = 0; /* Top of list of configurations */static struct config **currentend = 0; /* Last on list of configs */static struct config *basis = 0; /* Top of list of basis configs */static struct config **basisend = 0; /* End of list of basis configs *//* Return a pointer to a new configuration */PRIVATE struct config *newconfig(void){ struct config *new; if( freelist==0 ){ int i; int amt = 3; freelist = (struct config *)malloc( sizeof(struct config)*amt ); if( freelist==0 ){ fprintf(stderr,"Unable to allocate memory for a new configuration."); exit(1); } for(i=0; i<amt-1; i++) freelist[i].next = &freelist[i+1]; freelist[amt-1].next = 0; } new = freelist; freelist = freelist->next; return new;}/* The configuration "old" is no longer used */PRIVATE void deleteconfig(struct config *old){ old->next = freelist; freelist = old;}/* Initialized the configuration list builder */void Configlist_init(void){ current = 0; currentend = ¤t; basis = 0; basisend = &basis; Configtable_init(); return;}/* Initialized the configuration list builder */void Configlist_reset(void){ current = 0; currentend = ¤t; basis = 0; basisend = &basis; Configtable_clear(0); return;}/* Add another configuration to the configuration list */struct config *Configlist_add( struct rule *rp, /* The rule */ int dot) /* Index into the RHS of the rule where the dot goes */{ struct config *cfp, model; assert( currentend!=0 ); model.rp = rp; model.dot = dot; cfp = Configtable_find(&model); if( cfp==0 ){ cfp = newconfig(); cfp->rp = rp; cfp->dot = dot; cfp->fws = SetNew(); cfp->stp = 0; cfp->fplp = cfp->bplp = 0; cfp->next = 0; cfp->bp = 0; *currentend = cfp; currentend = &cfp->next; Configtable_insert(cfp); } return cfp;}/* Add a basis configuration to the configuration list */struct config *Configlist_addbasis(struct rule *rp, int dot){ struct config *cfp, model; assert( basisend!=0 ); assert( currentend!=0 ); model.rp = rp; model.dot = dot; cfp = Configtable_find(&model); if( cfp==0 ){ cfp = newconfig(); cfp->rp = rp; cfp->dot = dot; cfp->fws = SetNew(); cfp->stp = 0; cfp->fplp = cfp->bplp = 0; cfp->next = 0; cfp->bp = 0; *currentend = cfp; currentend = &cfp->next; *basisend = cfp; basisend = &cfp->bp; Configtable_insert(cfp); } return cfp;}/* Compute the closure of the configuration list */void Configlist_closure(struct lemon *lemp){ struct config *cfp, *newcfp; struct rule *rp, *newrp; struct symbol *sp, *xsp; int i, dot; assert( currentend!=0 ); for(cfp=current; cfp; cfp=cfp->next){ rp = cfp->rp; dot = cfp->dot; if( dot>=rp->nrhs ) continue; sp = rp->rhs[dot]; if( sp->type==NONTERMINAL ){ if( sp->rule==0 && sp!=lemp->errsym ){ ErrorMsg(lemp->filename,rp->line,"Nonterminal \"%s\" has no rules.", sp->name); lemp->errorcnt++; } for(newrp=sp->rule; newrp; newrp=newrp->nextlhs){ newcfp = Configlist_add(newrp,0); for(i=dot+1; i<rp->nrhs; i++){ xsp = rp->rhs[i]; if( xsp->type==TERMINAL ){ SetAdd(newcfp->fws,xsp->index); break; }else{ SetUnion(newcfp->fws,xsp->firstset); if( xsp->lambda==BOOL_FALSE ) break; } } if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp); } } } return;}/* Sort the configuration list */void Configlist_sort(void){ current = (struct config *)msort((char *)current,(char **)&(current->next),Configcmp); currentend = 0; return;}/* Sort the basis configuration list */void Configlist_sortbasis(void){ basis = (struct config *)msort((char *)current,(char **)&(current->bp),Configcmp); basisend = 0; return;}/* Return a pointer to the head of the configuration list and** reset the list */struct config *Configlist_return(void){ struct config *old; old = current; current = 0; currentend = 0; return old;}/* Return a pointer to the head of the configuration list and** reset the list */struct config *Configlist_basis(void){ struct config *old; old = basis; basis = 0; basisend = 0; return old;}/* Free all elements of the given configuration list */void Configlist_eat(struct config *cfp){ struct config *nextcfp; for(; cfp; cfp=nextcfp){ nextcfp = cfp->next; assert( cfp->fplp==0 ); assert( cfp->bplp==0 ); if( cfp->fws ) SetFree(cfp->fws); deleteconfig(cfp); } return;}/***************** From the file "error.c" *********************************//*** Code for printing error message.*//* Find a good place to break "msg" so that its length is at least "min"** but no more than "max". Make the point as close to max as possible.*/static int findbreak(char *msg, int min, int max){ int i,spot; char c; for(i=spot=min; i<=max; i++){ c = msg[i]; if( c=='\t' ) msg[i] = ' '; if( c=='\n' ){ msg[i] = ' '; spot = i; break; } if( c==0 ){ spot = i; break; } if( c=='-' && i<max-1 ) spot = i+1; if( c==' ' ) spot = i; } return spot;}/*** The error message is split across multiple lines if necessary. The** splits occur at a space, if there is a space available near the end** of the line.*/#define ERRMSGSIZE 10000 /* Hope this is big enough. No way to error check */#define LINEWIDTH 79 /* Max width of any output line */#define PREFIXLIMIT 30 /* Max width of the prefix on each line */void ErrorMsg(char *filename, int lineno, char *format, ...){ char errmsg[ERRMSGSIZE]; char prefix[PREFIXLIMIT+10]; int errmsgsize; int prefixsize; int availablewidth; va_list ap; int end, restart, base; va_start(ap, format); /* Prepare a prefix to be prepended to every output line */ if( lineno>0 ){ sprintf(prefix,"%.*s:%d: ",PREFIXLIMIT-10,filename,lineno); }else{ sprintf(prefix,"%.*s: ",PREFIXLIMIT-10,filename); } prefixsize = strlen(prefix); availablewidth = LINEWIDTH - prefixsize; /* Generate the error message */ vsprintf(errmsg,format,ap); va_end(ap); errmsgsize = strlen(errmsg); /* Remove trailing '\n's from the error message. */ while( errmsgsize>0 && errmsg[errmsgsize-1]=='\n' ){ errmsg[--errmsgsize] = 0; } /* Print the error message */ base = 0; while( errmsg[base]!=0 ){ end = restart = findbreak(&errmsg[base],0,availablewidth); restart += base; while( errmsg[restart]==' ' ) restart++; fprintf(stdout,"%s%.*s\n",prefix,end,&errmsg[base]); base = restart; }}/**************** From the file "main.c" ************************************//*** Main program file for the LEMON parser generator.*//* Report an out-of-memory condition and abort. This function** is used mostly by the "MemoryCheck" macro in struct.h*/void memory_error(void){ fprintf(stderr,"Out of memory. Aborting...\n"); exit(1);}/* Locates the basename in a string possibly containing paths, * including forward-slash and backward-slash delimiters on Windows, * and allocates a new string containing just the basename. * Returns the pointer to that string. */PRIVATE char*make_basename(char* fullname){ char *cp; char *new_string; /* Find the last forward slash */ cp = strrchr(fullname, '/');#ifdef WIN32 /* On Windows, if no forward slash was found, look ofr * backslash also */ if (!cp) cp = strrchr(fullname, '\\');#endif if (!cp) { new_string = malloc( strlen(fullname) ); strcpy(new_string, fullname); } else { /* skip the slash */ cp++; new_string = malloc( strlen(cp) ); strcpy(new_string, cp); } return new_string;}/* The main program. Parse the command line and do it... */int main(int argc, char **argv){ static int version = 0; static int rpflag = 0; static int basisflag = 0; static int compress = 0; static int quiet = 0; static int statistics = 0; static int mhflag = 0; static char *outdirname = NULL; static char *templatename = NULL; static struct s_options options[] = { {OPT_FLAG, "b", (char*)&basisflag, "Print only the basis in report."}, {OPT_FLAG, "c", (char*)&compress, "Don't compress the action table."}, {OPT_STR, "d", (char*)&outdirname, "Output directory name."}, {OPT_FLAG, "g", (char*)&rpflag, "Print grammar without actions."}, {OPT_FLAG, "m", (char*)&mhflag, "Output a makeheaders compatible file"}, {OPT_FLAG, "q", (char*)&quiet, "(Quiet) Don't print the report file."}, {OPT_FLAG, "s", (char*)&statistics, "Print parser stats to standard output."}, {OPT_STR, "t", (char*)&templatename, "Template file to use."}, {OPT_FLAG, "x", (char*)&version, "Print the version number."}, {OPT_FLAG,0,0,0} }; int i; struct lemon lem; optinit(argv,options,stderr); if( version ){ printf("Lemon version 1.0\n" "Copyright 1991-1997 by D. Richard Hipp\n" "Freely distributable under the GNU Public License.\n" ); exit(0); } if( optnargs()!=1 ){ fprintf(stderr,"Exactly one filename argument is required.\n"); exit(1); } lem.errorcnt = 0; /* Initialize the machine */ Strsafe_init(); Symbol_init(); State_init(); lem.argv0 = argv[0]; lem.filename = get_optarg(0); lem.basisflag = basisflag; lem.nconflict = 0; lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0; lem.stacksize = 0; lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest = lem.tokenprefix = lem.outname = lem.extracode = 0; lem.tablesize = 0; Symbol_new("$"); lem.errsym = Symbol_new("error"); lem.outdirname = outdirname; lem.templatename = templatename; lem.basename = make_basename(lem.filename); /* Parse the input file */ Parse(&lem);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -