예제 #1
0
        // 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);
        }
예제 #2
0
        // 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);
        }
예제 #3
0
 // expand ambiguous directions in rule pattern known to have no matching action
 // replacing by individuals (absolute or relative)
 // abs could be fixed by more powerful vm code
 IList <AtomicRule> ExpandDirectionSimple(AtomicRule oldrule)
 {
     for (var riter = new RuleIterator {
         Rule = oldrule
     }; !riter.Done; riter.Step())
     {
         // look for any ambiguous unmatched pattern directions, just one each time
         var patom = riter.PatternAtoms.FirstOrDefault(a => _expanddirlookup.ContainsKey(a.Direction));
         if (patom != null)
         {
             return(ExpandDirectionSingle(riter, patom.Direction));
         }
     }
     return(new List <AtomicRule> {
         oldrule
     });
 }
예제 #4
0
        // expand a rule where an occurrence on an action does not match its pattern
        // replacing combination directions and symbols by individuals (absolute or relative)
        // could be fixed by more powerful vm code
        IList <AtomicRule> ExpandRule(AtomicRule oldrule)
        {
            if (!oldrule.HasAction)
            {
                return(ExpandDirectionSimple(oldrule));
            }

            // check each cell of each subrule
            for (var riter = new RuleIterator {
                Rule = oldrule
            }; !riter.Done; riter.Step())
            {
                // Do no expansion on random actions
                if (riter.ActionAtoms.Any(a => a.IsRandom))
                {
                    oldrule.Prefixes.Add(RulePrefix.Final);
                }
                else
                {
                    // check for action atom with ambiguous direction and no matching pattern atom
                    var datom = riter.ActionAtoms.FirstOrDefault(a => _expanddirlookup.ContainsKey(a.Direction) &&
                                                                 !riter.PatternAtoms.Any(p => p.Matches(a) && p.Direction == a.Direction));
                    if (datom != null)
                    {
                        return(ExpandDirectionMulti(oldrule, datom.Direction));
                    }

                    // check for action atom with property symbol and no matching pattern atom
                    var satom = riter.ActionAtoms.FirstOrDefault(a => a.Symbol.Kind == SymbolKind.Property &&
                                                                 !a.IsNegated && !a.IsRandom && !riter.PatternAtoms.Any(p => p.Matches(a)));
                    if (satom != null)
                    {
                        var newrules = ExpandSymbolMulti(oldrule, satom.Symbol) ?? ExpandPropertyMatcher(riter);
                        if (newrules == null)
                        {
                            _parser.CompileError("'{0}' in action cannot be matched", satom.Symbol.Name);
                        }
                        else
                        {
                            return(newrules);
                        }
                    }
                }
            }
            return(ExpandDirectionSimple(oldrule));
        }