Pattern Deriv(Pattern p, Pattern c) { switch (p.Type) { case PatternType.NotAllowed: return(p); case PatternType.Empty: return(NotAllowed()); case PatternType.Ref: return(c.Type == PatternType.Ref && p.Name == c.Name ? Empty() : NotAllowed()); case PatternType.OneOrMore: return(Group(Deriv(p.p1, c), Optional(p))); case PatternType.Choice: return(Choice(Deriv(p.p1, c), Deriv(p.p2, c))); case PatternType.And: return(And(Deriv(p.p1, c), Deriv(p.p2, c))); case PatternType.Not: return(Not(Deriv(p.p1, c))); case PatternType.Group: if (c.Type == PatternType.Attribute) { return(Choice(Group(Deriv(p.p1, c), p.p2), Group(p.p1, Deriv(p.p2, c)))); } if (p.p1.Nullable) { return(Choice(Deriv(p.p2, c), Group(Deriv(p.p1, c), p.p2))); } return(Group(Deriv(p.p1, c), p.p2)); case PatternType.Text: return(NotAllowed()); case PatternType.Attribute: return(c.Type == PatternType.Attribute && p.Name == c.Name ? Optional(p) : NotAllowed()); case PatternType.Interleave: return(Choice(Interleave(Deriv(p.p1, c), p.p2), Interleave(p.p1, Deriv(p.p2, c)))); case PatternType.Define: return(Define(p.Name, Deriv(p.p1, c))); case PatternType.AnyName: return(p); case PatternType.LnName: return(c.Type == PatternType.LnName && c.Name == p.Name ? Empty() : NotAllowed()); case PatternType.NsName: return(c.Type == PatternType.NsName && c.Namespace == p.Namespace ? Empty() : NotAllowed()); default: throw new Exception(); } }
public State Simulate(Pattern elem) { if (Seen.Contains(elem)) { return(Pattern2State [elem]); } var ElemState = new State() { IsNullable = elem.Nullable }; var root = elem; if (!Pattern2State.ContainsKey(root)) { Pattern2State.Add(root, ElemState); } Queue <Pattern> queue = new Queue <Pattern> (); queue.Enqueue(root); var leaves = elem.DescendantNodesAndSelf().Where(x => x.Type == PatternType.Attribute || x.Type == PatternType.Ref).Distinct().ToList(); while (queue.Count > 0) { var current = queue.Dequeue(); var cstate = Pattern2State [current]; if (Seen.Contains(current)) { continue; } current.DescendantNodesAndSelf() .Where(x => x.Type == PatternType.Define) .Where(x => x.Nullable) .ToList() .ForEach(x => cstate.NullableDefines.Add(x.Name)); Seen.Add(current); foreach (var leaf in leaves) { var derived = Deriv(current, leaf); if (derived.Type == PatternType.NotAllowed) { continue; } if (!Pattern2State.ContainsKey(derived)) { Pattern2State.Add(derived, new State() { IsNullable = derived.Nullable }); queue.Enqueue(derived); } var dstate = Pattern2State [derived]; if (leaf.Type == PatternType.Attribute) { if (leaf.Namespace.Length > 0) { cstate.AttrStates.Add("{" + leaf.Namespace + "}" + leaf.Name, dstate); } else { cstate.AttrStates.Add(leaf.Name, dstate); } } else if (leaf.Type == PatternType.Ref) { cstate.ChildStates.Add(leaf.Name, dstate); } } } if (!Pattern2State.ContainsValue(ElemState)) { throw new Exception(); } return(ElemState); }
Pattern Optional(Pattern p) { return(Choice(Empty(), p)); }