/// <summary> /// Genereates warnings for useless variables. /// </summary> /// <param name="g">the grammar</param> /// <returns></returns> public static List <string> getGrammarWarnings(ContextFreeGrammar g) { List <string> res = new List <string>(); HashSet <string> variables = new HashSet <string>(); foreach (var n in g.Variables) { variables.Add(n.ToString()); } var productiv = g.GetUsefulNonterminals(true); var unproductiv = variables.Except(productiv); if (unproductiv.Count() > 0) { res.Add(string.Format("Warning: There are unproductive variables! ({0})", string.Join(", ", unproductiv))); } var reachable = new HashSet <string>(); //Lemma 4.2, p. 89, Hopcroft-Ullman Stack <Nonterminal> stack = new Stack <Nonterminal>(); stack.Push(g.StartSymbol); reachable.Add(g.StartSymbol.ToString()); while (stack.Count > 0) { Nonterminal v = stack.Pop(); foreach (Production p in g.GetProductions(v)) { foreach (Nonterminal u in p.GetVariables()) { if (!reachable.Contains(u.ToString())) { reachable.Add(u.ToString()); stack.Push(u); } } } } var unreachable = variables.Except(reachable); if (unproductiv.Count() > 0) { res.Add(string.Format("Warning: There are unreachable variables! ({0})", string.Join(", ", unreachable))); } return(res); }