internal void CreateSpecialProduction(NonTerminal root) { rootProduction = new Production(LookupNonTerminal("$accept")); AddProduction(rootProduction); rootProduction.rhs.Add(root); rootProduction.rhs.Add(LookupTerminal(Token.ident, "EOF")); }
private List <NonTerminal> BuildDependencyGraph() { List <NonTerminal> rslt = new List <NonTerminal>(); foreach (KeyValuePair <string, NonTerminal> kvp in this.nonTerminals) { NonTerminal nonTerm = kvp.Value; NonTerminal dependency = null; if (!nonTerm.terminating) { rslt.Add(nonTerm); nonTerm.dependsOnList = new List <NonTerminal>(); foreach (Production prod in nonTerm.productions) { foreach (Symbol symbol in prod.rhs) { dependency = symbol as NonTerminal; if (dependency != null && dependency != nonTerm && !dependency.terminating && !nonTerm.dependsOnList.Contains(dependency)) { nonTerm.depth = 0; nonTerm.dependsOnList.Add(dependency); } } } } } return(rslt); }
private static void SccPropagate(NonTerminal root, List <NonTerminal> thisTestConfig, List <NonTerminal> fixes) { int count = 0; bool changed = false; do { count = 0; changed = false; foreach (NonTerminal nt in thisTestConfig) { if (!nt.terminating) { foreach (Production prod in nt.productions) { if (ProductionTerminates(prod)) { nt.terminating = true; changed = true; } } if (!nt.terminating) { count++; } } } }while (changed); if (count == 0) { fixes.Add(root); } }
void WriteProductions(StreamWriter writer) { NonTerminal lhs = null; foreach (Production production in productions) { int lhsLength = production.lhs.ToString().Length; if (production.lhs != lhs) { lhs = production.lhs; writer.WriteLine(); writer.Write("{0} {1}: ", ProductionAnchor(production.num), lhs); } else { writer.Write("{0} {1}| ", ProductionAnchor(production.num), new string(' ', lhsLength)); } if (production.rhs.Count == 0) { writer.WriteLine("/* empty */"); } else { writer.WriteLine(ListUtilities.GetStringFromList(production.rhs, " ", lhsLength + 12)); } } writer.WriteLine(); }
private void ComputeLA() { // LA(q, A->w) = Union { Follow(p,A) | p -> w -> q } foreach (AutomatonState q in states) { foreach (ProductionItem item in q.allItems) { if (item.isReduction()) { item.LA = new SetCollection <Terminal>(); foreach (AutomatonState p in states) { if (PathTo(p, item.production, item.pos) == q) { NonTerminal A = item.production.lhs; if (p.nonTerminalTransitions.ContainsKey(A)) { Transition pA = p.nonTerminalTransitions[A]; item.LA.AddRange(pA.Follow); } } } } } } }
private void ComputeIncludes() { // (p,A) include (q,B) iff B -> Beta A Gamma and Gamma => empty and q -> Beta -> p foreach (AutomatonState q in states) { foreach (Transition qB in q.nonTerminalTransitions.Values) { foreach (Production prod in qB.A.productions) { for (int i = prod.rhs.Count - 1; i >= 0; i--) { Symbol A = prod.rhs[i]; NonTerminal NT = A as NonTerminal; if (NT != null) { AutomatonState p = PathTo(q, prod, i); p.nonTerminalTransitions[NT].includes.Add(qB); } if (!A.IsNullable()) { break; } } } } } }
internal NonTerminal LookupNonTerminal(string name) { if (!nonTerminals.ContainsKey(name)) { nonTerminals[name] = new NonTerminal(name); } return(nonTerminals[name]); }
private void LeafExperiment(NonTerminal probe, List <NonTerminal> component) { // Test what happens with probe terminating ... probe.terminating = true; LeafPropagate(probe, component); // Then reset the values of all components foreach (NonTerminal element in component) { element.terminating = false; } }
private static bool ProductionTerminates(Production thisProd) { foreach (Symbol smbl in thisProd.rhs) { NonTerminal nonTerm = smbl as NonTerminal; if (nonTerm != null && !nonTerm.terminating) { return(false); } } return(true); }
/// <summary> /// This is the method that computes the shortest terminal /// string sequence for each NonTerminal symbol. The immediate /// guide is to find those NT that are non-terminating. /// </summary> void MarkTerminating() { bool changed = false; int nonTerminatingCount = 0; // This uses a naive algorithm that iterates until // an iteration completes without changing anything. do { changed = false; nonTerminatingCount = 0; foreach (KeyValuePair <string, NonTerminal> kvp in this.nonTerminals) { NonTerminal nonTerm = kvp.Value; if (!nonTerm.terminating) { foreach (Production prod in nonTerm.productions) { if (ProductionTerminates(prod)) { nonTerm.terminating = true; changed = true; } } if (!nonTerm.terminating) { nonTerminatingCount++; } } } } while (changed); // // Now produce some helpful diagnostics. // We wish to find single NonTerminals that, if made // terminating will fix up many, even all of the // non-terminating NonTerminals that have been found. // if (nonTerminatingCount > 0) { List <NonTerminal> ntDependencies = BuildDependencyGraph(); hasNonTerminatingNonTerms = true; handler.AddError( 5, String.Format(CultureInfo.InvariantCulture, "There are {0} non-terminating NonTerminal Symbols{1} {{{2}}}", nonTerminatingCount, System.Environment.NewLine, ListUtilities.GetStringFromList(ntDependencies)), null); FindNonTerminatingSCC(ntDependencies); // Do some diagnosis } }
private void Walk(NonTerminal node, Stack <NonTerminal> stack, List <NonTerminal> fixes, ref int count) { count++; stack.Push(node); node.depth = count; foreach (NonTerminal next in node.dependsOnList) { if (next.depth == 0) { Walk(next, stack, fixes, ref count); } if (next.depth < count) { node.depth = next.depth; } } if (node.depth == count) // traversal leaving strongly connected component { // This algorithm is folklore. I have been using it since // at least early 1980s in the Gardens Point compilers. // I don't even remember where I learned it ... (kjg). // NonTerminal popped = stack.Pop(); popped.depth = finishMark; if (popped != node) { List <NonTerminal> SCC = new List <NonTerminal>(); SCC.Add(popped); do { popped = stack.Pop(); popped.depth = finishMark; SCC.Add(popped); }while (popped != node); handler.AddWarning(150, String.Format(CultureInfo.InvariantCulture, "The following {2} symbols form a non-terminating cycle {0}{{{1}}}", System.Environment.NewLine, ListUtilities.GetStringFromList(SCC), SCC.Count), null); // // Check if termination of any single NonTerminal // would eliminate the whole cycle of dependency. // SccExperiment(SCC, fixes); } } count--; }
private void LeafPropagate(NonTerminal root, List <NonTerminal> thisTestConfig) { int count = 0; bool changed = false; do { count = 0; changed = false; foreach (NonTerminal nt in thisTestConfig) { if (!nt.terminating) { foreach (Production prod in nt.productions) { if (ProductionTerminates(prod)) { nt.terminating = true; changed = true; } } if (!nt.terminating) { count++; } } } }while (changed); List <NonTerminal> filtered = FilterTerminatingElements(thisTestConfig); handler.AddWarning(151, String.Format(CultureInfo.InvariantCulture, "Terminating {0} fixes the following size-{1} NonTerminal set{2}{{{3}}}", root.ToString(), filtered.Count, System.Environment.NewLine, ListUtilities.GetStringFromList(filtered)), null); }
void WriteProductions(StreamWriter writer) { NonTerminal lhs = null; string padding = ""; foreach (Production production in productions) { int lhsLength = 0; if (production.lhs != lhs) { if (lhs != null) // ==> this is a change to a new LHS, write terminating ';' { writer.WriteLine("{0} {1};", indexSkip, padding); } lhsLength = production.lhs.ToString().Length; padding = new string( ' ', lhsLength ); lhs = production.lhs; writer.WriteLine(); writer.Write("{0} {1}: ", ProductionAnchor(production.num), lhs); } else { writer.Write("{0} {1}| ", ProductionAnchor(production.num), padding); } if (production.rhs.Count == 0) { writer.WriteLine("/* empty */"); } else { writer.WriteLine(ListUtilities.GetStringFromList(production.rhs, " ", lhsLength + 12)); } } writer.Write("{0} {1};", indexSkip, padding); writer.WriteLine(); }
void MarkReachable() { Stack <NonTerminal> work = new Stack <NonTerminal>(); rootProduction.lhs.reached = true; // by definition. work.Push(startSymbol); startSymbol.reached = true; while (work.Count > 0) { NonTerminal nonT = work.Pop(); foreach (Production prod in nonT.productions) { foreach (Symbol smbl in prod.rhs) { NonTerminal rhNt = smbl as NonTerminal; if (rhNt != null && !rhNt.reached) { rhNt.reached = true; work.Push(rhNt); } } } } }
internal Production(NonTerminal lhs) { this.lhs = lhs; lhs.productions.Add(this); }
internal Transition(NonTerminal A, AutomatonState next) { this.A = A; this.next = next; }