public override bool Equals(Object obj)
        {
            if (obj == null || GetType() != obj.GetType())
            {
                return(false);
            }

            PoemSyntaxRuleDocument p = (PoemSyntaxRuleDocument)obj;

            if (rules.Count != p.rules.Count)
            {
                return(false);
            }
            if (rules.Keys.Except(p.rules.Keys).Any())
            {
                return(false);
            }
            if (p.rules.Keys.Except(rules.Keys).Any())
            {
                return(false);
            }
            foreach (var pair in rules)
            {
                if (!(pair.Value).SetEquals(p.rules[pair.Key]))
                {
                    return(false);
                }
            }
            return(true);
        }
        // Summary:
        //     Parses the specified file with syntax rules. As a result
        //     generates a IPoemSyntaxRuleDocument object.
        //
        // Parameters:
        //   fileName:
        //     The name of the file with syntax rules to be parsed.
        // Returns:
        //     IPoemSyntaxRuleDocument instance representing syntax rules.
        public IPoemSyntaxRuleDocument Parse(string fileName)
        {
            PoemSyntaxRuleDocument doc = new PoemSyntaxRuleDocument();

            string rulesDescriprion = fileReader.ReadTextFromFile(fileName);

            foreach (string line in rulesDescriprion.Split('\n'))
            {
                string[] lineParts = line.Trim().Split(':');

                string        node        = lineParts[0];
                ISet <string> descendants = new HashSet <string>(lineParts[1].Trim().Split('|'));

                doc.AddRule(node, descendants);
            }

            return(doc);
        }