Пример #1
0
        public GrammarAlphabet(GrammarSymbol[] symbols)
        {
            bool hasDuplicates = symbols.Distinct().Count() < symbols.Length;
            if (hasDuplicates)
                throw new ArgumentException("Alphabet cannot contain duplicates.");

            this.symbols = (GrammarSymbol[])symbols.Clone();
        }
Пример #2
0
        public bool HasSentence(IEnumerable <string> sentence)
        {
            // TODO: force normal form somehow
            //       check alphabet

            if (!sentence.Any())
            {
                return(rules.Any((p) => p.Original == starting && p.DirectDerivative == Sentence.Empty));
            }

            var input = sentence.ToArray();
            int n     = input.Length;

            var table = new List <GrammarSymbol> [n][];

            for (int i = 0; i < n; i++)
            {
                table[i] = new List <GrammarSymbol> [i + 1];
                for (int j = 0; j < i; j++)
                {
                    table[i][j] = new List <GrammarSymbol>();
                }

                var query = from rule in rules
                            let derivative = rule.DirectDerivative
                                             where derivative.Length == 1 &&
                                             derivative.First().Matches(input[i])
                                             select rule.Original;
                table[i][i] = query.ToList();
            }

            for (int k = 1; k < n; k++)
            {
                for (int i = 0; i < n - k; i++)
                {
                    for (int j = 0; j < k; j++)
                    {
                        foreach (Production rule in rules)
                        {
                            var derivative = rule.DirectDerivative;
                            if (derivative.Length != 2)
                            {
                                continue;
                            }

                            GrammarSymbol first  = derivative.First(),
                                          second = derivative.ElementAt(1);
                            if (table[i + j][i].Contains(first) && table[i + k][i + j + 1].Contains(second))
                            {
                                table[i + k][i].Add(rule.Original);
                            }
                        }
                    }
                }
            }

            return(table[n - 1][0].Contains(starting));
        }
Пример #3
0
        public ContextFreeGrammar(string[] nonterminals, string[] terminals,
            ProductionInfo[] rules, string starting)
        {
            if (HasDuplicates(nonterminals))
                throw new ArgumentException("Nonterminal symbols cannot contain duplicates.");
            if (HasDuplicates(terminals))
                throw new ArgumentException("Terminal symbols cannot contain duplicates.");
            if (HasDuplicates(rules))
                throw new ArgumentException("Rules cannot contain duplicates.");

            bool overlap = terminals.Intersect(nonterminals).Any();
            if (overlap)
                throw new ArgumentException("Terminal symbols and nonterminal symbols are not disjoint.");

            var symbolByString = new Dictionary<string, GrammarSymbol>(nonterminals.Length + terminals.Length);

            this.nonterminals = new GrammarSymbol[nonterminals.Length];
            for (int i = 0; i < nonterminals.Length; i++)
            {
                this.nonterminals[i] = new GrammarSymbol(nonterminals[i], false);
                symbolByString.Add(nonterminals[i], this.nonterminals[i]);
            }

            this.terminals = new GrammarSymbol[terminals.Length];
            for (int i = 0; i < terminals.Length; i++)
            {
                this.terminals[i] = new GrammarSymbol(terminals[i], true);
                symbolByString.Add(terminals[i], this.terminals[i]);
            }

            this.alphabet = (this.nonterminals).Concat(this.terminals).ToArray();

            int startingIndex = Array.IndexOf(nonterminals, starting);
            if (startingIndex < 0)
                throw new ArgumentException("Start symbol must be a nonterminal symbol.");

            this.starting = this.nonterminals[startingIndex];

            var ruleList = new List<Production>(rules.Length);
            foreach (var rule in rules)
            {
                if (!IsValid(rule))
                    throw new ArgumentException("Production rule is invalid.");

                GrammarSymbol original = symbolByString[rule.Original];

                var sentenceSymbols = new List<GrammarSymbol>();
                foreach (string s in rule.DirectDerivative)
                    sentenceSymbols.Add(symbolByString[s]);
                Sentence sentence = new Sentence(sentenceSymbols.ToArray());

                ruleList.Add(new Production(original, sentence));
            }
            this.rules = ruleList.ToArray();
        }
Пример #4
0
        private ContextFreeGrammar(GrammarSymbol[] nonterminals, GrammarSymbol[] terminals,
            Production[] rules, GrammarSymbol starting)
        {
            // doesnt check for exception, careful

            this.nonterminals = nonterminals;
            this.terminals = terminals;
            this.alphabet = nonterminals.Concat(terminals).ToArray();
            this.rules = rules;
            this.starting = starting;
        }
Пример #5
0
        private ContextFreeGrammar(GrammarSymbol[] nonterminals, GrammarSymbol[] terminals,
                                   Production[] rules, GrammarSymbol starting)
        {
            // doesnt check for exception, careful

            this.nonterminals = nonterminals;
            this.terminals    = terminals;
            this.alphabet     = nonterminals.Concat(terminals).ToArray();
            this.rules        = rules;
            this.starting     = starting;
        }
Пример #6
0
        private bool AlphabetContains(GrammarSymbol[] array, string symbol)
        {
            foreach (GrammarSymbol s in array)
                if (s.Matches(symbol))
                    return true;

            return false;
        }
Пример #7
0
        public ContextFreeGrammar GetChomskyNormalForm()
        {
            var newNonterminals = new List<GrammarSymbol>(nonterminals);
            var newRules = new List<Production>(rules);
            var toBeAddedRules = new List<Production>();

            var newStarting = new GrammarSymbol("S0", false);
            newNonterminals.Add(newStarting);
            newRules.Add(new Production(newStarting, new Sentence(new[] { starting })));

            for (int i = 0; i < newRules.Count; i++)
            {
                var rule = newRules[i];

                var sentence = rule.DirectDerivative.ToArray();
                if (rule.DirectDerivative.HasNonsolitaryTerminal)
                {
                    var encountered = new List<GrammarSymbol>();
                    for (int j = 0; j < sentence.Length; j++)
                    {
                        var symbol = sentence[j];

                        if (symbol.IsTerminal)
                        {
                            string label = "N" + symbol.ToString();
                            GrammarSymbol newSymbol = encountered.FirstOrDefault((s) => s.Matches(label));
                            if (newSymbol == null)
                            {
                                newSymbol = new GrammarSymbol(label, false);
                                encountered.Add(newSymbol);
                                newNonterminals.Add(newSymbol);
                                toBeAddedRules.Add(new Production(newSymbol, new Sentence(new[] { symbol })));
                            }

                            sentence[j] = newSymbol;
                        }
                    }
                }

                newRules[i] = new Production(rule.Original, new Sentence(sentence));
            }
            newRules.AddRange(toBeAddedRules);
            toBeAddedRules = new List<Production>();

            for (int i = 0; i < newRules.Count; i++)
            {
                var rule = newRules[i];

                var sentence = rule.DirectDerivative;
                var newSentence = sentence.ToArray();
                if (sentence.HasMoreThanTwoNonterminals)
                {
                    GrammarSymbol nextSymbol = rule.Original;
                    int n = newSentence.Length;
                    for (int j = 0; j < n - 2; j++)
                    {
                        var currentSymbol = nextSymbol;
                        nextSymbol = new GrammarSymbol(rule.Original.ToString() + (i + 1).ToString(), false);
                        newNonterminals.Add(nextSymbol);
                        toBeAddedRules.Add(new Production(currentSymbol, new Sentence(new[] { newSentence[j], nextSymbol })));
                    }
                    newRules[i] = new Production(nextSymbol, new Sentence(new[] { newSentence[n - 2], newSentence[n - 1] }));
                    // order is somewhat scrambled
                }
            }
            newRules.AddRange(toBeAddedRules);
            toBeAddedRules = new List<Production>();

            bool noEpsilonLeft = false;
            while (!noEpsilonLeft)
            {
                noEpsilonLeft = true;
                foreach (var rule in newRules)
                    if (rule.DirectDerivative.IsEmpty && rule.Original != newStarting)
                    {

                        GrammarSymbol nullable = rule.Original;
                        bool isLastRule = newRules.Count((r) => r.Original == nullable) == 0;
                        if (!isLastRule)
                            for (int i = 0; i < newRules.Count(); i++)
                            {
                                var oldSymbol = newRules[i].Original;
                                var sentence = newRules[i].DirectDerivative.ToArray();
                                int n = sentence.Length;
                                Debug.Assert(n < 3);

                                if (n == 1 && sentence[0] == nullable)
                                    AddIfNotExist(ref newRules, new Production(oldSymbol, Sentence.Empty));
                                else if (n == 2)
                                {
                                    if (sentence[0] == sentence[1] && sentence[0] == nullable)
                                    {
                                        AddIfNotExist(ref newRules, new Production(oldSymbol, Sentence.Empty));
                                        AddIfNotExist(ref newRules, new Production(oldSymbol, new Sentence(new[] { sentence[0] })));
                                    }
                                    else if (sentence[0] == nullable)
                                        AddIfNotExist(ref newRules, new Production(oldSymbol, new Sentence(new[] { sentence[1] })));
                                    else if (sentence[1] == nullable)
                                        AddIfNotExist(ref newRules, new Production(oldSymbol, new Sentence(new[] { sentence[0] })));
                                }
                            }
                        else
                        {
                            for (int i = 0; i < newRules.Count(); i++)
                            {
                                var oldSymbol = newRules[i].Original;
                                var sentence = newRules[i].DirectDerivative.ToArray();
                                int n = sentence.Length;
                                Debug.Assert(n < 3);

                                if (n == 1 && sentence[0] == nullable)
                                    AddIfNotExist(ref newRules, new Production(oldSymbol, Sentence.Empty));
                                else if (n == 2)
                                {
                                    if (sentence[0] == sentence[1] && sentence[0] == nullable)
                                        AddIfNotExist(ref newRules, new Production(oldSymbol, Sentence.Empty));
                                    else if (sentence[0] == nullable)
                                        AddIfNotExist(ref newRules, new Production(oldSymbol, new Sentence(new[] { sentence[1] })));
                                    else
                                        AddIfNotExist(ref newRules, new Production(oldSymbol, new Sentence(new[] { sentence[0] })));
                                }
                            }
                            newNonterminals.Remove(nullable);
                        }
                        newRules.Remove(rule);
                        toBeAddedRules = new List<Production>();
                        noEpsilonLeft = false;
                        break;
                    }
            }

            bool noUnitRuleLeft = false;
            while (!noUnitRuleLeft)
            {
                noUnitRuleLeft = true;
                foreach (var rule in newRules)
                {
                    bool isUnitRule = rule.DirectDerivative.Length == 1 && !rule.DirectDerivative.First().IsTerminal;
                    if (isUnitRule)
                    {
                        newRules.Remove(rule);

                        var toBeReplaced = rule.DirectDerivative.First();
                        var replacement = rule.Original;
                        for (int i = 0; i < newRules.Count(); i++)
                        {
                            var oldSymbol = newRules[i].Original;
                            var sentence = newRules[i].DirectDerivative.ToArray();

                            if (oldSymbol == toBeReplaced)
                                toBeAddedRules.Add(new Production(replacement, new Sentence(sentence)));
                        }
                        newNonterminals.Remove(toBeReplaced);
                        newRules.AddRange(toBeAddedRules);
                        toBeAddedRules = new List<Production>();

                        noUnitRuleLeft = false;
                        break;
                    }
                }
            }

            return new ContextFreeGrammar(newNonterminals.ToArray(), this.terminals, newRules.ToArray(), newStarting);
        }
Пример #8
0
 public Production(GrammarSymbol original, Sentence directDerivative)
 {
     this.original         = original;
     this.directDerivative = directDerivative;
 }
Пример #9
0
 public Production(GrammarSymbol original, Sentence directDerivative)
 {
     this.original = original;
     this.directDerivative = directDerivative;
 }
Пример #10
0
        public ContextFreeGrammar(string[] nonterminals, string[] terminals,
                                  ProductionInfo[] rules, string starting)
        {
            if (HasDuplicates(nonterminals))
            {
                throw new ArgumentException("Nonterminal symbols cannot contain duplicates.");
            }
            if (HasDuplicates(terminals))
            {
                throw new ArgumentException("Terminal symbols cannot contain duplicates.");
            }
            if (HasDuplicates(rules))
            {
                throw new ArgumentException("Rules cannot contain duplicates.");
            }


            bool overlap = terminals.Intersect(nonterminals).Any();

            if (overlap)
            {
                throw new ArgumentException("Terminal symbols and nonterminal symbols are not disjoint.");
            }


            var symbolByString = new Dictionary <string, GrammarSymbol>(nonterminals.Length + terminals.Length);

            this.nonterminals = new GrammarSymbol[nonterminals.Length];
            for (int i = 0; i < nonterminals.Length; i++)
            {
                this.nonterminals[i] = new GrammarSymbol(nonterminals[i], false);
                symbolByString.Add(nonterminals[i], this.nonterminals[i]);
            }

            this.terminals = new GrammarSymbol[terminals.Length];
            for (int i = 0; i < terminals.Length; i++)
            {
                this.terminals[i] = new GrammarSymbol(terminals[i], true);
                symbolByString.Add(terminals[i], this.terminals[i]);
            }

            this.alphabet = (this.nonterminals).Concat(this.terminals).ToArray();


            int startingIndex = Array.IndexOf(nonterminals, starting);

            if (startingIndex < 0)
            {
                throw new ArgumentException("Start symbol must be a nonterminal symbol.");
            }

            this.starting = this.nonterminals[startingIndex];


            var ruleList = new List <Production>(rules.Length);

            foreach (var rule in rules)
            {
                if (!IsValid(rule))
                {
                    throw new ArgumentException("Production rule is invalid.");
                }

                GrammarSymbol original = symbolByString[rule.Original];

                var sentenceSymbols = new List <GrammarSymbol>();
                foreach (string s in rule.DirectDerivative)
                {
                    sentenceSymbols.Add(symbolByString[s]);
                }
                Sentence sentence = new Sentence(sentenceSymbols.ToArray());

                ruleList.Add(new Production(original, sentence));
            }
            this.rules = ruleList.ToArray();
        }
Пример #11
0
        public ContextFreeGrammar GetChomskyNormalForm()
        {
            var newNonterminals = new List <GrammarSymbol>(nonterminals);
            var newRules        = new List <Production>(rules);
            var toBeAddedRules  = new List <Production>();


            var newStarting = new GrammarSymbol("S0", false);

            newNonterminals.Add(newStarting);
            newRules.Add(new Production(newStarting, new Sentence(new[] { starting })));

            for (int i = 0; i < newRules.Count; i++)
            {
                var rule = newRules[i];

                var sentence = rule.DirectDerivative.ToArray();
                if (rule.DirectDerivative.HasNonsolitaryTerminal)
                {
                    var encountered = new List <GrammarSymbol>();
                    for (int j = 0; j < sentence.Length; j++)
                    {
                        var symbol = sentence[j];

                        if (symbol.IsTerminal)
                        {
                            string        label     = "N" + symbol.ToString();
                            GrammarSymbol newSymbol = encountered.FirstOrDefault((s) => s.Matches(label));
                            if (newSymbol == null)
                            {
                                newSymbol = new GrammarSymbol(label, false);
                                encountered.Add(newSymbol);
                                newNonterminals.Add(newSymbol);
                                toBeAddedRules.Add(new Production(newSymbol, new Sentence(new[] { symbol })));
                            }

                            sentence[j] = newSymbol;
                        }
                    }
                }

                newRules[i] = new Production(rule.Original, new Sentence(sentence));
            }
            newRules.AddRange(toBeAddedRules);
            toBeAddedRules = new List <Production>();


            for (int i = 0; i < newRules.Count; i++)
            {
                var rule = newRules[i];

                var sentence    = rule.DirectDerivative;
                var newSentence = sentence.ToArray();
                if (sentence.HasMoreThanTwoNonterminals)
                {
                    GrammarSymbol nextSymbol = rule.Original;
                    int           n          = newSentence.Length;
                    for (int j = 0; j < n - 2; j++)
                    {
                        var currentSymbol = nextSymbol;
                        nextSymbol = new GrammarSymbol(rule.Original.ToString() + (i + 1).ToString(), false);
                        newNonterminals.Add(nextSymbol);
                        toBeAddedRules.Add(new Production(currentSymbol, new Sentence(new[] { newSentence[j], nextSymbol })));
                    }
                    newRules[i] = new Production(nextSymbol, new Sentence(new[] { newSentence[n - 2], newSentence[n - 1] }));
                    // order is somewhat scrambled
                }
            }
            newRules.AddRange(toBeAddedRules);
            toBeAddedRules = new List <Production>();


            bool noEpsilonLeft = false;

            while (!noEpsilonLeft)
            {
                noEpsilonLeft = true;
                foreach (var rule in newRules)
                {
                    if (rule.DirectDerivative.IsEmpty && rule.Original != newStarting)
                    {
                        GrammarSymbol nullable   = rule.Original;
                        bool          isLastRule = newRules.Count((r) => r.Original == nullable) == 0;
                        if (!isLastRule)
                        {
                            for (int i = 0; i < newRules.Count(); i++)
                            {
                                var oldSymbol = newRules[i].Original;
                                var sentence  = newRules[i].DirectDerivative.ToArray();
                                int n         = sentence.Length;
                                Debug.Assert(n < 3);

                                if (n == 1 && sentence[0] == nullable)
                                {
                                    AddIfNotExist(ref newRules, new Production(oldSymbol, Sentence.Empty));
                                }
                                else if (n == 2)
                                {
                                    if (sentence[0] == sentence[1] && sentence[0] == nullable)
                                    {
                                        AddIfNotExist(ref newRules, new Production(oldSymbol, Sentence.Empty));
                                        AddIfNotExist(ref newRules, new Production(oldSymbol, new Sentence(new[] { sentence[0] })));
                                    }
                                    else if (sentence[0] == nullable)
                                    {
                                        AddIfNotExist(ref newRules, new Production(oldSymbol, new Sentence(new[] { sentence[1] })));
                                    }
                                    else if (sentence[1] == nullable)
                                    {
                                        AddIfNotExist(ref newRules, new Production(oldSymbol, new Sentence(new[] { sentence[0] })));
                                    }
                                }
                            }
                        }
                        else
                        {
                            for (int i = 0; i < newRules.Count(); i++)
                            {
                                var oldSymbol = newRules[i].Original;
                                var sentence  = newRules[i].DirectDerivative.ToArray();
                                int n         = sentence.Length;
                                Debug.Assert(n < 3);

                                if (n == 1 && sentence[0] == nullable)
                                {
                                    AddIfNotExist(ref newRules, new Production(oldSymbol, Sentence.Empty));
                                }
                                else if (n == 2)
                                {
                                    if (sentence[0] == sentence[1] && sentence[0] == nullable)
                                    {
                                        AddIfNotExist(ref newRules, new Production(oldSymbol, Sentence.Empty));
                                    }
                                    else if (sentence[0] == nullable)
                                    {
                                        AddIfNotExist(ref newRules, new Production(oldSymbol, new Sentence(new[] { sentence[1] })));
                                    }
                                    else
                                    {
                                        AddIfNotExist(ref newRules, new Production(oldSymbol, new Sentence(new[] { sentence[0] })));
                                    }
                                }
                            }
                            newNonterminals.Remove(nullable);
                        }
                        newRules.Remove(rule);
                        toBeAddedRules = new List <Production>();
                        noEpsilonLeft  = false;
                        break;
                    }
                }
            }

            bool noUnitRuleLeft = false;

            while (!noUnitRuleLeft)
            {
                noUnitRuleLeft = true;
                foreach (var rule in newRules)
                {
                    bool isUnitRule = rule.DirectDerivative.Length == 1 && !rule.DirectDerivative.First().IsTerminal;
                    if (isUnitRule)
                    {
                        newRules.Remove(rule);

                        var toBeReplaced = rule.DirectDerivative.First();
                        var replacement  = rule.Original;
                        for (int i = 0; i < newRules.Count(); i++)
                        {
                            var oldSymbol = newRules[i].Original;
                            var sentence  = newRules[i].DirectDerivative.ToArray();

                            if (oldSymbol == toBeReplaced)
                            {
                                toBeAddedRules.Add(new Production(replacement, new Sentence(sentence)));
                            }
                        }
                        newNonterminals.Remove(toBeReplaced);
                        newRules.AddRange(toBeAddedRules);
                        toBeAddedRules = new List <Production>();

                        noUnitRuleLeft = false;
                        break;
                    }
                }
            }

            return(new ContextFreeGrammar(newNonterminals.ToArray(), this.terminals, newRules.ToArray(), newStarting));
        }