예제 #1
0
        private string PrintTerminalInterfaces()
        {
            StringBuilder builder = new StringBuilder();

            foreach (string terminal in grammar.Terminals())
            {
                builder.Append(PrintTerminalInterface(terminal));
            }
            return(builder.ToString());
        }
예제 #2
0
        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);
        }
예제 #3
0
 /// <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);
         }
     }
 }
예제 #4
0
        /// <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);
        }