public Rule(IEnumerable <Chain> chains, NonTerminalSymbol target) { if (chains == null) { throw new ArgumentNullException(nameof(chains)); } if (target == null) { throw new ArgumentNullException(nameof(target)); } Chains = chains.ToSortedSet().AsReadOnly(); if (!Chains.Any()) { throw new ArgumentException("Rule must contain at least one chain."); } if (Chains.AnyNull()) { throw new ArgumentException("At least one null chain was found."); } Alphabet = Chains.SelectMany(chain => chain.Alphabet).ToSortedSet().AsReadOnly(); Target = target; ISet <NonTerminalSymbol> nonTerminals = Chains.SelectMany(chain => chain.NonTerminals).ToSortedSet(); nonTerminals.Add(Target); NonTerminals = nonTerminals.AsReadOnly(); }