/// <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 ICompiler <string, TValue> AddEndOfFile(TValue value) { _start.BranchTo(-1, -1, _automata.PushValue(value)); return(this); }