/* create a nonterminal given only names */ struct Production *newPackratNonterminal(unsigned char *name, unsigned char ***sub) { struct Production *ret = getProduction(name); struct Buffer_Production_p pors; struct Buffer_Production pthens; struct Production *pr; int ors, thens; ret->parser = packratNonterminal; /* now fill in the sub-productions */ INIT_BUFFER(pors); for (ors = 0; sub[ors]; ors++) { INIT_BUFFER(pthens); for (thens = 0; sub[ors][thens]; thens++) { pr = getProduction(sub[ors][thens]); WRITE_BUFFER(pthens, &pr, 1); } pr = NULL; WRITE_BUFFER(pthens, &pr, 1); WRITE_BUFFER(pors, &pthens.buf, 1); } pr = NULL; WRITE_BUFFER(pors, (struct Production ***) &pr, 1); ret->arg = pors.buf; return ret; }
void Grammar::computeSuccessors(LR1State &state) { //dump(state); pause(); BitSet itemsDone(state.m_items.size()); // this is correct! for(UINT i = 0; i < state.m_items.size(); i++) { if(itemsDone.contains(i)) { continue; } const LR1Item &origItem = state.m_items[i]; if(isAcceptItem(origItem)) { continue; // No successor, but accept } const Production &origProduction = getProduction(origItem); if(origItem.m_dot < origProduction.getLength()) { // origItem is A -> alfa . X beta [la] CompactIntArray successorItems; successorItems.add(i); int symbolNr = origProduction.m_rightSide[origItem.m_dot]; LR1State newState(getStateCount()); const LR1Item newItem(true, origItem.m_prod, origItem.m_dot+1, origItem.m_la); // newItem is A -> alfa X . beta [la] (kernelItem) newState.addItem(newItem); itemsDone += i; for(UINT k = i+1; k < state.m_items.size(); k++) { if(itemsDone.contains(k)) { continue; } const LR1Item &sameSymbolItem = state.m_items[k]; const Production &sameSymbolProd = getProduction(sameSymbolItem); if(sameSymbolItem.m_dot < sameSymbolProd.getLength() && sameSymbolProd.m_rightSide[sameSymbolItem.m_dot] == symbolNr) { // sameSymbolItem is C -> gamma . X zeta [la1] const LR1Item newItem1(true, sameSymbolItem.m_prod, sameSymbolItem.m_dot+1, sameSymbolItem.m_la); // newItem1 is C -> gamma X . zeta [la1] (kernelItem) newState.addItem(newItem1); itemsDone += k; successorItems.add(k); } } newState.sortItems(); int succStateIndex = findState(newState); if(succStateIndex < 0) { computeClosure(newState, true); succStateIndex = addState(newState); } else { if(mergeLookahead(m_states[succStateIndex], newState)) { m_unfinishedSet.add(succStateIndex); // printf(_T(")%d ", succStateIndex); } } assert(succStateIndex >= 0); for(size_t j = 0; j < successorItems.size(); j++) { state.m_items[successorItems[j]].m_succ = succStateIndex; } } } }
/* create a negation nonterminal given only a name */ struct Production *newPackratNotNonterminal(unsigned char *name, unsigned char *sub) { struct Production *ret = getProduction(name); struct Production **subp; ret->parser = packratNotNonterminal; /* now fill in the sub-production */ subp = GC_MALLOC(2 * sizeof(struct Production *)); subp[1] = NULL; subp[0] = getProduction(sub); ret->sub = subp; return ret; }
void actualizeNonTerminals(GrammarADT grammar) { int nontermquant = getQuantTerminals(grammar); char * nontermsfounded = NULL ; int nontermsfoundedsize =0; ProductionsADT productions = getProductions(grammar); int productionquant = getQuant(productions),i; /*detect current non terminals*/ for (i=0; i<productionquant; i++) { ProductionADT p = getProduction(productions,i); char first = getProductionComponent(p,0); char sec = getProductionComponent(p,1); char third = getProductionComponent(p,2); if (isNonTerminal(first) && !containsChar(nontermsfounded,nontermsfoundedsize,first) ) { addChar(&nontermsfounded, &nontermsfoundedsize, first); } if (isNonTerminal(sec) && !containsChar(nontermsfounded,nontermsfoundedsize,sec) ) { addChar(&nontermsfounded, &nontermsfoundedsize, sec); } if(isNonTerminal(third) && !containsChar(nontermsfounded,nontermsfoundedsize,third)) { addChar(&nontermsfounded, &nontermsfoundedsize, third); } } /*actualize non terminals*/ if( nontermsfoundedsize != nontermquant ) { /*there are less current non terminals*/ setNonTerminals(grammar,nontermsfounded,nontermsfoundedsize); } }
/*should be called after actualizeNonterminals*/ void actualizeProductions(GrammarADT grammar) { ProductionsADT productions = getProductions(grammar); int quantproductions = getQuant(productions); int quantnonterminals = getQuantNonTerminals(grammar); char * nonterminals = getNonTerminals(grammar); int i,j; /* por cada no terminal, si no exite ninguna producion que lo tenga * en su parte izquierda, hay que elimicar la producion */ int contained = FALSE; for ( i=0; i<quantnonterminals; i++ ) { contained = FALSE; for (j=0; j<quantproductions; j++ ) { ProductionADT p = getProduction(productions,j); char first = getProductionComponent(p,0); if( nonterminals[i] == first ) { contained = TRUE; break; } } /* if the symbol is no longer in the left of a production -> * all the production containing that symbol should be deleted */ if (!contained) { removeProductionsContaining(productions, nonterminals[i]); } } }
void Grammar::computeClosure(LR1State &state, bool allowNewItems) { bool changed; do { changed = false; for(size_t i = 0; i < state.m_items.size(); i++) { const LR1Item &item = state.m_items[i]; const Production &prod = getProduction(item); if(item.m_dot < prod.getLength() && isNonTerminal(prod.m_rightSide[item.m_dot])) { // item is A -> alfa . B beta [la] const GrammarSymbol &B = getSymbol(prod.m_rightSide[item.m_dot]); const BitSet la(first1(item)); for(size_t p = 0; p < B.m_leftSideOf.size(); p++) { const LR1Item newItem(false, B.m_leftSideOf[p], 0, la); // newItem is B -> . gamma [first1(beta la)] (nonkernelitem) LR1Item *oldItem = state.findItem(newItem); if(oldItem == NULL) { if(!allowNewItems) { throwException(_T("Grammar::computeClosure:No new items allowed")); } state.addItem(newItem); changed = true; } else { if(!(newItem.m_la - oldItem->m_la).isEmpty()) { oldItem->m_la += newItem.m_la; changed = true; } } } } } } while(changed); state.sortItems(); }
/*Utility*/ void printProductions(ProductionsADT productions){ printf("Productions: { \n"); int i; for(i=0; i<getQuant(productions);i++){ printProduction(getProduction(productions,i)); } printf("}\n"); }
void ProductionState::set_valid(const char *result) { Production *p = getProduction(result); // Update valid as allowed by current constraints if( _constraint == noConstraint ) { p->_valid = knownValid; } else { if( p->_valid != knownValid ) { p->_valid = unknownValid; } } }
/* remove all productions with the given name */ void delProduction(const unsigned char *name) { /* find the relevant production */ struct Production *curp = getProduction(name), *curp_left = curp->left, *curp_right = curp->right; /* and blank it */ memset(curp, 0, sizeof(struct Production)); curp->name = (unsigned char *) GC_STRDUP((char *) name); curp->left = curp_left; curp->right = curp_right; }
int isRight(GrammarADT grammar) { ProductionsADT productions = getProductions(grammar); int n = getQuant(productions); int i; for (i=0; i<n; i++) { ProductionADT p = getProduction(productions,i); char sec = getProductionComponent(p,1); char third = getProductionComponent(p,2); /*if there is a production like A->Ba, it is a left sided grammar*/ if (isNonTerminal(sec) && isTerminal(third)) { return 0; } } return 1; }
ConflictSolution Grammar::resolveShiftReduceConflict(const GrammarSymbol &terminal, const LR1Item &item) const { short productionPrecedence = getProduction(item).m_precedence; short terminalPrecedence = terminal.m_precedence; if((productionPrecedence == 0) || (terminalPrecedence == 0)) { return CONFLICT_NOT_RESOLVED; } if( (terminalPrecedence < productionPrecedence) || (productionPrecedence == terminalPrecedence && terminal.m_type != RIGHTASSOC_TERMINAL) ) { return CHOOSE_REDUCE; } else { return CHOOSE_SHIFT; } }
void toFile(GrammarADT grammar) { FILE * fp = fopen("grammar.gr", "w"); if(fp == NULL) { printf("Error: File could not be created\n"); fclose(fp); return; } fprintf(fp, "G1 = ({"); int i; for(i = 0; i < getQuantNonTerminals(grammar); i++) { fprintf(fp, "%c%s", getNonTerminals(grammar)[i], (i == getQuantNonTerminals(grammar)-1?"}":", ")); } fprintf(fp, ", {"); for(i = 0; i < getQuantTerminals(grammar); i++) { fprintf(fp, "%c%s", getTerminals(grammar)[i], (i == getQuantTerminals(grammar)-1?"}":", ")); } fprintf(fp, ", %c, {", getDistinguished(grammar)); for(i = 0; i < getQuant(getProductions(grammar)); i++) { fprintf(fp, "%c -> %c%c%s", getProductionComponent(getProduction(getProductions(grammar), i), 0), getProductionComponent(getProduction(getProductions(grammar), i), 1), getProductionComponent(getProduction(getProductions(grammar), i), 2), (i == getQuant(getProductions(grammar))-1? "}": ", ")); } fprintf(fp, ")"); fclose(fp); return; }
/* fills the list with Templates that can be manufactured in the Factory - based on size. There is a limit on how many can be manufactured at any one time. */ void fillTemplateList(std::vector<DROID_TEMPLATE *> &pList, STRUCTURE *psFactory) { const int player = psFactory->player; pList.clear(); BODY_SIZE iCapacity = (BODY_SIZE)psFactory->capacity; /* Add the templates to the list*/ for (DROID_TEMPLATE &i : localTemplates) { DROID_TEMPLATE *psCurr = &i; // Must add droids if currently in production. if (!getProduction(psFactory, psCurr).quantity) { //can only have (MAX_CMDDROIDS) in the world at any one time if (psCurr->droidType == DROID_COMMAND) { if (checkProductionForCommand(player) + checkCommandExist(player) >= (MAX_CMDDROIDS)) { continue; } } if (!psCurr->enabled || !validTemplateForFactory(psCurr, psFactory, false) || !researchedTemplate(psCurr, player, includeRedundantDesigns)) { continue; } } //check the factory can cope with this sized body if (((asBodyStats + psCurr->asParts[COMP_BODY])->size <= iCapacity)) { pList.push_back(psCurr); } else if (bMultiPlayer && (iCapacity == SIZE_HEAVY)) { // Special case for Super heavy bodyies (Super Transporter) if ((asBodyStats + psCurr->asParts[COMP_BODY])->size == SIZE_SUPER_HEAVY) { pList.push_back(psCurr); } } } }
// assume item = A -> alfa . B beta [la] // computes first1(beta la) BitSet Grammar::first1(const LR1Item &item) const { const Production &prod = getProduction(item); const int length = prod.getLength(); BitSet result(getTerminalCount()); for(int k = item.m_dot+1; k < length; k++) { const int symbol = prod.m_rightSide[k]; if(isTerminal(symbol)) { result += symbol; return result; } else { // nonterminal const GrammarSymbol &nt = getSymbol(symbol); result += nt.m_first1; if(!nt.m_deriveEpsilon) { return result; } } } return result += item.m_la; }
/* create a regex nonterminal */ struct Production *newPackratRegexTerminal(unsigned char *name, unsigned char *regex) { struct Production *ret = getProduction(name); const char *err; int erroffset; ret->parser = packratRegexTerminal; /* now fill in the arg */ ret->arg = pcre_compile((char *) regex, PCRE_DOTALL, &err, &erroffset, NULL); /* and cry if it's bad */ if (ret->arg == NULL) { fprintf(stderr, "Error compiling regex %s at (%d): %s\n", regex, erroffset, err); exit(1); } return ret; }
/* fills the list with Templates that can be manufactured in the Factory - based on size. There is a limit on how many can be manufactured at any one time. Pass back the number available. */ void fillTemplateList(std::vector<DROID_TEMPLATE *> &pList, STRUCTURE *psFactory) { const int player = psFactory->player; pList.clear(); DROID_TEMPLATE *psCurr; UDWORD iCapacity = psFactory->capacity; /* Add the templates to the list*/ for (std::list<DROID_TEMPLATE>::iterator i = localTemplates.begin(); i != localTemplates.end(); ++i) { psCurr = &*i; // Must add droids if currently in production. if (!getProduction(psFactory, psCurr).quantity) { //can only have (MAX_CMDDROIDS) in the world at any one time if (psCurr->droidType == DROID_COMMAND) { if (checkProductionForCommand(player) + checkCommandExist(player) >= (MAX_CMDDROIDS)) { continue; } } if (!psCurr->enabled || !validTemplateForFactory(psCurr, psFactory, false) || !researchedTemplate(psCurr, player, includeRedundantDesigns)) { continue; } } //check the factory can cope with this sized body if (!((asBodyStats + psCurr->asParts[COMP_BODY])->size > iCapacity) ) { pList.push_back(psCurr); } } }
void ProductionState::set_cost_bounds(const char *result, const Expr *cost, bool has_state_check, bool has_cost_check) { Production *p = getProduction(result); if( p->_valid == knownInvalid ) { // Our cost bounds are not unknown, just not defined. p->_cost_lb = cost->clone(); p->_cost_ub = cost->clone(); } else if (has_state_check || _constraint != noConstraint) { // The production is protected by a condition, so // the cost bounds may expand. // _cost_lb = min(cost, _cost_lb) if( cost->less_than_or_equal(p->_cost_lb) ) { p->_cost_lb = cost->clone(); } // _cost_ub = max(cost, _cost_ub) if( p->_cost_ub->less_than_or_equal(cost) ) { p->_cost_ub = cost->clone(); } } else if (has_cost_check) { // The production has no condition check, but does // have a cost check that could reduce the upper // and/or lower bound. // _cost_lb = min(cost, _cost_lb) if( cost->less_than_or_equal(p->_cost_lb) ) { p->_cost_lb = cost->clone(); } // _cost_ub = min(cost, _cost_ub) if( cost->less_than_or_equal(p->_cost_ub) ) { p->_cost_ub = cost->clone(); } } else { // The costs are unconditionally set. p->_cost_lb = cost->clone(); p->_cost_ub = cost->clone(); } }
void removeUnproductiveProductions(GrammarADT grammar) { ProductionsADT productions = getProductions(grammar); int i, quantproductions = getQuant(productions), productivequant=0,lastproductivequant=-1; char * productives = NULL; char * aux1 = NULL; while(productivequant != lastproductivequant) { lastproductivequant = productivequant; for( i=0; i< quantproductions; i++ ) { ProductionADT p1 = getProduction(productions,i); char first1 = getProductionComponent(p1,0); char sec1 = getProductionComponent(p1,1); char third1 = getProductionComponent(p1,2); if ( !containsChar(productives,productivequant,first1) ) { if ( ( sec1 == LAMDA && third1 == LAMDA ) || /*lamda*/ (isTerminal(sec1) && isTerminal(third1) ) || /*both terminal*/ ( isTerminal(sec1) && third1 == LAMDA ) || /*one terminal*/ ( isTerminal(third1) && sec1 == LAMDA ) || /*one terminal and one productive*/ (isTerminal(sec1) && ( isNonTerminal(third1) && containsChar(productives,productivequant,third1) ) ) || (isTerminal(third1) && ( isNonTerminal(sec1) && containsChar(productives,productivequant,sec1) ) ) || ( sec1 == LAMDA && ( isNonTerminal(third1) && containsChar(productives,productivequant,third1) ) ) || ( third1 == LAMDA && ( isNonTerminal(sec1) && containsChar(productives,productivequant,sec1) ) )) { if ( ( aux1 = realloc(productives, sizeof(char)*(productivequant+1)) ) == NULL ) { fprintf(stderr, "Error doing realloc \n"); } productives = aux1; productives[productivequant++] = first1; } } } } /*remove non terminals and terminals that are no longer there */ actualizeTerminals(grammar); actualizeNonTerminals(grammar); actualizeProductions(grammar); }
String Grammar::itemToString(const LR1Item &item, int flags) const { String result; const Production &prod = getProduction(item); result = format(_T(" (%3d)%c %-15s -> "), item.m_prod, item.m_kernelItem?'K':' ', getSymbol(prod.m_leftSide).m_name.cstr()); for(int i = 0; i < item.m_dot; i++) { result += getSymbol(prod.m_rightSide[i]).m_name; result += _T(" "); } result += _T("."); const int n = prod.getLength(); const TCHAR *delimiter = EMPTYSTRING; for(int i = item.m_dot; i < n; i++, delimiter = _T(" ")) { result += delimiter; result += getSymbol(prod.m_rightSide[i]).m_name; } if(flags & DUMP_LOOKAHEAD) { result += symbolSetToString(item.m_la); } if((flags & DUMP_SUCC) && (item.m_succ >= 0)) { result += format(_T(" -> %d"), item.getSuccessor()); // ie not reduce-item } return result; }
Expr *ProductionState::cost_ub(const char *result) { return getProduction(result)->cost_ub(); }
bool Grammar::isShiftItem(const LR1Item &item) const { // is item = "A -> alfa . a beta [la]" const Production &prod = getProduction(item); return item.m_dot < prod.getLength() && isTerminal(prod.m_rightSide[item.m_dot]); }
const char *ProductionState::valid(const char *result) { return getProduction(result)->valid(); }
bool Grammar::isReduceItem(const LR1Item &item) const { // is item = "A -> alfa . [la]" return item.m_dot == getProduction(item).getLength(); }
int Grammar::getShiftSymbol(const LR1Item &item) const { // Assume item = "A -> alfa . x beta [la]". Return x return getProduction(item).m_rightSide[item.m_dot]; }
void removeUnitaryProductions(GrammarADT grammar) { ProductionsADT productions = getProductions(grammar); int i,j,k, productionquant = getQuant(productions), unitaryquant = 0, lastunitaryquant = 0; /*auxiliar array for unitary productions*/ char * unitaries = NULL; /*iterate over productions and determine first unitaries: * the productions that have only one non terminal symbol * on the right side */ for (i=0; i< productionquant; i++) { char first = getProductionComponent(getProduction(productions,i),0); char sec = getProductionComponent(getProduction(productions,i),1); char third = getProductionComponent(getProduction(productions,i),2); if ( isNonTerminal(sec) && third == LAMDA ) { addPair(&unitaries,&unitaryquant,first, sec); } else if( isNonTerminal(third) && sec == LAMDA) { addPair(&unitaries,&unitaryquant,first, third); } } /*iterate over unitaries, adding the closure*/ while(unitaryquant != lastunitaryquant) { lastunitaryquant = unitaryquant; for (i=0; i<unitaryquant ; i+=2) { char first1 = unitaries[i]; char sec1 = unitaries[i+1]; for (j=0; j<unitaryquant ; j+=2) { char first2 = unitaries[j]; char sec2 = unitaries[j+1]; /*(A,B)(B,C)-> (A,C)*/ if (sec1 == first2 ) { if (!containsPair(unitaries,unitaryquant,first1,sec2) && first1 != sec2 ) { /*no sense in adding (A,A) unitaries*/ addPair(&unitaries,&unitaryquant,first1,sec2); } } } } } /*Debug*/ //printByPairs(unitaries,unitaryquant); //printf("unitaries quant: %d\n\n", unitaryquant/2); /*create the new productions and remove the unitaries*/ for(i=0; i<productionquant; i++) { ProductionADT p1 = getProduction(productions,i); if ( isUnitary(p1) ) { char first1 = getProductionComponent(p1,0); char sec1 = getProductionComponent(p1,1); char third1 = getProductionComponent(p1,2); for(j=0; j<unitaryquant; j+=2) { char uni1 = unitaries[j]; char uni2 = unitaries[j+1]; //A->B and (A,B) (unitary production is localized) if ((first1 == uni1) && (sec1 == uni2 || third1 == uni2 )) { for(k=0; k<productionquant; k++ ) { ProductionADT p2 = getProduction(productions,k); char first2 = getProductionComponent(p2,0); char sec2 = getProductionComponent(p2,1); char third2 = getProductionComponent(p2,2); if(!isUnitary(p2)) { if(first2 == uni2 ) { addProduction(productions,newProduction(first1,sec2,third2)); } } } } } removeParticularProduction(productions,p1); free(p1); } } /*remove non terminals and terminals that are no longer there */ actualizeTerminals(grammar); actualizeNonTerminals(grammar); actualizeProductions(grammar); }
void Grammar::checkStateIsConsistent(const LR1State &state, StateResult &result) { BitSet symbolsDone(getSymbolCount()); const int itemCount = (int)state.m_items.size(); for(int i = 0; i < itemCount; i++) { const LR1Item &item = state.m_items[i]; if(isShiftItem(item)) { const int t = getShiftSymbol(item); if(symbolsDone.contains(t)) { continue; } for(int j = 0; j < itemCount; j++) { if(j == i) { continue; } const LR1Item &item1 = state.m_items[j]; if(isReduceItem(item1) && item1.m_la.contains(t)) { const GrammarSymbol &terminal = getSymbol(t); switch(resolveShiftReduceConflict(terminal, item1)) { case CONFLICT_NOT_RESOLVED: m_SRconflicts++; result.m_errors.add(format(_T("Shift/reduce conflict. Shift or reduce by prod %-3d (prec=%d) on '%s' (prec=%d, %s).") ,item1.m_prod ,getProduction(item1).m_precedence ,terminal.m_name.cstr() ,terminal.m_precedence ,terminal.getTypeString())); break; case CHOOSE_SHIFT: result.m_actions.add(ParserAction(t, item.getSuccessor())); symbolsDone += t; result.m_warnings.add(format(_T("Shift/reduce conflict on %s (prec=%d, %s). Choose shift instead of reduce by prod %d (prec=%d).") ,terminal.m_name.cstr() ,terminal.m_precedence ,terminal.getTypeString() ,item1.m_prod ,getProduction(item1).m_precedence)); m_warningCount++; break; case CHOOSE_REDUCE: result.m_actions.add(ParserAction(t, -item1.m_prod)); symbolsDone += t; result.m_warnings.add(format(_T("Shift/reduce conflict on %s (prec=%d, %s). Choose reduce by prod %d (prec=%d).") ,terminal.m_name.cstr() ,terminal.m_precedence ,terminal.getTypeString() ,item1.m_prod ,getProduction(item1).m_precedence)); m_warningCount++; break; } } } if(!symbolsDone.contains(t)) { if(item.m_succ >= 0) { result.m_actions.add(ParserAction(t, item.getSuccessor())); } symbolsDone += t; continue; } } } for(int i = 0; i < itemCount; i++) { const LR1Item &itemi = state.m_items[i]; if(isReduceItem(itemi)) { BitSet tokensReducedByOtherItems(getTerminalCount()); if(isAcceptItem(itemi)) { // check if this is start -> S . [EOI] result.m_actions.add(ParserAction(0, 0)); if(symbolsDone.contains(0)) { throwException(_T("Token EOI already done in state %d while generating Acceptitem"), state.m_index); } symbolsDone += 0; continue; } for(int j = 0; j < itemCount; j++) { if(j == i) { continue; } const LR1Item &itemj = state.m_items[j]; if(isReduceItem(itemj)) { const BitSet intersection(itemi.m_la & itemj.m_la); if(!intersection.isEmpty()) { if(itemj.m_prod < itemi.m_prod) { tokensReducedByOtherItems += intersection; result.m_warnings.add(format(_T("Reduce/reduce conflict on %s between prod %d and prod %d. Choose prod %d.") ,symbolSetToString(intersection).cstr() ,itemj.m_prod ,itemi.m_prod ,itemj.m_prod)); m_warningCount++; } } } } BitSet itemTokens(itemi.m_la - tokensReducedByOtherItems); for(Iterator<size_t> it = itemTokens.getIterator(); it.hasNext(); ) { const unsigned short t = (unsigned short)it.next(); if(!symbolsDone.contains(t)) { result.m_actions.add(ParserAction(t, -itemi.m_prod)); symbolsDone += t; } } } } for(int i = 0; i < itemCount; i++) { const LR1Item &itemi = state.m_items[i]; if(!isShiftItem(itemi) && !isReduceItem(itemi)) { const int nt = getShiftSymbol(itemi); if(!symbolsDone.contains(nt)) { if(itemi.getSuccessor() >= 0) { result.m_succs.add(ParserAction(nt, itemi.getSuccessor())); } symbolsDone += nt; } } } // for result.m_actions.sort(parserActionCompareToken); // sort actions by symbolnumber (lookahead symbol) result.m_succs.sort( parserActionCompareToken); // sort result by symbolnumber (nonTerminal) }
void removeUnreachableProductions(GrammarADT grammar) { ProductionsADT productions = getProductions(grammar); int i, quantproductions = getQuant(productions), reachablesquant=0,lastreachablesquant=0; char * reachables = malloc(sizeof(char)); char * aux1 = NULL; /*starts only with distinguished symbol, if it is in the current productions*/ if(inCurrentProductions(productions,getDistinguished(grammar))) { reachables[reachablesquant++] = getDistinguished(grammar); } /*until something the quantity of reachables varies*/ while (reachablesquant != lastreachablesquant) { lastreachablesquant = reachablesquant; for(i=0; i<quantproductions; i++) { char first = getProductionComponent(getProduction(productions,i),0); char sec = getProductionComponent(getProduction(productions,i),1); char third = getProductionComponent(getProduction(productions,i),2); /*if the symbol of the left is contained in the reachables, the non terminal * symbols of the right must be added*/ if (containsChar(reachables,reachablesquant,first)) { /*if the second symbol is nonterminal and is not yet in the * reachable list, it must be added*/ if ( isNonTerminal( sec ) && !containsChar(reachables,reachablesquant,sec)) { if ( ( aux1 = realloc(reachables, sizeof(char)*(reachablesquant+1)) ) == NULL ) { fprintf(stderr, "Error doing realloc \n"); } reachables = aux1; reachables[reachablesquant++] = sec; }/*if the third symbol is nonterminal and is not yet in the * reachable list, it must be added*/ else if( isNonTerminal(third) && !containsChar(reachables,reachablesquant,third) ) { if ( (aux1 = realloc(reachables, sizeof(char)*(reachablesquant+1)) ) == NULL ) { fprintf(stderr, "Error doing realloc \n"); } reachables = aux1; reachables[reachablesquant++] = third; } } } } /*TODO: delete debug printf*/ printf("\nReachables!!: "); printArray(reachables,reachablesquant); int symsToRemovequant=0; /*remove the unreachable productions*/ /*If the quantity of reachables is equal to the quantity of nonterminals, * nothing should be removed*/ if (reachablesquant != getQuantNonTerminals(grammar)) { char * symsToRemove = NULL; symsToRemovequant = getDifferents(getNonTerminals(grammar), getQuantNonTerminals(grammar) ,reachables, reachablesquant, &symsToRemove); printf("\nTO REMOVE:"); printArray(symsToRemove,symsToRemovequant ); for(i=0; i<symsToRemovequant; i++) { removeProduction(productions,symsToRemove[i]); } } /*remove non terminals and terminals that are no longer there */ actualizeTerminals(grammar); actualizeNonTerminals(grammar); actualizeProductions(grammar); }
void removeOnlyRightTerminals(GrammarADT grammar) { int j; int found = FALSE; char newsymbol; ProductionsADT productions = getProductions(grammar); /*search for A->a like productions*/ for(j=0; j< getQuant(getProductions(grammar)); j++) { ProductionADT p = getProduction(productions,j); char sec = getProductionComponent(p,1); char third = getProductionComponent(p,2); if( ( isTerminal(sec) && third == LAMDA ) || ( isTerminal(third) && sec == LAMDA ) ) { found = TRUE; break; } } /*if there are not productions with only terminals in the right side * ,go away*/ if(!found) { return; } /*search for the new symbol to insert*/ newsymbol = getNewSymbol(grammar); /*add new symbol to the nonterminals array*/ char * term = getNonTerminals(grammar); int termquant = getQuantNonTerminals(grammar); char * aux = realloc(term, (termquant+1)*sizeof(char)); if(aux == NULL) { printf("Error: Not enought memory\n"); exit(1); } term = aux; term[termquant] = newsymbol; termquant++; setNonTerminals(grammar, term, termquant); int isright = isRight(grammar) ; int productionquant = getQuant(getProductions(grammar)); /*create the new productions with the new symbol*/ for(j=0; j< productionquant ; j++) { ProductionADT p = getProduction(getProductions(grammar),j); char sec = getProductionComponent(p,1); char third = getProductionComponent(p,2); /*is the production have only one terminal symbol on the right side */ if ( isTerminal(sec) && third == LAMDA ) { /*if the grammar is right sided the new symbol should be * added to the right*/ if( isright ) { setProductionComponent(p, 1, sec ); setProductionComponent(p, 2, newsymbol); } else { setProductionComponent(p, 2, sec ); setProductionComponent(p, 1, newsymbol); } } else if( isTerminal(third) && sec == LAMDA) { if( isright ) { setProductionComponent(p, 1, third ); setProductionComponent(p, 2, newsymbol); } else { setProductionComponent(p, 1, newsymbol); setProductionComponent(p, 2, third ); } } } addProduction(getProductions(grammar), newProduction(newsymbol,LAMDA,LAMDA)); /*remove non terminals and terminals that are no longer there */ actualizeTerminals(grammar); actualizeNonTerminals(grammar); return; }
void convertToRight(GrammarADT grammar) { int i; int ml = FALSE; char oldistiguished = getDistinguished(grammar); /*if the grammar is already right there is no * reason to convert it*/ if ( isRight(grammar) ) { return; } ProductionsADT productions = getProductions(grammar); int quantproductions = getQuant(productions); for(i = 0; i < quantproductions ; i++) { ProductionADT p1 = getProduction(productions, i); char first = getProductionComponent(p1, 0); char sec = getProductionComponent(p1, 1); char third = getProductionComponent(p1, 2); if(isNonTerminal(sec)) { addProduction(productions, newProduction(sec , third, first)); removeParticularProduction(productions,p1); } } setProductions(grammar, productions); /*a new nonTerminal should be created , * that joint the non terminals that were joined to lambda*/ char * leftnontermssymbols = NULL; int size=0; for(i=0; i < quantproductions; i++) { ProductionADT p1 = getProduction(productions, i); char first = getProductionComponent(p1, 0); char sec = getProductionComponent(p1, 1); char third = getProductionComponent(p1, 2); if(sec == LAMDA && third == LAMDA) { addChar(&leftnontermssymbols,&size,first); } } /*get a new distiguished symbol*/ char newsymbol = getNewSymbol(grammar); setDistinguished(grammar,newsymbol); /*generate new unitary productions*/ for(i=0; i<size; i++) { ProductionADT newprod = newProduction(newsymbol,leftnontermssymbols[i],LAMDA); //printProduction(newprod); addProduction(productions, newprod); } /*remove all old lambda productions*/ for(i=0; i<getQuant(productions); i++) { ProductionADT p = getProduction(productions,i); char sec = getProductionComponent(p,1); char third = getProductionComponent(p,2); /*if it is a lamda productions : delete*/ if( sec == LAMDA && third == LAMDA ) { removeParticularProduction(productions,p); } } if(!ml) { addProduction(productions, newProduction(oldistiguished, LAMDA, LAMDA)); } setProductions(grammar,productions); /*remove non terminals and terminals that are no longer there */ actualizeTerminals(grammar); actualizeNonTerminals(grammar); actualizeProductions(grammar); }