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(); }
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); }
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(); }
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; }
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; }
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(); }