//
        // Context-Free languages, CFG and LR Parsing
        //

        /// <summary>
        /// G3 in "A Survey of LR-Parsing Methods", Gallier.
        /// </summary>
        public static void GallierLookaheadLR_Example3()
        {
            var grammar = DragonBookExample4_48.GetGrammar();

            // characteristic automaton (LR(0) automaton)
            var dfaLr0 = grammar.GetLr0AutomatonDfa();

            SaveFile("GallierEx3_LR0Automaton.dot", DotLanguagePrinter.ToDotLanguage(dfaLr0, DotRankDirection.LeftRight, skipStateLabeling: true));

            var analyzer = Analyzers.CreateErasableSymbolsAnalyzer(grammar);

            //(ImmutableArray<IReadOnlySet<Terminal>> initfirstSets, IGraph graphFirst) = DigraphAlgorithm.GetFirstGraph(grammar, analyzer);
            (var initfirstSets, IGraph graphFirst) = DigraphAlgorithm.GetFirstGraph(grammar, analyzer);

            SaveFile("GallierEx3_FirstGraph.dot",
                     DigraphDotLanguagePrinter.PrintGraph("INITFIRST", initfirstSets, graphFirst, v => grammar.Nonterminals[v].Name));

            var firstSymbolsAnalyzer = Analyzers.CreateFirstSymbolsAnalyzer(grammar);

            (var initFollowSets, IGraph graphFollow) = DigraphAlgorithm.GetFollowGraph(grammar, firstSymbolsAnalyzer);

            SaveFile("GallierEx3_FollowGraph.dot",
                     DigraphDotLanguagePrinter.PrintGraph("INITFOLLOW", initFollowSets, graphFollow, v => grammar.Nonterminals[v].Name));

            var stringWriter = new StringWriter();

            grammar.PrintFirstAndFollowSets(stringWriter);
            SaveFile("GallierEx3_FirstAndFollowSets.txt", stringWriter.ToString());

            // Grammar is LR(0)
            var lr0Parser = grammar.ComputeLr0ParsingTable();
            var writer    = new StringWriter();

            lr0Parser.PrintParsingTable(writer);

            foreach (var conflict in lr0Parser.Conflicts)
            {
                writer.WriteLine(conflict);
                writer.WriteLine($"In state {conflict.State}: {lr0Parser.GetItems(conflict.State).KernelItems.ToVectorString()} (kernel items)");
            }
            writer.WriteLine();

            SaveFile("GallierEx3_Lr0ParsingTable.txt", writer.ToString());

            ////

            var vertices = LalrLookaheadSetsAlgorithm.GetGotoTransitionPairs(grammar, dfaLr0);

            // Read (INITFOLLOW) sets
            var(directReads, graphRead) = LalrLookaheadSetsAlgorithm.GetGraphReads(grammar, dfaLr0, vertices, analyzer);

            SaveFile("GallierEx3_ReadGraph.dot",
                     DigraphDotLanguagePrinter.PrintGraph("DR", directReads, graphRead, v => vertices[v].ToString()));

            var graphLaFollow = LalrLookaheadSetsAlgorithm.GetGraphLaFollow(grammar, dfaLr0, vertices, analyzer);

            SaveFile("GallierEx3_LaFollowGraph.dot",
                     DigraphDotLanguagePrinter.PrintGraph("INITFOLLOW", directReads, graphLaFollow, v => vertices[v].ToString()));
        }
        public static void DigraphMethods()
        {
            var grammar = GallierCalc.GetGrammar();

            var analyzer = Analyzers.CreateErasableSymbolsAnalyzer(grammar);

            (var initfirstSets, IGraph graphFirst) = DigraphAlgorithm.GetFirstGraph(grammar, analyzer);

            SaveFile("FirstGraph.dot", DigraphDotLanguagePrinter.PrintGraph("INITFIRST", initfirstSets, graphFirst, v => grammar.Nonterminals[v].Name));

            var firstSymbolsAnalyzer = Analyzers.CreateFirstSymbolsAnalyzer(grammar);

            (var initFollowSets, IGraph graphFollow) = DigraphAlgorithm.GetFollowGraph(grammar, firstSymbolsAnalyzer);

            SaveFile("FollowGraph.dot", DigraphDotLanguagePrinter.PrintGraph("INITFOLLOW", initFollowSets, graphFollow, v => grammar.Nonterminals[v].Name));
        }
Exemple #3
0
        public void GetFollowGraph()
        {
            var analyzer = Analyzers.CreateFirstSymbolsAnalyzer(Grammar);

            var(initSets, graph) = DigraphAlgorithm.GetFollowGraph(Grammar, analyzer);

            // INITFOLLOW(S)
            initSets[0].ShouldBeEmpty();
            // INITFOLLOW(E)
            initSets[1].ShouldSetEqual(Grammar.Ts(Sym.PLUS, Sym.RPARAN, Sym.EOF));
            // INITFOLLOW(T)
            initSets[2].ShouldSetEqual(Grammar.Ts(Sym.ASTERISK));
            // INITFOLLOW(F)
            initSets[3].ShouldBeEmpty();

            var closureSets = DigraphAlgorithm.Traverse(graph, new[]
            {
                // trick to inspect closure (unions)
                new Set <string> {
                    "S"
                },
                new Set <string> {
                    "E"
                },
                new Set <string> {
                    "T"
                },
                new Set <string> {
                    "F"
                }
            });

            // FOLLOW(S) = INITFOLLOW(S)
            closureSets[0].ShouldSetEqual("S");
            // FOLLOW(E) = INITFOLLOW(S) ∪ INITFOLLOW(E)
            closureSets[1].ShouldSetEqual("S", "E");
            // FOLLOW(T) = INITFOLLOW(S) ∪ INITFOLLOW(E) ∪ INITFOLLOW(T) ∪ INITFOLLOW(F)
            closureSets[2].ShouldSetEqual("S", "E", "T", "F");
            // FOLLOW(F) = INITFOLLOW(S) ∪ INITFOLLOW(E) ∪ INITFOLLOW(T) ∪ INITFOLLOW(F)
            closureSets[3].ShouldSetEqual("S", "E", "T", "F");
        }