Exemple #1
0
 internal void CreateSpecialProduction(NonTerminal root)
 {
     rootProduction = new Production(LookupNonTerminal("$accept"));
     AddProduction(rootProduction);
     rootProduction.rhs.Add(root);
     rootProduction.rhs.Add(LookupTerminal(Token.ident, "EOF"));
 }
Exemple #2
0
        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);
        }
Exemple #3
0
        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);
            }
        }
Exemple #4
0
        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();
        }
Exemple #5
0
        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);
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #6
0
        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;
                            }
                        }
                    }
                }
            }
        }
Exemple #7
0
 internal NonTerminal LookupNonTerminal(string name)
 {
     if (!nonTerminals.ContainsKey(name))
     {
         nonTerminals[name] = new NonTerminal(name);
     }
     return(nonTerminals[name]);
 }
Exemple #8
0
 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;
     }
 }
Exemple #9
0
 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);
 }
Exemple #10
0
        /// <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
            }
        }
Exemple #11
0
 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--;
 }
Exemple #12
0
        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);
        }
Exemple #13
0
        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();
        }
Exemple #14
0
        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);
                        }
                    }
                }
            }
        }
Exemple #15
0
 internal Production(NonTerminal lhs)
 {
     this.lhs = lhs;
     lhs.productions.Add(this);
 }
		internal Transition(NonTerminal A, AutomatonState next)
		{
			this.A = A;
			this.next = next;
		}
Exemple #17
0
 internal Transition(NonTerminal A, AutomatonState next)
 {
     this.A    = A;
     this.next = next;
 }
 internal Production(NonTerminal lhs)
 {
     this.lhs = lhs;
     lhs.productions.Add(this);
 }