/// <summary> /// Main method for the process that removes the rules that have left recursion /// </summary> public void RemoveLeftRecursion() { int n = productionRules.Count; bool foundRecursion = false; for (var index = 0; index < n; index++) { try { if (productionRules[index].NonTerminal.Equals(productionRules[index].Rule[0])) { var sindex = index; var nonterminal = productionRules[index].NonTerminal; var newterminal = this.GenerateNonTerminal(nonterminal); var newProdRule = new ProductionRule { NonTerminal = newterminal, Rule = new List <string>() }; productionRules.Add(newProdRule); foundRecursion = true; while (foundRecursion) { if (productionRules[sindex].NonTerminal.Equals(productionRules[sindex].Rule[0])) { var alpha = productionRules[sindex].Rule.GetRange(1, productionRules[sindex].Rule.Count - 1); alpha.Add(newterminal); productionRules[sindex].Rule = alpha; productionRules[sindex].NonTerminal = newterminal; } else { productionRules[sindex].Rule.Add(newterminal); } sindex++; if (!productionRules[sindex].NonTerminal.Equals(nonterminal)) { foundRecursion = false; index = sindex; } } } } catch (System.ArgumentOutOfRangeException) { //exceptie daca intalneste cazul EPS (rule.count = 0) } } productionRules = productionRules.OrderBy(o => o).ToList(); nonTerminals = nonTerminals.Distinct().ToList(); }
/// <summary> /// Generates else if the nonterminal is already visited /// </summary> /// <param name="rule"></param> /// <param name="code"></param> /// <param name="nrBrace"></param> /// <param name="nrIf"></param> private void GenerateElse2(ProductionRule rule, ref string code, ref int nrBrace, ref int nrIf) { code += "}\n"; //closing the brace for last if nrBrace--; while (nrIf > 1) { code += "else { throw new Exception(\"ERROR\"); }\n"; code += "}\n"; nrBrace--; nrIf--; } if (nrIf > 0) { try { if (_gramar.productionRules[_gramar.productionRules.IndexOf(rule) + 1].NonTerminal.Equals(rule.NonTerminal)) { code += "else\n {\n"; nrIf--; nrBrace++; } else { code += "else { throw new Exception(\"ERROR\"); }\n"; code += "}\n"; nrBrace--; nrIf--; code += "}"; nrBrace--; // } } catch (System.ArgumentOutOfRangeException exc) { code += "else { throw new Exception(\"ERROR\"); }\n"; code += "}\n"; nrBrace--; nrIf--; code += "}"; nrBrace--; // } } }
/// <summary> /// The rules with the same begining are being corrected /// </summary> /// <param name="column"></param> /// <param name="start"></param> /// <param name="final"></param> private void ModifyRulesSB_RSM(int column, int start, int final) { List <string> alpha = null; column++; if (column == 0) { alpha = productionRules[start].Rule.GetRange(0, column); //retin partea comuna; } else { alpha = productionRules[start].Rule.GetRange(0, column); } var newterminal = this.GenerateNonTerminal(productionRules[start].NonTerminal); var oldterminal = productionRules[start].NonTerminal; nonTerminals.Add(newterminal); //adaug noul neterminal in gramatica //modific regulie astfel: daca A->alpha beta atunci o sa defina An->beta; for (var ind = start; ind <= final; ind++) { var newprodRule = new ProductionRule { NonTerminal = newterminal, Rule = productionRules[ind].Rule.GetRange(column, productionRules[ind].Rule.Count() - column), }; //daca rule.count() == 0 atunci este EPS productionRules[ind] = newprodRule; } //adaug regula de productie A->alphaA0; var prodRule = new ProductionRule { NonTerminal = oldterminal, Rule = alpha, }; prodRule.Rule.Add(newterminal); productionRules.Add(prodRule); }