protected PatternCompiler(IMatcher <Lexem> patternLexer) { var automata = new NonDeterministicAutomata <TValue>(); _automata = automata; _patternLexer = patternLexer; _start = automata.PushEmpty(); }
private static void ConvertAndMatch <TValue>(NonDeterministicNode <TValue> node, string pattern, bool success, string expectedCapture, TValue?expectedValue) where TValue : struct { var scanner = new AutomataMatcher <TValue>(node.ToDeterministic()); using (var reader = new StringReader(pattern)) { var matcher = scanner.Open(reader); Assert.That(matcher.TryMatchNext(out var match), Is.EqualTo(success)); Assert.That(match.Capture, Is.EqualTo(expectedCapture)); Assert.That(match.Value, Is.EqualTo(expectedValue)); } }
/// <Summary> /// Convert compiled regular expression node into graph of non-deterministic /// states connected to given parent state and return final state of /// produced graph. /// </Summary> public NonDeterministicNode <TValue> ConnectTo <TValue>(NonDeterministicAutomata <TValue> automata, NonDeterministicNode <TValue> parent) { NonDeterministicNode <TValue> next; switch (Type) { case NodeType.Alternative: // /-- [child1] --\ // [parent] ---- [child2] ---> [next] // \-- [child3] --/ next = automata.PushEmpty(); foreach (var child in Children) { child.ConnectTo(automata, parent).EpsilonTo(next); } break; case NodeType.Character: // [parent] --{begin, end}--> [next] next = automata.PushEmpty(); foreach (var range in Ranges) { parent.BranchTo(range.Begin, range.End, next); } break; case NodeType.Repeat: // /-- [child] --\ * (max - min) // [parent] - [child] * min ----------------> [next] // \-- [child] --/ * infinite // Convert until lower bound is reached for (var i = 0; i < RepeatMin; ++i) { parent = Children[0].ConnectTo(automata, parent); } next = automata.PushEmpty(); parent.EpsilonTo(next); // Bounded repeat sequence, perform conversion (max - min) times if (RepeatMax >= 0) { for (var i = 0; i < RepeatMax - RepeatMin; ++i) { parent = Children[0].ConnectTo(automata, parent); parent.EpsilonTo(next); } } // Unbounded repeat sequence, loop converted state over itself else { var loop = Children[0].ConnectTo(automata, parent); loop.EpsilonTo(parent); loop.EpsilonTo(next); } return(next); case NodeType.Sequence: // [parent] -> [child1] -> [child2] -> ... -> [next] next = parent; foreach (var child in Children) { next = child.ConnectTo(automata, next); } break; default: throw new InvalidOperationException(); } return(next); }
public void EpsilonTo(NonDeterministicNode <TValue> target) { _automata.EpsilonTo(_index, target._index); }
public void BranchTo(int begin, int end, NonDeterministicNode <TValue> target) { _automata.BranchTo(_index, begin, end, target._index); }