?? lemon.c
字號:
int i; struct config *cfp, *other; struct state *stp; struct plink *plp; /* Housekeeping detail: ** Add to every propagate link a pointer back to the state to ** which the link is attached. */ for(i=0; i<lemp->nstate; i++){ stp = lemp->sorted[i]; for(cfp=stp->cfp; cfp; cfp=cfp->next){ cfp->stp = stp; } } /* Convert all backlinks into forward links. Only the forward ** links are used in the follow-set computation. */ for(i=0; i<lemp->nstate; i++){ stp = lemp->sorted[i]; for(cfp=stp->cfp; cfp; cfp=cfp->next){ for(plp=cfp->bplp; plp; plp=plp->next){ other = plp->cfp; Plink_add(&other->fplp,cfp); } } }}/* Compute all followsets.**** A followset is the set of all symbols which can come immediately** after a configuration.*/void FindFollowSets(lemp)struct lemon *lemp;{ int i; struct config *cfp; struct plink *plp; int progress; int change; for(i=0; i<lemp->nstate; i++){ for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){ cfp->status = INCOMPLETE; } } do{ progress = 0; for(i=0; i<lemp->nstate; i++){ for(cfp=lemp->sorted[i]->cfp; cfp; cfp=cfp->next){ if( cfp->status==COMPLETE ) continue; for(plp=cfp->fplp; plp; plp=plp->next){ change = SetUnion(plp->cfp->fws,cfp->fws); if( change ){ plp->cfp->status = INCOMPLETE; progress = 1; } } cfp->status = COMPLETE; } } }while( progress );}static int resolve_conflict();/* Compute the reduce actions, and resolve conflicts.*/void FindActions(lemp)struct lemon *lemp;{ int i,j; struct config *cfp; struct state *stp; struct symbol *sp; struct rule *rp; /* Add all of the reduce actions ** A reduce action is added for each element of the followset of ** a configuration which has its dot at the extreme right. */ for(i=0; i<lemp->nstate; i++){ /* Loop over all states */ stp = lemp->sorted[i]; for(cfp=stp->cfp; cfp; cfp=cfp->next){ /* Loop over all configurations */ if( cfp->rp->nrhs==cfp->dot ){ /* Is dot at extreme right? */ for(j=0; j<lemp->nterminal; j++){ if( SetFind(cfp->fws,j) ){ /* Add a reduce action to the state "stp" which will reduce by the ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */ Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp); } } } } } /* Add the accepting token */ if( lemp->start ){ sp = Symbol_find(lemp->start); if( sp==0 ) sp = lemp->rule->lhs; }else{ sp = lemp->rule->lhs; } /* Add to the first state (which is always the starting state of the ** finite state machine) an action to ACCEPT if the lookahead is the ** start nonterminal. */ Action_add(&lemp->sorted[0]->ap,ACCEPT,sp,0); /* Resolve conflicts */ for(i=0; i<lemp->nstate; i++){ struct action *ap, *nap; struct state *stp; stp = lemp->sorted[i]; assert( stp->ap ); stp->ap = Action_sort(stp->ap); for(ap=stp->ap; ap && ap->next; ap=ap->next){ for(nap=ap->next; nap && nap->sp==ap->sp; nap=nap->next){ /* The two actions "ap" and "nap" have the same lookahead. ** Figure out which one should be used */ lemp->nconflict += resolve_conflict(ap,nap,lemp->errsym); } } } /* Report an error for each rule that can never be reduced. */ for(rp=lemp->rule; rp; rp=rp->next) rp->canReduce = B_FALSE; for(i=0; i<lemp->nstate; i++){ struct action *ap; for(ap=lemp->sorted[i]->ap; ap; ap=ap->next){ if( ap->type==REDUCE ) ap->x.rp->canReduce = B_TRUE; } } for(rp=lemp->rule; rp; rp=rp->next){ if( rp->canReduce ) continue; ErrorMsg(lemp->filename,rp->ruleline,"This rule can not be reduced.\n"); lemp->errorcnt++; }}/* Resolve a conflict between the two given actions. If the** conflict can't be resolve, return non-zero.**** NO LONGER TRUE:** To resolve a conflict, first look to see if either action** is on an error rule. In that case, take the action which** is not associated with the error rule. If neither or both** actions are associated with an error rule, then try to** use precedence to resolve the conflict.**** If either action is a SHIFT, then it must be apx. This** function won't work if apx->type==REDUCE and apy->type==SHIFT.*/static int resolve_conflict(apx,apy,errsym)struct action *apx;struct action *apy;struct symbol *errsym; /* The error symbol (if defined. NULL otherwise) */{ struct symbol *spx, *spy; int errcnt = 0; assert( apx->sp==apy->sp ); /* Otherwise there would be no conflict */ if( apx->type==SHIFT && apy->type==REDUCE ){ spx = apx->sp; 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{ assert( apx->type==SH_RESOLVED || apx->type==RD_RESOLVED || apx->type==CONFLICT || apy->type==SH_RESOLVED || apy->type==RD_RESOLVED || apy->type==CONFLICT ); /* The REDUCE/SHIFT case cannot happen because SHIFTs come before ** REDUCEs on the list. If we reach this point it must be because ** the parser conflict had already been resolved. */ } 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(){ 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(old)struct config *old;{ old->next = freelist; freelist = old;}/* Initialized the configuration list builder */void Configlist_init(){ current = 0; currentend = ¤t; basis = 0; basisend = &basis; Configtable_init(); return;}/* Initialized the configuration list builder */void Configlist_reset(){ current = 0; currentend = ¤t; basis = 0; basisend = &basis; Configtable_clear(0); return;}/* Add another configuration to the configuration list */struct config *Configlist_add(rp,dot)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(rp,dot)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(lemp)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 if( xsp->type==MULTITERMINAL ){ int k; for(k=0; k<xsp->nsubsym; k++){ SetAdd(newcfp->fws, xsp->subsym[k]->index); } break; }else{ SetUnion(newcfp->fws,xsp->firstset); if( xsp->lambda==B_FALSE ) break; } } if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp); } } } return;}/* Sort the configuration list */void Configlist_sort(){ current = (struct config *)msort((char *)current,(char **)&(current->next),Configcmp); currentend = 0; return;}/* Sort the basis configuration list */void Configlist_sortbasis(){ 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(){ 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(){ struct config *old; old = basis; basis = 0; basisend = 0; return old;}/* Free all elements of the given configuration list */void Configlist_eat(cfp)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(msg,min,max)char *msg;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -