예제 #1
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();
        }
예제 #2
0
        private bool IsValid(ProductionInfo production)
        {
            Debug.Assert(nonterminals != null);
            Debug.Assert(terminals != null);
            Debug.Assert(alphabet != null);

            if (!AlphabetContains(nonterminals, production.Original))
            {
                return(false);
            }

            foreach (var symbol in production.DirectDerivative)
            {
                if (!AlphabetContains(alphabet, symbol))
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #3
0
        private static void EnterRules()
        {
            if (nonterminals == null || terminals == null)
            {
                Console.WriteLine("Please enter nonterminal and terminal symbols first.");
                return;
            }
            if (alphabet == null)
            {
                alphabet = nonterminals.Concat(terminals).ToArray();
            }

            string message    = "Enter number of production rules: ";
            int    rulesCount = AskForNumberInput(message, 1);

            rules = new ProductionInfo[rulesCount];
            for (int i = 0; i < rulesCount; i++)
            {
                message = string.Format("Enter original symbol of production rule number {0}: ", i + 1);
                string original = AskForSymbolInput(message, nonterminals);

                message = "Enter number of symbol in the sentence: ";
                int symbolsCount = AskForNumberInput(message, 0);

                string[] sentence = new string[symbolsCount];
                for (int j = 0; j < symbolsCount; j++)
                {
                    message     = string.Format("Enter the symbol number {0}: ", j + 1);
                    sentence[j] = AskForSymbolInput(message, alphabet);
                }

                rules[i] = new ProductionInfo(original, sentence);
            }

            grammar    = new ContextFreeGrammar(nonterminals, terminals, rules, starting);
            normalForm = grammar.GetChomskyNormalForm();
        }
예제 #4
0
        private bool IsValid(ProductionInfo production)
        {
            Debug.Assert(nonterminals != null);
            Debug.Assert(terminals != null);
            Debug.Assert(alphabet != null);

            if (!AlphabetContains(nonterminals, production.Original))
                return false;

            foreach (var symbol in production.DirectDerivative)
                if (!AlphabetContains(alphabet, symbol))
                    return false;

            return true;
        }
예제 #5
0
        private bool HasDuplicates(ProductionInfo[] rules)
        {
            int n = rules.Length;
            for (int i = 0; i < n - 1; i++)
                for (int j = i + 1; j < n; j++)
                    if (rules[i] == rules[j])
                        return true;

            return false;
        }
예제 #6
0
        private static void EnterRules()
        {
            if (nonterminals == null || terminals == null)
            {
                Console.WriteLine("Please enter nonterminal and terminal symbols first.");
                return;
            }
            if (alphabet == null)
                alphabet = nonterminals.Concat(terminals).ToArray();

            string message = "Enter number of production rules: ";
            int rulesCount = AskForNumberInput(message, 1);

            rules = new ProductionInfo[rulesCount];
            for (int i = 0; i < rulesCount; i++)
            {
                message = string.Format("Enter original symbol of production rule number {0}: ", i + 1);
                string original = AskForSymbolInput(message, nonterminals);

                message = "Enter number of symbol in the sentence: ";
                int symbolsCount = AskForNumberInput(message, 0);

                string[] sentence = new string[symbolsCount];
                for (int j = 0; j < symbolsCount; j++)
                {
                    message = string.Format("Enter the symbol number {0}: ", j + 1);
                    sentence[j] = AskForSymbolInput(message, alphabet);
                }

                rules[i] = new ProductionInfo(original, sentence);
            }

            grammar = new ContextFreeGrammar(nonterminals, terminals, rules, starting);
            normalForm = grammar.GetChomskyNormalForm();
        }