public void CreateWithNoStartRules()
        {
            var terminals = new TerminalSymbol[]
            {
                new TerminalSymbol("a"),
                new TerminalSymbol("b"),
            };

            var grammaticals = new GrammaticalSymbol[]
            {
                new GrammaticalSymbol("S"),
                new GrammaticalSymbol("A"),
            };

            var rules = new Rule[]
            {
                new Rule(grammaticals[1], new Symbol[]{ terminals[0] }),
                new Rule(grammaticals[1], new Symbol[]{ terminals[1] }),
            };

            var gr = new RestrictedStartSymbolGrammar(new Grammar(terminals, grammaticals, rules, 0));

            Assert.Equal(2, gr.Grammaticals.Count);
            Assert.Equal(3, gr.Rules.Count);
            Assert.Equal(gr.StartSymbol, gr.StartRule.LeftHandSide);
            Assert.True(gr.StartRule.IsEpsilonRule);
        }
        public void CreateWithMultipleStartRules()
        {
            var terminals = new TerminalSymbol[]
            {
                new TerminalSymbol("a"),
                new TerminalSymbol("b"),
            };

            var grammaticals = new GrammaticalSymbol[]
            {
                new GrammaticalSymbol("S"),
            };

            var rules = new Rule[]
            {
                new Rule(grammaticals[0], new Symbol[]{ terminals[0] }),
                new Rule(grammaticals[0], new Symbol[]{ terminals[1] }),
            };

            var gr = new RestrictedStartSymbolGrammar(new Grammar(terminals, grammaticals, rules, 0));

            Assert.Equal(2, gr.Grammaticals.Count);
            Assert.Equal(3, gr.Rules.Count);
            Assert.Equal(1, gr.Rules.Count(r => r.LeftHandSide == gr.StartSymbol));
            Assert.True(gr.Rules.FirstOrDefault(r => r.RightHandSide.IndexOf(gr.StartSymbol) != -1) == null);
        }
Beispiel #3
0
 static Grammar()
 {
     var start_sym = new GrammaticalSymbol("S");
     EmptyGrammar = new Grammar(
         new TerminalSymbol[0],
         new GrammaticalSymbol[] { start_sym },
         new Rule[] { new Rule(start_sym, new Symbol[0]) },
         0);
 }
Beispiel #4
0
        static Grammar1()
        {
            var terminals = new TerminalSymbol[]
                {
                    new TerminalSymbol("a"),
                };

            var grammaticals = new GrammaticalSymbol[]
                {
                    new GrammaticalSymbol("S"),
                };

            var rules = new Rule[]
                {
                    // S->aS
                    new Rule(
                        grammaticals[0],
                        new Symbol[]
                        {
                            terminals[0],
                            grammaticals[0],
                        }),

                    // S->
                    new Rule(
                        grammaticals[0],
                        new Symbol[0]),
                };

            BaseGrammar = new Grammar(terminals, grammaticals, rules, 0);
            RestrictedGrammar = new RestrictedStartSymbolGrammar(BaseGrammar);
            ExtendedGrammar = new ExtendedGrammar(RestrictedGrammar);

            EpsilonGrammaticals = new HashSet<GrammaticalSymbol>(RestrictedGrammar.Grammaticals);

            FirstSets = new Dictionary<GrammaticalSymbol, ISet<TerminalSymbol>>();
            // S': a,Eps
            FirstSets[ExtendedGrammar.StartSymbol] = new HashSet<TerminalSymbol>(BaseGrammar.Terminals);
            FirstSets[ExtendedGrammar.StartSymbol].Add(EpsilonSymbol.Instance);
            // S: a,Eps
            FirstSets[BaseGrammar.StartSymbol] = new HashSet<TerminalSymbol>(BaseGrammar.Terminals);
            FirstSets[BaseGrammar.StartSymbol].Add(EpsilonSymbol.Instance);

            FollowSets = new Dictionary<GrammaticalSymbol, ISet<TerminalSymbol>>();
            // S':
            FollowSets[ExtendedGrammar.Grammaticals[0]] = new HashSet<TerminalSymbol>();
            // S: #
            FollowSets[ExtendedGrammar.Grammaticals[1]] = new HashSet<TerminalSymbol>();
            FollowSets[ExtendedGrammar.Grammaticals[1]].Add(ExtendedGrammar.EndOfSourceSymbol);
        }
Beispiel #5
0
        public void CreateWithForeignGrammaticalInRuleRhs()
        {
            var foreign_symbol = new GrammaticalSymbol("TestGrammatical");
            var bad_rule = new Rule(
                Fixtures.EmptyGrammar.BaseGrammar.Grammaticals[0],
                new Symbol[] { foreign_symbol });

            var ex = Assert.Throws<ForeignSymbolInRuleException>(
                () => new Grammar(
                    Fixtures.EmptyGrammar.BaseGrammar.Terminals,
                    Fixtures.EmptyGrammar.BaseGrammar.Grammaticals,
                    new Rule[]
                    {
                        Fixtures.EmptyGrammar.BaseGrammar.Rules[0],
                        bad_rule,
                    },
                    0)
            );

            Assert.Equal(bad_rule, ex.Rule);
            Assert.Equal(foreign_symbol, ex.Symbol);
        }
Beispiel #6
0
        /// <summary>
        /// Creates the rule instances with the given paramaters.
        /// </summary>
        /// <param name="left_hand_side">The <see cref="GrammaticalSymbol"/> on the left hand side.</param>
        /// <param name="right_hand_side">An enumeration of <see cref="Symbol"/>s of the right hand side.</param>
        /// <exception cref="ArgumentNullException"> if either of the parameters is <c>null</c>.</exception>
        /// <exception cref="ArgumentException"> if the <paramref name="right_hand_side"/> 
        ///     contains an <see cref="EpsilonSymbol"/>.</exception>
        /// <exception cref="ArgumentException"> if the <paramref name="right_hand_side"/> 
        ///     contains an <see cref="EndOfSourceSymbol"/> other than at the end.</exception>
        public Rule( GrammaticalSymbol left_hand_side, IEnumerable<Symbol> right_hand_side )
        {
            if( left_hand_side == null )
                throw new ArgumentNullException("left_hand_side");
            if( right_hand_side == null )
                throw new ArgumentNullException("right_hand_side");

            var rhs = new List<Symbol>(right_hand_side);
            if( rhs.Count > 0 )
            {
                if( rhs.IndexOf(EpsilonSymbol.Instance) != -1 )
                    throw new ArgumentException("RightHandSide must not contain Epsilon.");

                // Checking for EndOfSource symbols other then at the end.
                int index = rhs.FindIndex(s => s is EndOfSourceSymbol);
                if( index != -1 && index < rhs.Count - 1 )
                    throw new ArgumentException("RightHandSide must not contain EndOfSource symbol other than at the end.");
            }

            this.lhs = left_hand_side;
            this.rhs = rhs.AsReadOnly();
        }
Beispiel #7
0
        static Grammar3()
        {
            var terminals = new TerminalSymbol[]
                {
                    new TerminalSymbol("a"),
                    new TerminalSymbol("b"),
                };

            var grammaticals = new GrammaticalSymbol[]
                {
                    new GrammaticalSymbol("S"),
                    new GrammaticalSymbol("A"),
                    new GrammaticalSymbol("B"),
                };

            var rules = new Rule[]
                {
                    // S->AB
                    new Rule(
                        grammaticals[0],
                        new Symbol[]
                        {
                            grammaticals[1],
                            grammaticals[2],
                        }),

                    // S->aSbS
                    new Rule(
                        grammaticals[1],
                        new Symbol[]
                        {
                            terminals[0],
                            grammaticals[0],
                            terminals[1],
                            grammaticals[0],
                        }),

                    // A->
                    new Rule(
                        grammaticals[1],
                        new Symbol[0]),

                    // B->
                    new Rule(
                        grammaticals[2],
                        new Symbol[0]),
                };

            BaseGrammar = new Grammar(terminals, grammaticals, rules, 0);
            RestrictedGrammar = new RestrictedStartSymbolGrammar(BaseGrammar);
            ExtendedGrammar = new ExtendedGrammar(RestrictedGrammar);

            EpsilonGrammaticals = new HashSet<GrammaticalSymbol>(ExtendedGrammar.Grammaticals);

            FollowSets = new Dictionary<GrammaticalSymbol, ISet<TerminalSymbol>>();
            // S': -
            FollowSets[ExtendedGrammar.StartSymbol] = new HashSet<TerminalSymbol>();
            // S: b,#
            FollowSets[ExtendedGrammar.Grammaticals[1]] = new HashSet<TerminalSymbol>(
                new TerminalSymbol[]{
                    ExtendedGrammar.Terminals[1],
                    ExtendedGrammar.EndOfSourceSymbol,
                });
            // A: b,#
            FollowSets[ExtendedGrammar.Grammaticals[2]] = FollowSets[ExtendedGrammar.Grammaticals[1]];
            // B: b,#
            FollowSets[ExtendedGrammar.Grammaticals[3]] = FollowSets[ExtendedGrammar.Grammaticals[1]];
        }
Beispiel #8
0
        static Grammar2()
        {
            var terminals = new TerminalSymbol[]
                {
                    new TerminalSymbol("+"),
                    new TerminalSymbol("*"),
                    new TerminalSymbol("("),
                    new TerminalSymbol(")"),
                    new TerminalSymbol("i"),
                };

            var grammaticals = new GrammaticalSymbol[]
                {
                    new GrammaticalSymbol("S"),
                    new GrammaticalSymbol("E"),
                    new GrammaticalSymbol("E'"),
                    new GrammaticalSymbol("T"),
                    new GrammaticalSymbol("T'"),
                    new GrammaticalSymbol("F"),
                };

            var rules = new Rule[]
                {
                    // S->E
                    new Rule(
                        grammaticals[0],
                        new Symbol[]
                        {
                            grammaticals[1],
                        }),

                    // E->TE'
                    new Rule(
                        grammaticals[1],
                        new Symbol[]
                        {
                            grammaticals[3],
                            grammaticals[2],
                        }),

                    // E'->+TE'
                    new Rule(
                        grammaticals[2],
                        new Symbol[]
                        {
                            terminals[0],
                            grammaticals[3],
                            grammaticals[2],
                        }),

                    // E'->
                    new Rule(
                        grammaticals[2],
                        new Symbol[] { }),

                    // T->FT'
                    new Rule(
                        grammaticals[3],
                        new Symbol[]
                        {
                            grammaticals[5],
                            grammaticals[4],
                        }),

                    // T'->*FT'
                    new Rule(
                        grammaticals[4],
                        new Symbol[]
                        {
                            terminals[1],
                            grammaticals[5],
                            grammaticals[4],
                        }),

                    // T'->
                    new Rule(
                        grammaticals[4],
                        new Symbol[] { }),

                    // F->(E)
                    new Rule(
                        grammaticals[5],
                        new Symbol[]
                        {
                            terminals[2],
                            grammaticals[1],
                            terminals[3],
                        }),

                    // F->i
                    new Rule(
                        grammaticals[5],
                        new Symbol[]
                        {
                            terminals[4],
                        }),
                };

            BaseGrammar = new Grammar(terminals, grammaticals, rules, 0);
            RestrictedGrammar = new RestrictedStartSymbolGrammar(BaseGrammar);
            ExtendedGrammar = new ExtendedGrammar(RestrictedGrammar);

            EpsilonGrammaticals = new HashSet<GrammaticalSymbol>(
                new GrammaticalSymbol[] { grammaticals[2], grammaticals[4] });

            FirstSets = new Dictionary<GrammaticalSymbol, ISet<TerminalSymbol>>();
            // S: (,i
            FirstSets[BaseGrammar.Grammaticals[0]] = new HashSet<TerminalSymbol>(new TerminalSymbol[]
                {
                    BaseGrammar.Terminals[2],
                    BaseGrammar.Terminals[4],
                });

            // E: (,i
            FirstSets[BaseGrammar.Grammaticals[1]] = new HashSet<TerminalSymbol>(new TerminalSymbol[]
                {
                    BaseGrammar.Terminals[2],
                    BaseGrammar.Terminals[4],
                });

            // E': +,Eps
            FirstSets[BaseGrammar.Grammaticals[2]] = new HashSet<TerminalSymbol>(new TerminalSymbol[]
                {
                    BaseGrammar.Terminals[0],
                    EpsilonSymbol.Instance,
                });

            // T: (,i
            FirstSets[BaseGrammar.Grammaticals[3]] = new HashSet<TerminalSymbol>(new TerminalSymbol[]
                {
                    BaseGrammar.Terminals[2],
                    BaseGrammar.Terminals[4],
                });

            // T': *,Eps
            FirstSets[BaseGrammar.Grammaticals[4]] = new HashSet<TerminalSymbol>(new TerminalSymbol[]
                {
                    BaseGrammar.Terminals[1],
                    EpsilonSymbol.Instance,
                });

            // F: (,i
            FirstSets[BaseGrammar.Grammaticals[5]] = new HashSet<TerminalSymbol>(new TerminalSymbol[]
                {
                    BaseGrammar.Terminals[2],
                    BaseGrammar.Terminals[4],
                });

            FollowSets = new Dictionary<GrammaticalSymbol, ISet<TerminalSymbol>>();

            // S:
            FollowSets[ExtendedGrammar.Grammaticals[0]] = new HashSet<TerminalSymbol>();

            // E: ),EoS
            FollowSets[ExtendedGrammar.Grammaticals[1]] = new HashSet<TerminalSymbol>(new TerminalSymbol[]
                {
                    ExtendedGrammar.Terminals[3],
                    ExtendedGrammar.Terminals[5],
                });

            // E': ),EoS
            FollowSets[ExtendedGrammar.Grammaticals[2]] = new HashSet<TerminalSymbol>(new TerminalSymbol[]
                {
                    ExtendedGrammar.Terminals[3],
                    ExtendedGrammar.Terminals[5],
                });

            // T: +,),EoS
            FollowSets[ExtendedGrammar.Grammaticals[3]] = new HashSet<TerminalSymbol>(new TerminalSymbol[]
                {
                    ExtendedGrammar.Terminals[0],
                    ExtendedGrammar.Terminals[3],
                    ExtendedGrammar.Terminals[5],
                });

            // T': +,),EoS
            FollowSets[ExtendedGrammar.Grammaticals[4]] = new HashSet<TerminalSymbol>(new TerminalSymbol[]
                {
                    ExtendedGrammar.Terminals[0],
                    ExtendedGrammar.Terminals[3],
                    ExtendedGrammar.Terminals[5],
                });

            // F: +,*,),EoS
            FollowSets[ExtendedGrammar.Grammaticals[5]] = new HashSet<TerminalSymbol>(new TerminalSymbol[]
                {
                    ExtendedGrammar.Terminals[0],
                    ExtendedGrammar.Terminals[1],
                    ExtendedGrammar.Terminals[3],
                    ExtendedGrammar.Terminals[5],
                });

            //TODO: Use real fixture!!
            LR0CanonicalSets = LR0CanonicalSets.Build(RestrictedGrammar);

            //TODO: Use real fixtures!!
            SLR1ParserTable = SLR1ParserTableBuilder.Build(ExtendedGrammar, LR0CanonicalSets, FollowSets);
        }
Beispiel #9
0
 /// <summary>
 /// Returns the index og the given <paramref name="symbol"/>.
 /// </summary>
 /// <param name="symbol"></param>
 /// <returns>The index of the given grammatical, or <c>-1</c> if the symbol is not part of this grammar.</returns>
 public int IndexOf( GrammaticalSymbol symbol )
 {
     return this.Grammaticals.IndexOf(symbol);
 }
Beispiel #10
0
 /// <summary>
 /// Returns an index unique among symbols from the same grammar.
 /// (terminals first, grammaticals second)
 /// </summary>
 /// <param name="symbol"></param>
 /// <returns>The index of the given symbol, <c>-1</c> if symbol not part of this grammar.</returns>
 public int GlobalIndexOf( GrammaticalSymbol symbol )
 {
     return this.Terminals.Count + this.Grammaticals.IndexOf((GrammaticalSymbol)symbol);
 }
        private void Initialize()
        {
            var old_start_sym = this.base_gr.StartSymbol;
            var rules = new List<Rule>(this.base_gr.Rules.Count + 1);
            rules.AddRange(this.base_gr.Rules);
            var start_rules = rules.FindAll(r => r.LeftHandSide == old_start_sym);

            if( rules.Find(r => r.RightHandSide.Contains(old_start_sym)) != null ||
                start_rules.Count > 1 )
            {
                // New start symbol, and new start rule
                string new_start_sym_name = "S'";
                while( this.base_gr.Grammaticals.FirstOrDefault(gr => gr.Name == new_start_sym_name) != null )
                    new_start_sym_name += "'";

                var new_start_sym = new GrammaticalSymbol(new_start_sym_name);
                var grammaticals = new List<GrammaticalSymbol>(this.base_gr.Grammaticals.Count + 1);
                grammaticals.Add(new_start_sym);
                grammaticals.AddRange(this.base_gr.Grammaticals);
                this.grammaticals = grammaticals.AsReadOnly();

                var new_start_rule = new Rule(new_start_sym, new Symbol[] { old_start_sym });
                rules.Insert(0, new_start_rule);
                this.rules = rules.AsReadOnly();
            }
            else
            {
                if( this.base_gr.IndexOf(old_start_sym) != 0 )
                {
                    int old_ind = this.base_gr.IndexOf(old_start_sym);
                    var grammaticals = new List<GrammaticalSymbol>(this.base_gr.Grammaticals);
                    grammaticals.RemoveAt(old_ind);
                    grammaticals.Insert(0, old_start_sym);
                    this.grammaticals = grammaticals.AsReadOnly();
                }
                else
                {
                    this.grammaticals = this.base_gr.Grammaticals;
                }

                if( start_rules.Count == 0 )
                {
                    // New epsilon start rule.
                    var new_start_rule = new Rule(old_start_sym, new Symbol[0]);
                    rules.Insert(0, new_start_rule);
                    this.rules = rules.AsReadOnly();
                }
                else if( rules[0] != start_rules[0] )
                {
                    // Reorder to be the first rule.
                    var old_start_rule = start_rules[0];
                    rules.Remove(old_start_rule);
                    rules.Insert(0, old_start_rule);
                    this.rules = rules.AsReadOnly();
                }
                else
                {
                    // Rules are fine.
                    this.rules = this.base_gr.Rules;
                }
            }
        }
        public void CreateWithStartRuleNotTheFirst()
        {
            var terminals = new TerminalSymbol[]
            {
                new TerminalSymbol("a"),
                new TerminalSymbol("b"),
            };

            var grammaticals = new GrammaticalSymbol[]
            {
                new GrammaticalSymbol("S"),
                new GrammaticalSymbol("A"),
            };

            var rules = new Rule[]
            {
                new Rule(grammaticals[1], new Symbol[]{ terminals[0] }),
                new Rule(grammaticals[0], new Symbol[]{ terminals[1] }),
            };

            var gr = new RestrictedStartSymbolGrammar(new Grammar(terminals, grammaticals, rules, 0));

            Assert.Equal(2, gr.Grammaticals.Count);
            Assert.Equal(2, gr.Rules.Count);
            Assert.Equal(rules[1], gr.StartRule);
        }