private string PrintTerminalInterfaces() { StringBuilder builder = new StringBuilder(); foreach (string terminal in grammar.Terminals()) { builder.Append(PrintTerminalInterface(terminal)); } return(builder.ToString()); }
private static CFG verifyConsistency(CFG oldGrammar, CFG newGrammar) { OrderedHashSet <string> oldVariables = oldGrammar.Variables(); foreach (string terminal in newGrammar.Terminals()) { if (oldVariables.Contains(terminal)) { throw new Exception($"grammar is malformed: variable {terminal} cannot be derived"); } } foreach (string variable in newGrammar.Variables()) { bool variableIsDerived = false; foreach (Production production in newGrammar.productions) { if (production.lhs == variable) { variableIsDerived = true; break; } } if (!variableIsDerived) { throw new Exception($"grammar is malformed: variable {variable} cannot be derived"); } } return(newGrammar); }
/// <summary> /// Transforms grammar into Greibach normal form, i.e., /// where productions are of the form `v ::= t s1 s2...`, `v` a variable, /// `t` a terminal. /// The grammar's start variable may be nullable, `v0 ::= epsilon`. /// </summary> /// <param name="grammar">target grammar</param> /// <returns>grammar in Greibach normal form</returns> public static CFG ToGreibachNormalForm(this CFG grammar) { if (grammar.InGreibachNormalForm()) { return(grammar); } while (true) { grammar = grammar.RemoveEpsilonProductions().RemoveLeftRecursion(); OrderedHashSet <Production> productions = new OrderedHashSet <Production>(); foreach (Production production in grammar.productions) { if (production.IsEpsilonProduction() || grammar.Terminals().Contains(production.rhs[0])) { productions.Add(production); } else { string rhsStartVariable = production.rhs[0]; foreach (Production otherProduction in grammar.productions) { if (otherProduction.lhs == rhsStartVariable) { List <string> newRHS = new List <string>(); newRHS.AddRange(otherProduction.rhs); newRHS.AddRange(production.rhs.Skip(1)); productions.Add(new Production(production.lhs, newRHS.ToArray())); } } } } grammar = verifyConsistency(grammar, new CFG(grammar.startVariable, productions)); if (grammar.InGreibachNormalForm()) { return(grammar); } } }
/// <summary> /// Checks whether grammar is in Greibach normal form, i.e., /// where productions are of the form `v ::= t s1 s2...`, `v` a variable, /// `t` a terminal. /// The grammar's start variable may be nullable, `v0 ::= epsilon`. /// </summary> /// <param name="grammar">context-free grammar</param> /// <returns>whether grammar is in Greibach normal form</returns> public static bool InGreibachNormalForm(this CFG grammar) { bool hasNilStartVariable = false; foreach (Production production in grammar.productions) { if (production.IsEpsilonProduction()) { if (production.lhs == grammar.startVariable) { hasNilStartVariable = true; } else { return(false); } } else if (!grammar.Terminals().Contains(production.rhs[0])) { return(false); } } if (hasNilStartVariable) { foreach (Production production in grammar.productions) { foreach (string symbol in production.rhs) { if (grammar.startVariable == symbol) { return(false); } } } } return(true); }