// expand an OR symbol throughout a rule // error if more than one in pattern IList <AtomicRule> ExpandSymbolMulti(AtomicRule oldrule, ObjectSymbol oldsym) { var pcells = oldrule.Patterns.SelectMany(p => p.Cells .SelectMany(c => c.Where(a => a.Symbol == oldsym && !a.IsNegated))); if (pcells.Count() != 1) { return(null); } // expand one rule per object id var newrules = new List <AtomicRule>(); foreach (var newobj in oldsym.ObjectIds) { var newrule = oldrule.Clone(); for (var riter = new RuleIterator { Rule = oldrule }; !riter.Done; riter.Step()) { newrule.Patterns[riter.SubRuleIndex].Cells[riter.CellIndex] = ReplaceObject(riter.PatternAtoms, oldsym, newobj); newrule.Actions[riter.SubRuleIndex].Cells[riter.CellIndex] = ReplaceObject(riter.ActionAtoms, oldsym, newobj); } newrules.AddRange(ExpandRule(newrule)); } return(newrules); }
// expand an ambiguous direction throughout a rule // error if more than one in pattern IList <AtomicRule> ExpandDirectionMulti(AtomicRule oldrule, Direction olddir) { var pcells = oldrule.Patterns.SelectMany(p => p.Cells .SelectMany(c => c.Where(a => a.Direction == olddir))); if (pcells.Count() != 1) { _parser.CompileError("'{0}' in action cannot be matched", olddir); } // expand one rule per single direction var newrules = new List <AtomicRule>(); foreach (var newdir in _expanddirlookup[olddir]) { var newrule = oldrule.Clone(); for (var riter = new RuleIterator { Rule = oldrule }; !riter.Done; riter.Step()) { newrule.Patterns[riter.SubRuleIndex].Cells[riter.CellIndex] = ReplaceDirection(riter.PatternAtoms, olddir, newdir); newrule.Actions[riter.SubRuleIndex].Cells[riter.CellIndex] = ReplaceDirection(riter.ActionAtoms, olddir, newdir); } newrules.AddRange(ExpandRule(newrule)); } return(newrules); }
// Convert every relative direction into absolute AtomicRule MakeAbsolute(AtomicRule rule, Direction ruledir) { var newrule = rule.Clone(); newrule.Directions = new HashSet <Direction>() { ruledir }; MakeAbsolute(newrule.Patterns, ruledir); if (newrule.HasAction) { MakeAbsolute(newrule.Actions, ruledir); } return(newrule); }