public void ParseEngineGivenAmbiguousGrammarShouldCreateMulipleParsePaths()
        {
            // example 3 section 4, Elizabeth Scott
            var tokens = Tokenize("abbb");

            ProductionExpression B = "B", S = "S", T = "T", A = "A";

            S.Rule = (Expr)A + T | 'a' + T;
            A.Rule = (Expr)'a' | B + A;
            B.Rule = null;
            T.Rule = (Expr)'b' + 'b' + 'b';

            var grammar = new GrammarExpression(S, new[] { S, A, B, T })
                          .ToGrammar();

            var parseEngine = new ParseEngine(grammar);

            ParseInput(parseEngine, tokens);

            var S_0_4 = parseEngine.GetParseForestRootNode() as ISymbolForestNode;

            Assert.IsNotNull(S_0_4);
            AssertNodeProperties(S_0_4, nameof(S), 0, 4);
            Assert.AreEqual(2, S_0_4.Children.Count);

            var S_0_4_1 = S_0_4.Children[0] as IAndForestNode;

            Assert.IsNotNull(S_0_4_1);
            Assert.AreEqual(2, S_0_4_1.Children.Count);

            var a_0_1 = S_0_4_1.Children[0] as ITokenForestNode;

            Assert.IsNotNull(a_0_1);
            Assert.AreEqual("a", a_0_1.Token.Value);

            var T_1_4 = S_0_4_1.Children[1] as ISymbolForestNode;

            Assert.IsNotNull(T_1_4);
            AssertNodeProperties(T_1_4, nameof(T), 1, 4);
            Assert.AreEqual(1, T_1_4.Children.Count);

            var S_0_4_2 = S_0_4.Children[1] as IAndForestNode;

            Assert.IsNotNull(S_0_4_2);
            Assert.AreEqual(2, S_0_4_2.Children.Count);

            var A_0_1 = S_0_4_2.Children[0] as ISymbolForestNode;

            Assert.IsNotNull(A_0_1);
            AssertNodeProperties(A_0_1, nameof(A), 0, 1);
            Assert.AreEqual(2, A_0_1.Children.Count);

            var A_0_1_1 = A_0_1.Children[0] as IAndForestNode;

            Assert.IsNotNull(A_0_1_1);
            Assert.AreEqual(1, A_0_1_1.Children.Count);

            Assert.AreSame(a_0_1, A_0_1_1.Children[0]);

            var A_0_1_2 = A_0_1.Children[1] as IAndForestNode;

            Assert.IsNotNull(A_0_1_1);
            Assert.AreEqual(2, A_0_1_2.Children.Count);

            Assert.AreSame(A_0_1, A_0_1_2.Children[1]);

            var B_0_0 = A_0_1_2.Children[0] as ISymbolForestNode;

            Assert.IsNotNull(B_0_0);
            AssertNodeProperties(B_0_0, nameof(B), 0, 0);
            Assert.AreEqual(1, B_0_0.Children.Count);

            var B_0_0_1 = B_0_0.Children[0] as IAndForestNode;

            Assert.IsNotNull(B_0_0_1);
            Assert.AreEqual(1, B_0_0_1.Children.Count);

            var nullToken = B_0_0_1.Children[0] as ITokenForestNode;

            Assert.IsNotNull(nullToken);
            Assert.AreEqual(string.Empty, nullToken.Token.Value);

            var T_1_4_1 = T_1_4.Children[0] as IAndForestNode;

            Assert.IsNotNull(T_1_4_1);
            Assert.AreEqual(2, T_1_4_1.Children.Count);

            var T_1_3 = T_1_4_1.Children[0] as IIntermediateForestNode;

            Assert.IsNotNull(T_1_3);
            Assert.AreEqual(1, T_1_3.Children.Count);

            var b_3_4 = T_1_4_1.Children[1] as ITokenForestNode;

            Assert.IsNotNull(b_3_4);
            Assert.AreEqual("b", b_3_4.Token.Value);

            var T_1_3_1 = T_1_3.Children[0] as IAndForestNode;

            Assert.IsNotNull(T_1_3_1);
            Assert.AreEqual(2, T_1_3_1.Children.Count);

            var b_1_2 = T_1_3_1.Children[0] as ITokenForestNode;

            Assert.IsNotNull(b_1_2);
            Assert.AreEqual("b", b_1_2.Token.Value);

            var b_2_3 = T_1_3_1.Children[1] as ITokenForestNode;

            Assert.IsNotNull(b_2_3);
            Assert.AreEqual("b", b_2_3.Token.Value);
        }
        public void ParseEngineShouldParseMidGrammarRightRecursionAndHandleNullRootTransitionItem()
        {
            ProductionExpression S = "S", A = "A", B = "B", C = "C";

            S.Rule = (Expr)A | A + S;
            A.Rule = (Expr)B | B + C;
            B.Rule = (Expr)'.';
            C.Rule = (Expr)'+' | '?' | '*';

            var grammar     = new GrammarExpression(S, new[] { S, A, B, C }).ToGrammar();
            var tokens      = Tokenize(".+");
            var parseEngine = new ParseEngine(grammar);

            ParseInput(parseEngine, tokens);

            var parseForestRoot = parseEngine.GetParseForestRootNode();
            var parseForest     = parseForestRoot;

            Assert.IsNotNull(parseForest);

            // S_0_2 -> A_0_2
            // A_0_2 -> B_0_1 C_1_2
            // B_0_1 -> '.'_0_1
            // C_1_2 -> '+'_1_2
            var S_0_2 = parseForest as ISymbolForestNode;

            Assert.IsNotNull(S_0_2);
            Assert.AreEqual(1, S_0_2.Children.Count);

            var S_0_2_1 = S_0_2.Children[0] as IAndForestNode;

            Assert.IsNotNull(S_0_2_1);
            Assert.AreEqual(1, S_0_2_1.Children.Count);

            var A_0_2 = S_0_2_1.Children[0] as ISymbolForestNode;

            Assert.IsNotNull(A_0_2);
            Assert.AreEqual(1, A_0_2.Children.Count);

            var A_0_2_1 = A_0_2.Children[0] as IAndForestNode;

            Assert.IsNotNull(A_0_2_1);
            Assert.AreEqual(2, A_0_2_1.Children.Count);

            var B_0_1 = A_0_2_1.Children[0] as ISymbolForestNode;

            Assert.IsNotNull(B_0_1);
            Assert.AreEqual(1, B_0_1.Children.Count);

            var B_0_1_1 = B_0_1.Children[0] as IAndForestNode;

            Assert.IsNotNull(B_0_1_1);
            Assert.AreEqual(1, B_0_1_1.Children.Count);

            var dot_0_1 = B_0_1_1.Children[0] as ITokenForestNode;

            Assert.IsNotNull(dot_0_1);
            Assert.AreEqual(".", dot_0_1.Token.Value);

            var C_1_2 = A_0_2_1.Children[1] as ISymbolForestNode;

            Assert.IsNotNull(C_1_2);

            var C_1_2_1 = C_1_2.Children[0] as IAndForestNode;

            Assert.IsNotNull(C_1_2_1);
            Assert.AreEqual(1, C_1_2_1.Children.Count);

            var plus_1_2 = C_1_2_1.Children[0] as ITokenForestNode;

            Assert.IsNotNull(plus_1_2);
            Assert.AreEqual("+", plus_1_2.Token.Value);
        }
        public void ParseEngineLeoItemsShouldGenerateProperParseTree()
        {
            ProductionExpression S = "S", A = "A";

            S.Rule = A;
            A.Rule = 'a' + A | 'b';

            var grammar = new GrammarExpression(S, new[] { S, A }).ToGrammar();

            var tokens      = Tokenize("ab");
            var parseEngine = new ParseEngine(grammar);

            ParseInput(parseEngine, tokens);

            /*  S_0_2 -> A_0_2
             *  A_0_2 -> a_0_1 A_1_2
             *  A_1_2 -> b_1_2
             */
            var parseForestRoot = parseEngine.GetParseForestRootNode();
            var root            = parseForestRoot;

            var S_0_2 = root as ISymbolForestNode;

            Assert.IsNotNull(S_0_2);
            Assert.AreEqual(1, S_0_2.Children.Count);

            var S_0_2_1 = S_0_2.Children[0] as IAndForestNode;

            Assert.IsNotNull(S_0_2_1);
            Assert.AreEqual(1, S_0_2_1.Children.Count);

            var A_0_2 = S_0_2_1.Children[0] as ISymbolForestNode;

            Assert.IsNotNull(A_0_2);
            Assert.AreEqual(1, A_0_2.Children.Count);

            var A_0_2_1 = A_0_2.Children[0] as IAndForestNode;

            Assert.IsNotNull(A_0_2_1);
            Assert.AreEqual(2, A_0_2_1.Children.Count);

            var a_0_1 = A_0_2_1.Children[0] as ITokenForestNode;

            Assert.IsNotNull(a_0_1);
            Assert.AreEqual("a", a_0_1.Token.Value);

            var A_1_2 = A_0_2_1.Children[1] as ISymbolForestNode;

            Assert.IsNotNull(A_1_2);
            Assert.AreEqual(1, A_1_2.Children.Count);

            var A_1_2_1 = A_1_2.Children[0] as IAndForestNode;

            Assert.IsNotNull(A_1_2_1);
            Assert.AreEqual(1, A_1_2_1.Children.Count);

            var b_1_2 = A_1_2_1.Children[0] as ITokenForestNode;

            Assert.IsNotNull(b_1_2);
            Assert.AreEqual("b", b_1_2.Token.Value);
        }
        public void ParseEnginePassThroughRecursiveItemsShouldCreateVirtualNodes()
        {
            ProductionExpression S = "S", A = "A", B = "B";

            S.Rule = A;
            A.Rule = 'a' + B;
            B.Rule = A | 'b';

            var grammar = new GrammarExpression(S, new[] { S, A, B }).ToGrammar();
            var tokens  = Tokenize("aaab");

            var parseEngine = new ParseEngine(grammar);

            ParseInput(parseEngine, tokens);

            /*  S_0_4 -> A_0_4
             *  A_0_4 -> 'a' B_1_4
             *  B_1_4 -> A_1_4
             *  A_1_4 -> 'a' B_2_4
             *  B_2_4 -> A_2_4
             *  A_2_4 -> 'a' B_3_4
             *  B_3_4 -> 'b'
             */
            var parseForestRoot = parseEngine.GetParseForestRootNode();
            var root            = parseForestRoot;

            var S_0_4 = root as ISymbolForestNode;

            Assert.IsNotNull(S_0_4);
            Assert.AreEqual(1, S_0_4.Children.Count);

            var S_0_4_1 = S_0_4.Children[0] as IAndForestNode;

            Assert.IsNotNull(S_0_4_1);
            Assert.AreEqual(1, S_0_4_1.Children.Count);

            var A_0_4 = S_0_4_1.Children[0] as ISymbolForestNode;

            Assert.IsNotNull(A_0_4);
            Assert.AreEqual(1, A_0_4.Children.Count);

            var A_0_4_1 = A_0_4.Children[0] as IAndForestNode;

            Assert.IsNotNull(A_0_4_1);
            Assert.AreEqual(2, A_0_4_1.Children.Count);

            var a_0_1 = A_0_4_1.Children[0] as ITokenForestNode;

            Assert.IsNotNull(a_0_1);
            Assert.AreEqual("a", a_0_1.Token.Value);

            var B_1_4 = A_0_4_1.Children[1] as ISymbolForestNode;

            Assert.IsNotNull(B_1_4);
            Assert.AreEqual(1, B_1_4.Children.Count);

            var B_1_4_1 = B_1_4.Children[0] as IAndForestNode;

            Assert.IsNotNull(B_1_4_1);
            Assert.AreEqual(1, B_1_4_1.Children.Count);

            var A_1_4 = B_1_4_1.Children[0] as ISymbolForestNode;

            Assert.IsNotNull(A_1_4);
            Assert.AreEqual(1, A_1_4.Children.Count);

            var A_1_4_1 = A_1_4.Children[0] as IAndForestNode;

            Assert.IsNotNull(A_1_4_1);
            Assert.AreEqual(2, A_1_4_1.Children.Count);

            var a_1_2 = A_1_4_1.Children[0] as ITokenForestNode;

            Assert.IsNotNull(a_1_2);
            Assert.AreEqual("a", a_1_2.Token.Value);

            var B_2_4 = A_1_4_1.Children[1] as ISymbolForestNode;

            Assert.IsNotNull(B_2_4);
            Assert.AreEqual(1, B_2_4.Children.Count);

            var B_2_4_1 = B_2_4.Children[0] as IAndForestNode;

            Assert.IsNotNull(B_2_4_1);
            Assert.AreEqual(1, B_2_4_1.Children.Count);

            var A_2_4 = B_2_4_1.Children[0] as ISymbolForestNode;

            Assert.IsNotNull(A_2_4);
            Assert.AreEqual(1, A_2_4.Children.Count);

            var A_2_4_1 = A_2_4.Children[0] as IAndForestNode;

            Assert.IsNotNull(A_2_4_1);
            Assert.AreEqual(2, A_2_4_1.Children.Count);

            var a_2_3 = A_2_4_1.Children[0] as ITokenForestNode;

            Assert.IsNotNull(a_2_3);
            Assert.AreEqual("a", a_2_3.Token.Value);

            var B_3_4 = A_2_4_1.Children[1] as ISymbolForestNode;

            Assert.IsNotNull(B_3_4);
            Assert.AreEqual(1, B_3_4.Children.Count);

            var B_3_4_1 = B_3_4.Children[0] as IAndForestNode;

            Assert.IsNotNull(B_3_4_1);
            Assert.AreEqual(1, B_3_4_1.Children.Count);

            var b_3_4 = B_3_4_1.Children[0] as ITokenForestNode;

            Assert.IsNotNull(b_3_4);
            Assert.AreEqual("b", b_3_4.Token.Value);
        }
        public void NodeVisitorShouldEnumerateAllParseTrees()
        {
            ProductionExpression And              = "AND",
                                 Panda            = "Panda",
                                 AAn              = "AAn",
                                 ShootsLeaves     = "ShootsAndLeaves",
                                 EatsShootsLeaves = "EatsShootsLeaves"
            ;

            And.Rule = (Expr)'a' + 'n' + 'd';
            var and = new GrammarExpression(And, new[] { And }).ToGrammar();

            Panda.Rule = (Expr)'p' + 'a' + 'n' + 'd' + 'a';
            var panda = new GrammarExpression(Panda, new[] { Panda }).ToGrammar();

            AAn.Rule = (Expr)'a' | (Expr)'a' + 'n';
            var aAn = new GrammarExpression(AAn, new[] { AAn }).ToGrammar();

            ShootsLeaves.Rule =
                (Expr)"shoots"
                | (Expr)"leaves";
            var shootsLeaves = new GrammarExpression(ShootsLeaves, new[] { ShootsLeaves }).ToGrammar();

            EatsShootsLeaves.Rule =
                (Expr)'e' + 'a' + 't' + 's'
                | (Expr)'s' + 'h' + 'o' + 'o' + 't' + 's'
                | (Expr)'l' + 'e' + 'a' + 'v' + 'e' + 's';
            var eatsShootsLeaves = new GrammarExpression(EatsShootsLeaves, new[] { EatsShootsLeaves }).ToGrammar();

            ProductionExpression
                S = "S", NP = "NP", VP = "VP", NN = "NN",
                NNS = "NNS", DT = "DT", CC = "CC", VBZ = "VBZ";

            S.Rule =
                NP + VP + '.';
            NP.Rule =
                NN
                | NNS
                | DT + NN
                | NN + NNS
                | NNS + CC + NNS;
            VP.Rule = VBZ + NP
                      | VP + VBZ + NNS
                      | VP + CC + VP
                      | VP + VP + CC + VP
                      | VBZ;
            CC.Rule  = new GrammarLexerRule(nameof(CC), and);
            DT.Rule  = new GrammarLexerRule(nameof(DT), aAn);
            NN.Rule  = new GrammarLexerRule(nameof(NN), panda);
            NNS.Rule = new GrammarLexerRule(nameof(NNS), shootsLeaves);
            VBZ.Rule = new GrammarLexerRule(nameof(VBZ), eatsShootsLeaves);

            var grammar = new GrammarExpression(
                S,
                new[] { S, NP, VP, CC, DT, NN, NNS, VBZ },
                new[] { new LexerRuleModel(_whitespace) })
                          .ToGrammar();
            var sentence = "a panda eats shoots and leaves.";

            var parseEngine = new ParseEngine(grammar);
            var parseRunner = new ParseRunner(parseEngine, sentence);

            while (!parseRunner.EndOfStream())
            {
                Assert.IsTrue(parseRunner.Read(),
                              $"Error parsing position: {parseRunner.Position}");
            }
            Assert.IsTrue(parseRunner.ParseEngine.IsAccepted());
        }