Пример #1
0
        public void TestNonSLRGrammar()
        {
            // 1. S’ ::= S     4. L ::= * R
            // 2. S ::= L = R  5. L ::= id
            // 3. S ::= R      6. R ::= L
            var configurator = ParserFactory.Configure <int>();
            var s            = configurator.CreateNonTerminal();

            s.DebugName = "S";
            var l = configurator.CreateNonTerminal();

            l.DebugName = "L";
            var r = configurator.CreateNonTerminal();

            r.DebugName = "R";

            s.AddProduction(l, "=", r);
            s.AddProduction(r);

            l.AddProduction("*", r);
            l.AddProduction("id");

            r.AddProduction(l);
            configurator.CreateParser();
        }
Пример #2
0
        public void TestMultipleEpsilonParametersInARow()
        {
            var configurator = ParserFactory.Configure <int>();
            var a            = configurator.CreateNonTerminal();

            a.DebugName = "A";
            var b = configurator.CreateNonTerminal();

            b.DebugName = "B";
            var c = configurator.CreateNonTerminal();

            c.DebugName = "C";
            var d = configurator.CreateNonTerminal();

            d.DebugName = "D";

            a.AddProduction("a", b, c, d, "a");
            b.AddProduction("b");
            b.AddProduction();

            c.AddProduction("c");
            c.AddProduction();
            d.AddProduction("d");
            d.AddProduction();

            var parser = configurator.CreateParser();

            parser.Parse("aa");
            parser.Parse("aba");
            parser.Parse("abca");
            parser.Parse("abcda");
            parser.Parse("aca");
            parser.Parse("ada");
            parser.Parse("abda");
        }
Пример #3
0
        public void TestGrammarWithEpsilonTransitions()
        {
            var configurator = ParserFactory.Configure <int>();
            var func         = configurator.CreateNonTerminal();

            func.DebugName = "FUNC";
            var paramList = configurator.CreateNonTerminal();

            paramList.DebugName = "PARAMLIST";
            var optionalParamList = configurator.CreateNonTerminal();

            optionalParamList.DebugName = "OPTIONALPARAMLIST";

            func.AddProduction("func", "(", optionalParamList, ")");
            paramList.AddProduction(paramList, ",", "ident");
            paramList.AddProduction("ident");

            optionalParamList.AddProduction(paramList);
            optionalParamList.AddProduction();

            var parser = configurator.CreateParser();

            parser.Parse("func(ident,ident,ident,ident)");
            parser.Parse("func()");
        }
Пример #4
0
        public void TestDeepEpsilonChain()
        {
            var configurator = ParserFactory.Configure <int>();
            var a            = configurator.CreateNonTerminal();
            var b            = configurator.CreateNonTerminal();
            var c            = configurator.CreateNonTerminal();
            var d            = configurator.CreateNonTerminal();
            var e            = configurator.CreateNonTerminal();

            a.AddProduction("a", b);
            b.AddProduction(c);
            b.AddProduction();

            c.AddProduction("d", d);

            d.AddProduction(e);
            d.AddProduction();

            e.AddProduction("e");

            var parser = configurator.CreateParser();

            parser.Parse("ade");
            parser.Parse("a");
            parser.Parse("ad");
        }
Пример #5
0
        public void TestNonAssociativity()
        {
            try
            {
                // Configure an illegal rule
                var configurator = ParserFactory.Configure <int>();

                var number = configurator.CreateTerminal(@"\d+",
                                                         int.Parse);
                var equals = configurator.CreateTerminal("=");

                configurator.NonAssociative(equals);


                var exp = configurator.CreateNonTerminal();

                exp.AddProduction(exp, equals, exp)
                .SetReduceFunction(f => f[0] - f[2]);
                exp.AddProduction(number).SetReduceFunction(
                    f => f[0]);

                configurator.CreateParser();
                Assert.Fail("You shall not parse!");
            }
            catch (ShiftReduceConflictException <int> )
            {
                // We cool
            }
        }
Пример #6
0
        public void TestACalculator()
        {
            // This is a full on integration test that builds a parser and performs a simple calculation.
            var configurator = ParserFactory.Configure <int>();

            ITerminal <int> number = configurator.CreateTerminal("\\d+", int.Parse);

            number.DebugName = "number";

            INonTerminal <int> expr = configurator.CreateNonTerminal();

            expr.DebugName = "expr";
            INonTerminal <int> term = configurator.CreateNonTerminal();

            term.DebugName = "term";
            INonTerminal <int> factor = configurator.CreateNonTerminal();

            factor.DebugName = "factor";

            expr.AddProduction(expr, "+", term).SetReduceFunction(s => s[0] + s[2]);
            expr.AddProduction(expr, "-", term).SetReduceFunction(s => s[0] - s[2]);
            expr.AddProduction(term).SetReduceFunction(s => s[0]);

            term.AddProduction(term, "*", factor).SetReduceFunction(s => s[0] * s[2]);
            term.AddProduction(term, "/", factor).SetReduceFunction(s => s[0] / s[2]);
            term.AddProduction(factor).SetReduceFunction(s => s[0]);

            factor.AddProduction(number).SetReduceFunction(s => s[0]);
            factor.AddProduction("(", expr, ")").SetReduceFunction(s => s[1]);

            var parser = configurator.CreateParser();
            int result = parser.Parse(new StringReader("2-2-5"));

            Assert.AreEqual(-5, result);
        }
Пример #7
0
        public void TestShiftReduceError()
        {
            INonTerminal <string> ifStatement = null;

            try
            {
                // This configuration is not a valid LR1 parser. It contains shift reduce conflicts
                // clasical dangling else case
                var configurator = ParserFactory.Configure <string>();
                var ident        = configurator.CreateTerminal("[a-z]+");
                ident.DebugName = "ident";

                ifStatement           = configurator.CreateNonTerminal();
                ifStatement.DebugName = "ifStatement";

                var statement = configurator.CreateNonTerminal();
                statement.DebugName = "statement";

                ifStatement.AddProduction("if", "\\(", ident, "\\)", "then", statement);
                ifStatement.AddProduction("if", "\\(", ident, "\\)", "then", statement, "else", statement);

                statement.AddProduction(ifStatement);
                statement.AddProduction(ident, "=", ident);

                configurator.LexerSettings.CreateLexer = false;
                configurator.CreateParser();

                Assert.Fail("No exception for ambiguous grammar");
            }
            catch (ShiftReduceConflictException <string> e)
            {
                Assert.AreEqual(ifStatement, e.ReduceSymbol);
                Assert.AreEqual("else", e.ShiftSymbol.DebugName);
            }
        }
Пример #8
0
        public void TestParseTableToString()
        {
            // Need to get our hands on a parse table, which isn't the easiest thing for a normal user
            // since its encapsulated and destroyed. However, we have magic casts at our disposal.
            // We are simply going to test that it doesn't break, not really what it contains.
            var configurator = ParserFactory.Configure <int>();

            var a = configurator.CreateNonTerminal();

            a.DebugName = "a";
            var b = configurator.CreateNonTerminal();

            b.DebugName = "b";
            var c = configurator.CreateNonTerminal();

            c.DebugName = "c";

            a.AddProduction(b);
            a.AddProduction(c);

            b.AddProduction("b");
            c.AddProduction("c");

            var grammar = (IGrammar <int>)configurator;
            var parser  = configurator.CreateParser();

            string debugString = parser.ParseTable.ToDebugString(grammar, 3);

            Assert.IsNotNull(debugString);
        }
Пример #9
0
        public void TestSingleRuleTerminalGrammar()
        {
            var configurator = ParserFactory.Configure <int>();
            var s            = configurator.CreateNonTerminal();

            s.DebugName = "S";
            s.AddProduction("a", "b", "c", "d");
            var parser = configurator.CreateParser();

            parser.Parse("abcd");
        }
Пример #10
0
        public void TestCanMultiplyDefineTerminalStringsInConfiguration()
        {
            var configurator = ParserFactory.Configure <int>();
            INonTerminal <int> nonTerminal = configurator.CreateNonTerminal();

            nonTerminal.DebugName = "NonTerm";
            nonTerminal.AddProduction("this", "is", "a", "string");
            nonTerminal.AddProduction("this", "is", "a", "test");

            var parser = configurator.CreateParser();

            Assert.IsNotNull(parser);
        }
Пример #11
0
        public void TestLeftAssociative()
        {
            var configurator = ParserFactory.Configure <int>();
            var number       = configurator.CreateTerminal(@"\d+", int.Parse);
            var plus         = configurator.CreateTerminal("\\+");
            var minus        = configurator.CreateTerminal("-");
            var mul          = configurator.CreateTerminal("\\*");
            var div          = configurator.CreateTerminal("/");

            configurator.LeftAssociative(plus, minus);
            configurator.LeftAssociative(mul, div);

            var exp = configurator.CreateNonTerminal();

            exp.AddProduction(exp, plus, exp).SetReduceFunction(s =>
            {
                Console.WriteLine("{0} + {1}", s[0], s[2]);
                return(s[0] + s[2]);
            });
            exp.AddProduction(exp, minus, exp).SetReduceFunction(s =>
            {
                Console.WriteLine("{0} - {1}", s[0], s[2]);
                return(s[0] - s[2]);
            });
            exp.AddProduction(exp, mul, exp).SetReduceFunction(s =>
            {
                Console.WriteLine("{0} * {1}", s[0], s[2]);
                return(s[0] * s[2]);
            });
            exp.AddProduction(exp, div, exp).SetReduceFunction(s =>
            {
                Console.WriteLine("{0} / {1}", s[0], s[2]);
                return(s[0] / s[2]);
            });
            exp.AddProduction("(", exp, ")").SetReduceFunction(s =>
            {
                Console.WriteLine("Paranthesis ({0})", s[1]);
                return(s[1]);
            });
            exp.AddProduction(number).SetReduceFunction(s => s[0]);

            var parser = configurator.CreateParser();

            Assert.AreEqual(-2, parser.Parse("1 - (1 + (1 * 2))"));
            Assert.AreEqual(2, parser.Parse("(((1 - 1) + 1) * 2)"));
            Assert.AreEqual(4 - 7 - 3, parser.Parse("4 - 7 - 3"));
            Assert.AreEqual(1 + 2 - 3 * 4, parser.Parse("1 + 2 - 3 * 4"));
            Assert.AreEqual(5 * 5 / 5, parser.Parse("5*5/5"));

            Assert.AreEqual(1 + 2 - 3 * 4 / 5 + 124 * 8, parser.Parse("1 + 2 - 3 * 4 / 5 + 124 * 8"));
        }
Пример #12
0
        public void TestNonTerminalFollow()
        {
            // This grammar will require the parser factory to perform an aggregated FOLLOW
            // which it doesn't do if there aren't two nonteminals in a row
            var configurator = ParserFactory.Configure <int>();
            var a            = configurator.CreateNonTerminal();
            var b            = configurator.CreateNonTerminal();
            var c            = configurator.CreateNonTerminal();
            var d            = configurator.CreateNonTerminal();

            a.AddProduction(a, b, c, d);
            b.AddProduction("b");
            c.AddProduction(b);
            d.AddProduction("d");

            configurator.CreateParser();
        }
Пример #13
0
 public void TestRetardedCyclicGrammar()
 {
     try
     {
         var configurator = ParserFactory.Configure <byte>();
         var t            = configurator.CreateNonTerminal();
         t.AddProduction(t);
         configurator.CreateParser();
         Assert.Fail();
     }
     catch (ShiftReduceConflictException <byte> )
     {
         // There is no real need to check this exception. It says something
         // about wanting to shift the augmented start symbol. We are cool that this
         // sillyness doesn't run on forever.
     }
 }
Пример #14
0
        public static void RunTechnical()
        {
            var configurator = ParserFactory.Configure <bool>();

            configurator.LexerSettings.Ignore = new[] { @"\s+" };

            var name         = configurator.CreateTerminal("[a-z]+");
            var quotedString = configurator.CreateTerminal("\"[^\"]+\"");

            var obj = configurator.CreateNonTerminal();
            var optionalObjectList    = configurator.CreateNonTerminal();
            var objectList            = configurator.CreateNonTerminal();
            var optionalAttributeList = configurator.CreateNonTerminal();
            var attributeList         = configurator.CreateNonTerminal();
            var attribute             = configurator.CreateNonTerminal();

            obj.AddProduction(name, "{", optionalObjectList, optionalAttributeList, "}");

            optionalObjectList.AddProduction(objectList);
            optionalObjectList.AddProduction();

            objectList.AddProduction(objectList, obj);
            objectList.AddProduction(obj);

            optionalAttributeList.AddProduction(attributeList);
            optionalAttributeList.AddProduction();

            attributeList.AddProduction(attributeList, attribute);
            attributeList.AddProduction(attribute);

            attribute.AddProduction("[", name, "=", quotedString, "]");

            var parser = configurator.CreateParser();

            parser.Parse("fruits {" +
                         "    banana {" +
                         "        [tasty=\"true\"]" +
                         "        [colour=\"yellow\"]" +
                         "    }" +
                         "" +
                         "    orange {" +
                         "    }" +
                         "    " +
                         "    [eatable=\"if not rotten\"]" +
                         "}");
        }
Пример #15
0
        public void TestConstantStringsInRulesTakesPrecedenceOverDeclaredTerminals()
        {
            var configurator = ParserFactory.Configure <int>();
            var ident        = configurator.CreateTerminal("[a-z]+");
            var s            = configurator.CreateNonTerminal();
            int x            = 0;

            s.AddProduction("abc", ident).SetReduceFunction(f =>
            {
                x = 1;
                return(0);
            });
            var parser = configurator.CreateParser();

            parser.Parse("abc abcde");

            Assert.AreEqual(1, x);
        }
Пример #16
0
        public void TestRightAssociativity()
        {
            var configurator = ParserFactory.Configure <int>();
            var number       = configurator.CreateTerminal(@"\d+",
                                                           int.Parse);
            var minus = configurator.CreateTerminal("-");

            configurator.RightAssociative(minus);

            var exp = configurator.CreateNonTerminal();

            exp.AddProduction(exp, minus, exp).SetReduceFunction(f => f[0] - f[2]);
            exp.AddProduction(number).SetReduceFunction(f => f[0]);

            var parser = configurator.CreateParser();

            Assert.AreEqual(4 - (7 - 3), parser.Parse("4 - 7 - 3"));
        }
Пример #17
0
        public void TestRecoverFromErrors()
        {
            // Valid inputs are long lists of "a" followed by a ;.
            // "b" however is a legal token, and the error recovery should
            // skip tokens until it gets another ;.
            // The error recovery routine should also be called with the exception that is generated at that point
            int caughtErrors = 0;
            var configurator = ParserFactory.Configure <int>();

            var listOfA     = configurator.CreateNonTerminal();
            var a           = configurator.CreateNonTerminal();
            var terminatedA = configurator.CreateNonTerminal();

            a.AddProduction(a, "a").SetReduceFunction(f => f[0] + 1);
            a.AddProduction("a").SetReduceFunction(f => 1);

            terminatedA.AddProduction(a, ";").SetReduceFunction(f => f[0]);
            terminatedA.AddProduction(configurator.ErrorToken, ";").SetErrorFunction((e, f) =>
            {
                Console.WriteLine(e);
                ++caughtErrors;
                return(0);
            });

            listOfA.AddProduction(terminatedA).SetReduceFunction(f => f[0]);
            listOfA.AddProduction(listOfA, terminatedA).SetReduceFunction(f => f[0] + f[1]);

            // Bogus terminal that isn't in any sort of use
            configurator.CreateTerminal("b");

            var parser = configurator.CreateParser();

            const string legal   = "aaaaaaa;aaaaaaaaaa;aaa;aa;a;aaaaa;aaaaaaaa;";
            int          legalAs = parser.Parse(legal);

            Assert.AreEqual(legal.Aggregate(0, (i, c) => c == 'a' ? i + 1 : i), legalAs);
            Assert.AreEqual(0, caughtErrors);

            const string withErrors = "aaaaaaa;aaaaaabaaa;aaa;aa;a;aaaaa;aaaaaaaa;";

            legalAs = parser.Parse(withErrors);
            Assert.AreEqual("aaaaaaa;THESEAREEATEN;aaa;aa;a;aaaaa;aaaaaaaa;".Aggregate(0, (i, c) => c == 'a' ? i + 1 : i), legalAs);
            Assert.AreEqual(1, caughtErrors);
        }
Пример #18
0
        public void TestRedeclaredTerminalDoesNotChangePrecedence()
        {
            var configurator = ParserFactory.Configure <int>();
            var name         = configurator.CreateTerminal("abc");
            var ident        = configurator.CreateTerminal("[a-z]+");
            var s            = configurator.CreateNonTerminal();
            int x            = 0;

            s.AddProduction("abc", ident).SetReduceFunction(f =>
            {
                x = 1;
                return(0);
            });
            var parser = configurator.CreateParser();

            parser.Parse("abc abcde");

            Assert.AreEqual(1, x);
        }
Пример #19
0
        public void TestUnaryMinus()
        {
            var configurator = ParserFactory.Configure <int>();
            var expr         = configurator.CreateNonTerminal();
            var mul          = configurator.CreateTerminal(@"\*");
            var minus        = configurator.CreateTerminal("-");
            var number       = configurator.CreateTerminal(@"\d+", int.Parse);

            configurator.LeftAssociative(minus);
            configurator.LeftAssociative(mul);
            var highPrecgroup = configurator.LeftAssociative();

            expr.AddProduction(expr, minus, expr).SetReduceFunction(f =>
            {
                Console.WriteLine("{0} - {1}", f[0], f[2]);
                return(f[0] - f[2]);
            });

            expr.AddProduction(expr, mul, expr).SetReduceFunction(f =>
            {
                Console.WriteLine("{0} * {1}", f[0], f[2]);
                return(f[0] * f[2]);
            });

            var uMinusProduction = expr.AddProduction(minus, expr);

            uMinusProduction.SetReduceFunction(f =>
            {
                Console.WriteLine("-{0}", f[1]);
                return(-f[1]);
            });
            uMinusProduction.SetPrecedence(highPrecgroup);

            expr.AddProduction(number).SetReduceFunction(f => f[0]);

            var parser = configurator.CreateParser();

            int result = parser.Parse("9 - -5*-4 - 2");

            Assert.AreEqual(9 - -5 * -4 - 2, result);
        }
Пример #20
0
        public void TestShiftReduceConflictWithAccept()
        {
            // For certain grammars you can produce this stuff. It is not a real world case
            // but the exception should still be helpful

            // Here's how this retarded grammar looks
            // a := a | b | c
            // b := "b"
            // c := "c"
            //
            try
            {
                var configurator = ParserFactory.Configure <int>();
                var a            = configurator.CreateNonTerminal();
                a.DebugName = "a";
                var b = configurator.CreateNonTerminal();
                b.DebugName = "b";
                var c = configurator.CreateNonTerminal();
                c.DebugName = "c";

                a.AddProduction(a);
                a.AddProduction(b);
                a.AddProduction(c);

                b.AddProduction("b");

                c.AddProduction("c");

                configurator.CreateParser();

                Assert.Fail();
            }
            catch (ShiftReduceConflictException <int> )
            {
                // There is no real need to check this exception. It says something
                // about wanting to reduce on the $. We are cool that this
                // sillyness doesn't run on forever.
            }
        }
Пример #21
0
        public void TestLr1Harness()
        {
            // Duplicate grammar from dragon book, for comparison
            //
            // S -> CC
            // C -> cC | d
            var configurator = ParserFactory.Configure <int>();
            var s            = configurator.CreateNonTerminal();

            s.DebugName = "S";
            var c = configurator.CreateNonTerminal();

            c.DebugName = "C";

            s.AddProduction(c, c);
            c.AddProduction("c", c);
            c.AddProduction("d");

            var parser = configurator.CreateParser();

            parser.Parse("ccccccccdd");
        }
Пример #22
0
        public void TestBadToken()
        {
            var c = ParserFactory.Configure <int>();
            var a = c.CreateNonTerminal();

            c.CreateTerminal("b");

            a.AddProduction(a, "a");
            a.AddProduction("a");

            var parser = c.CreateParser();

            try
            {
                parser.Parse("aa    aaa\naa a a a\na a a b");
                Assert.Fail("No error for bad token");
            }
            catch (ParseException e)
            {
                Assert.AreEqual(3, e.LexerState.CurrentLineNumber);
                Assert.AreEqual("a a a b", e.LexerState.CurrentLine);
            }
        }
Пример #23
0
        public void TestReduceReduceConflict()
        {
            // Represents the grammar
            //
            // x := t | y
            // t := "A"
            // y := "A"
            //
            INonTerminal <object> y = null, t = null;

            try
            {
                var configurator        = ParserFactory.Configure <object>();
                INonTerminal <object> x = configurator.CreateNonTerminal();
                x.DebugName = "X";

                t           = configurator.CreateNonTerminal();
                t.DebugName = "T";

                y           = configurator.CreateNonTerminal();
                y.DebugName = "Y";

                x.AddProduction(t);
                x.AddProduction(y);

                t.AddProduction("A");
                y.AddProduction("A");

                configurator.CreateParser();
                Assert.Fail();
            }
            catch (ReduceReduceConflictException <object> e)
            {
                Assert.AreEqual(y, e.NewReduceSymbol);
                Assert.AreEqual(t, e.PreviousReduceSymbol);
            }
        }
Пример #24
0
        public static void Run()
        {
            var configurator = ParserFactory.Configure <object>();

            var quotedString = configurator.CreateTerminal("\"(\\\\.|[^\"])*\"", f => f.Substring(1, f.Length - 2));
            var doubleValue  = configurator.CreateTerminal(@"\d+\.\d+", f => double.Parse(f));
            var integerValue = configurator.CreateTerminal(@"\d+", f => int.Parse(f));

            var jsonObject          = configurator.CreateNonTerminal();
            var optionalElementList = configurator.CreateNonTerminal();
            var elementList         = configurator.CreateNonTerminal();
            var element             = configurator.CreateNonTerminal();
            var value             = configurator.CreateNonTerminal();
            var array             = configurator.CreateNonTerminal();
            var optionalValueList = configurator.CreateNonTerminal();
            var valueList         = configurator.CreateNonTerminal();

            jsonObject.AddProduction("{", optionalElementList, "}")
            .SetReduceFunction(f => new JsonObject {
                Elements = (List <JsonElement>)f[1]
            });

            optionalElementList.AddProduction(elementList)
            .SetReduceFunction(f => f[0]);

            optionalElementList.AddProduction()
            .SetReduceFunction(f => new List <JsonElement>());

            elementList.AddProduction(elementList, ",", element)
            .SetReduceFunction(f =>
            {
                var list = (List <JsonElement>)f[0];
                list.Add((JsonElement)f[2]);
                return(list);
            });

            elementList.AddProduction(element)
            .SetReduceFunction(f => new List <JsonElement> {
                (JsonElement)f[0]
            });

            element.AddProduction(quotedString, ":", value)
            .SetReduceFunction(f => new JsonElement {
                Name = (string)f[0], Value = f[2]
            });


            value.AddProduction(quotedString).SetReduceFunction(f => f[0]);
            value.AddProduction(integerValue).SetReduceFunction(f => f[0]);
            value.AddProduction(doubleValue).SetReduceFunction(f => f[0]);
            value.AddProduction(jsonObject).SetReduceFunction(f => f[0]);
            value.AddProduction(array).SetReduceFunction(f => f[0]);
            value.AddProduction("true").SetReduceFunction(f => true);
            value.AddProduction("false").SetReduceFunction(f => false);
            value.AddProduction("null").SetReduceFunction(f => null);


            array.AddProduction("[", optionalValueList, "]")
            .SetReduceFunction(f => ((List <object>)f[1]).ToArray());

            optionalValueList.AddProduction(valueList)
            .SetReduceFunction(f => f[0]);
            optionalValueList.AddProduction()
            .SetReduceFunction(f => new List <object>());

            valueList.AddProduction(valueList, ",", value)
            .SetReduceFunction(f =>
            {
                var list = (List <object>)f[0];
                list.Add(f[2]);
                return(list);
            });
            valueList.AddProduction(value)
            .SetReduceFunction(f => new List <object> {
                f[0]
            });

            configurator.LexerSettings.EscapeLiterals = true;
            configurator.LexerSettings.Ignore         = new[] { @"\s+" };
            var parser = configurator.CreateParser();

            var jObject = (JsonObject)parser.Parse("{ \"Property1\":\"va\\\"lue\", \"IntegerProperty\" : 1234 }");
        }
Пример #25
0
        public void TestExpectedInput()
        {
            var configurator = ParserFactory.Configure <int>();

            var word = configurator.CreateTerminal("[a-z]+");

            word.DebugName = "word";
            var illegalWord = configurator.CreateTerminal("[A-Z]+"); // Never legal, used to cause errors

            illegalWord.DebugName = "illegalWord";

            var list = configurator.CreateNonTerminal();

            list.DebugName = "list";
            var element = configurator.CreateNonTerminal();

            element.DebugName = "element";

            element.AddProduction("{", list, "}");
            element.AddProduction(word);

            list.AddProduction(list, ",", element);
            list.AddProduction(element);

            var parser = configurator.CreateParser();

            // This should parse
            parser.Parse("a, b, {c, d, e, f, {g}, h, i}, {j, k}");

            // You shall not parse
            try
            {
                parser.Parse("a, b, {c, d, e, F, {g}, h, i}, {j, k}");
            }
            catch (ParseException e)
            {
                // This will fail on the F
                // The exception should contain that the expected input is word or {
                var expectedTokens = e.ExpectedTokens;
                Assert.AreEqual(2, expectedTokens.Length);
                Assert.IsTrue(expectedTokens.Contains("word"));
                Assert.IsTrue(expectedTokens.Contains("{"));
            }

            // You shall not parse
            try
            {
                parser.Parse("a, b, {c, d, e, f f, {g}, h, i}, {j, k}");
            }
            catch (ParseException e)
            {
                // This will fail on the second f since there is no comma
                // The exception should contain that the expected input is , or }
                var expectedTokens = e.ExpectedTokens;

                // EOF is here, since this is a LALR1 parser, even though it not strictly ballroom to use that token here
                // the error actually appears after a reduce. This is OK
                Assert.AreEqual(3, expectedTokens.Length);
                Assert.IsTrue(expectedTokens.Contains(","));
                Assert.IsTrue(expectedTokens.Contains("}"));
            }
        }
Пример #26
0
        public SceneParser()
        {
            var configurator = ParserFactory.Configure <object>();

            // Non-terminals.

            var sceneFile             = CreateNonTerminal <SceneFile>(configurator);
            var directiveList         = CreateNonTerminal <Directive[]>(configurator);
            var directive             = CreateNonTerminal <Directive>(configurator);
            var standardDirectiveType = CreateNonTerminal <StandardDirectiveType>(configurator);
            var paramSet            = CreateNonTerminal <Param[]>(configurator);
            var param               = CreateNonTerminal <Param>(configurator);
            var paramValueList      = CreateNonTerminal <object[]>(configurator);
            var paramValue          = CreateNonTerminal <object>(configurator);
            var point               = CreateNonTerminal <Point>(configurator);
            var vector              = CreateNonTerminal <Vector>(configurator);
            var matrix              = CreateNonTerminal <Matrix4x4>(configurator);
            var floatOrInt          = CreateNonTerminal <float>(configurator);
            var activeTransformType = CreateNonTerminal <ActiveTransformType>(configurator);

            // Terminals.

            var floatLiteral   = CreateTerminalParse(configurator, @"-?\d*\.\d+", Convert.ToSingle);
            var integerLiteral = CreateTerminalParse(configurator, @"-?\d+", Convert.ToInt32);
            var quotedString   = CreateTerminalParse(configurator, "\"(\\\\.|[^\"])*\"", x => x.Substring(1, x.Length - 2));

            // Productions.

            sceneFile.Add(directiveList).SetReduceToFirst();

            directiveList.Add(directiveList, directive).SetReduce((a, b) => a.Concat(new[] { b }).ToArray());
            directiveList.Add(directive).SetReduce(a => new[] { a });

            directive.Add(standardDirectiveType, quotedString, paramSet).SetReduce(
                (a, b, c) => new StandardDirective
            {
                DirectiveType      = a,
                ImplementationType = b,
                Parameters         = new ParamSet(c)
            });
            directive.Add(standardDirectiveType, quotedString).SetReduce(
                (a, b) => new StandardDirective
            {
                DirectiveType      = a,
                ImplementationType = b,
                Parameters         = new ParamSet()
            });
            directive.Add(CreateTerminal(configurator, "Texture"), quotedString, quotedString, quotedString, paramSet).SetReduce(
                (_, b, c, d, e) => new TextureDirective
            {
                Name         = b,
                TextureType  = c,
                TextureClass = d,
                Parameters   = new ParamSet(e)
            });
            directive.Add(CreateTerminal(configurator, "Texture"), quotedString, quotedString, quotedString).SetReduce(
                (_, b, c, d) => new TextureDirective
            {
                Name         = b,
                TextureType  = c,
                TextureClass = d,
                Parameters   = new ParamSet()
            });
            directive.Add(CreateTerminal(configurator, "Identity")).SetReduce(_ => new IdentityDirective());
            directive.Add(CreateTerminal(configurator, "Translate"), vector).SetReduce(
                (_, b) => new TranslateDirective
            {
                Translation = b
            });
            directive.Add(CreateTerminal(configurator, "Scale"), vector).SetReduce(
                (_, b) => new ScaleDirective
            {
                Scale = b
            });
            directive.Add(CreateTerminal(configurator, "Rotate"), floatOrInt, vector).SetReduce(
                (_, b, c) => new RotateDirective
            {
                Angle = b,
                Axis  = c
            });
            directive.Add(CreateTerminal(configurator, "LookAt"), point, point, vector).SetReduce(
                (_, b, c, d) => new LookAtDirective
            {
                Eye    = b,
                LookAt = c,
                Up     = d
            });
            directive.Add(CreateTerminal(configurator, "CoordinateSystem"), quotedString).SetReduce(
                (_, b) => new CoordinateSystemDirective
            {
                Name = b
            });
            directive.Add(CreateTerminal(configurator, "CoordSysTransform"), quotedString).SetReduce(
                (_, b) => new CoordSysTransformDirective
            {
                Name = b
            });
            directive.Add(CreateTerminal(configurator, "Transform"), matrix).SetReduce(
                (_, b) => new TransformDirective
            {
                Transform = b
            });
            directive.Add(CreateTerminal(configurator, "ConcatTransform"), matrix).SetReduce(
                (_, b) => new ConcatTransformDirective
            {
                Transform = b
            });
            directive.Add(CreateTerminal(configurator, "TransformTimes"), floatOrInt, floatOrInt).SetReduce(
                (_, b, c) => new TransformTimesDirective
            {
                Start = b,
                End   = c
            });
            directive.Add(CreateTerminal(configurator, "ActiveTransform"), activeTransformType).SetReduce(
                (_, b) => new ActiveTransformDirective
            {
                Type = b
            });
            directive.Add(CreateTerminal(configurator, "MakeNamedMaterial"), quotedString, quotedString, paramSet).SetReduce(
                (_, b, c, d) => new MakeNamedMaterialDirective
            {
                MaterialName = b,
                MaterialType = c,
                Parameters   = new ParamSet(d)
            });
            directive.Add(CreateTerminal(configurator, "NamedMaterial"), quotedString).SetReduce(
                (_, b) => new NamedMaterialDirective {
                MaterialName = b
            });
            directive.Add(CreateTerminal(configurator, "ObjectBegin"), quotedString).SetReduce(
                (_, b) => new ObjectBeginDirective {
                Name = b
            });
            directive.Add(CreateTerminal(configurator, "ObjectEnd")).SetReduce(_ => new ObjectEndDirective());
            directive.Add(CreateTerminal(configurator, "ObjectInstance"), quotedString).SetReduce(
                (_, b) => new ObjectInstanceDirective {
                Name = b
            });
            directive.Add(CreateTerminal(configurator, "ReverseOrientation")).SetReduce(_ => new ReverseOrientationDirective());
            directive.Add(CreateTerminal(configurator, "TransformBegin")).SetReduce(_ => new TransformBeginDirective());
            directive.Add(CreateTerminal(configurator, "TransformEnd")).SetReduce(_ => new TransformEndDirective());
            directive.Add(CreateTerminal(configurator, "WorldBegin")).SetReduce(_ => new WorldBeginDirective());
            directive.Add(CreateTerminal(configurator, "WorldEnd")).SetReduce(_ => new WorldEndDirective());
            directive.Add(CreateTerminal(configurator, "AttributeBegin")).SetReduce(_ => new AttributeBeginDirective());
            directive.Add(CreateTerminal(configurator, "AttributeEnd")).SetReduce(_ => new AttributeEndDirective());

            standardDirectiveType.Add(CreateTerminal(configurator, "Accelerator")).SetReduce(_ => StandardDirectiveType.Accelerator);
            standardDirectiveType.Add(CreateTerminal(configurator, "AreaLightSource")).SetReduce(_ => StandardDirectiveType.AreaLightSource);
            standardDirectiveType.Add(CreateTerminal(configurator, "Camera")).SetReduce(_ => StandardDirectiveType.Camera);
            standardDirectiveType.Add(CreateTerminal(configurator, "Film")).SetReduce(_ => StandardDirectiveType.Film);
            standardDirectiveType.Add(CreateTerminal(configurator, "LightSource")).SetReduce(_ => StandardDirectiveType.LightSource);
            standardDirectiveType.Add(CreateTerminal(configurator, "Material")).SetReduce(_ => StandardDirectiveType.Material);
            standardDirectiveType.Add(CreateTerminal(configurator, "PixelFilter")).SetReduce(_ => StandardDirectiveType.PixelFilter);
            standardDirectiveType.Add(CreateTerminal(configurator, "Renderer")).SetReduce(_ => StandardDirectiveType.Renderer);
            standardDirectiveType.Add(CreateTerminal(configurator, "Sampler")).SetReduce(_ => StandardDirectiveType.Sampler);
            standardDirectiveType.Add(CreateTerminal(configurator, "Shape")).SetReduce(_ => StandardDirectiveType.Shape);
            standardDirectiveType.Add(CreateTerminal(configurator, "SurfaceIntegrator")).SetReduce(_ => StandardDirectiveType.SurfaceIntegrator);
            standardDirectiveType.Add(CreateTerminal(configurator, "Volume")).SetReduce(_ => StandardDirectiveType.Volume);
            standardDirectiveType.Add(CreateTerminal(configurator, "VolumeIntegrator")).SetReduce(_ => StandardDirectiveType.VolumeIntegrator);

            paramSet.Add(paramSet, param).SetReduce((a, b) => a.Concat(new[] { b }).ToArray());
            paramSet.Add(param).SetReduce(a => new[] { a });

            param.Add(quotedString, CreateTerminal(configurator, @"\["), paramValueList, CreateTerminal(configurator, @"\]"))
            .SetReduce((a, b, c, d) => GetParamList(a, c));
            param.Add(quotedString, paramValue).SetReduce(GetParam);

            paramValueList.Add(paramValueList, paramValue).SetReduce((a, b) => a.Concat(new[] { b }).ToArray());
            paramValueList.Add(paramValue).SetReduce(a => new [] { a });

            paramValue.Add(floatOrInt).SetReduce(a => a);
            paramValue.Add(quotedString).SetReduce(a => a);

            point.Add(floatOrInt, floatOrInt, floatOrInt).SetReduce((a, b, c) => new Point(a, b, c));
            vector.Add(floatOrInt, floatOrInt, floatOrInt).SetReduce((a, b, c) => new Vector(a, b, c));
            matrix.Add(floatOrInt, floatOrInt, floatOrInt, floatOrInt, floatOrInt, floatOrInt, floatOrInt, floatOrInt, floatOrInt, floatOrInt, floatOrInt, floatOrInt, floatOrInt, floatOrInt, floatOrInt, floatOrInt)
            .SetReduce((m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33) => new Matrix4x4(m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33));

            floatOrInt.Add(floatLiteral).SetReduceToFirst();
            floatOrInt.Add(integerLiteral).SetReduce(a => (float)a);

            activeTransformType.Add(CreateTerminal(configurator, "StartTime")).SetReduce(x => ActiveTransformType.Start);
            activeTransformType.Add(CreateTerminal(configurator, "EndTime")).SetReduce(x => ActiveTransformType.End);
            activeTransformType.Add(CreateTerminal(configurator, "All")).SetReduce(x => ActiveTransformType.All);

            // Ignore whitespace and comments
            configurator.LexerSettings.Ignore = new[] { @"\s+", @"#[^\n]*\n" };

            _parser = configurator.CreateParser();
        }