/// <summary> /// Generates a CNF for a given grammar or returns null if the Grammar doesn't produce any words. /// </summary> /// <param name="g">the original grammar</param> /// <returns>the CNF or null</returns> public static ContextFreeGrammar getEquivalentCNF(ContextFreeGrammar g) { if (g == null) { return(null); } if (g.IsInCNF()) { return(g); } try { ContextFreeGrammar res = ContextFreeGrammar.MkCNF(g); //handle empty string res.setAcceptanceForEmptyString(g.acceptsEmptyString()); return(res); } catch (AutomataException e) { if (g.acceptsEmptyString()) { var res = new ContextFreeGrammar(new Nonterminal("S"), new Production[] { new Production(new Nonterminal("S"), new GrammarSymbol[] { new Nonterminal("S"), new Nonterminal("S") }) }); res.setAcceptanceForEmptyString(true); return(res); } return(null); } }
/// <summary> /// Generates a CFG that accepts the prefix closure of a given grammar. /// </summary> /// <param name="g">the original grammar</param> /// <returns>the prefix closure</returns> public static ContextFreeGrammar getPrefixClosure(ContextFreeGrammar g) { Func <Nonterminal, Nonterminal> prefixFor = delegate(Nonterminal x) { return(new Nonterminal(x.Name + "PREFIX")); }; if (g == null) { return(g); } if (!g.IsInCNF()) { g = getEquivalentCNF(g); } if (g == null) { return(g); } Nonterminal prefixStart = prefixFor(g.StartSymbol); var prefixProductions = new List <Production>(); foreach (Production p in g.GetProductions()) { //add original prefixProductions.Add(p); Nonterminal prefixNT = prefixFor(p.Lhs); if (p.Rhs.Length == 2) // case: X->AB ==> X' ->A' | AB' { prefixProductions.Add(new Production(prefixNT, new GrammarSymbol[] { p.Rhs[0], prefixFor((Nonterminal)p.Rhs[1]) })); prefixProductions.Add(new Production(prefixNT, new GrammarSymbol[] { prefixFor((Nonterminal)p.Rhs[0]) })); } else // case: X->a ==> X'->a { prefixProductions.Add(new Production(prefixNT, new GrammarSymbol[] { p.Rhs[0] })); } } var res = new ContextFreeGrammar(prefixStart, prefixProductions); res.setAcceptanceForEmptyString(true); return(res); }