private NfaState NewNfaState(ushort?acceptState = null) { var res = new NfaState(_nextNfaStateNumber, acceptState); _nfaStates.Add(res); ++_nextNfaStateNumber; return(res); }
private void GetEpsilonMoves(SortedSet <NfaState> stateCollection, NfaState currentState) { foreach (var pair in currentState.Map) { if (pair.Key != RegExInputRange.EPS) { continue; } var state = pair.Value; if (stateCollection.Contains(state)) { continue; } stateCollection.Add(state); GetEpsilonMoves(stateCollection, state); } }
private void Apply(RegExNode regExNode, NfaState begin, NfaState end) { switch (regExNode.RegExType) { case RegExType.Blank: Transition(begin, end, RegExInputRange.EPS); break; case RegExType.Union: var union = (RegExNodeUnion)regExNode; foreach (var exp in union.Expressions) { Apply(exp, begin, end); } break; case RegExType.Concat: var concat = (RegExNodeConcat)regExNode; var lastConcat = begin; for (var i = 0; i < concat.Expressions.Count; i++) { var tmp = (i + 1) < concat.Expressions.Count ? NewNfaState() : end; Apply(concat.Expressions[i], lastConcat, tmp); lastConcat = tmp; } break; case RegExType.Ranges: var prim = (RegExNodeRanges)regExNode; foreach (var range in prim.Ranges) { Transition(begin, end, range); } break; case RegExType.Sequence: var seq = (RegExNodeSequence)regExNode; var lastSeq = begin; switch (seq.Casing) { case RegExCasing.Insensitive: for (var i = 0; i < seq.Sequence.Length; i++) { var tmp = (i + 1 < seq.Sequence.Length) ? NewNfaState() : end; var c1 = char.ToLowerInvariant(seq.Sequence[i]); var c2 = char.ToUpperInvariant(c1); Transition(lastSeq, tmp, new RegExInputRange(c1)); if (c2 != c1) { Transition(lastSeq, tmp, new RegExInputRange(c2)); } lastSeq = tmp; } break; case RegExCasing.Sensitive: for (var i = 0; i < seq.Sequence.Length; i++) { var tmp = (i + 1 < seq.Sequence.Length) ? NewNfaState() : end; Transition(lastSeq, tmp, new RegExInputRange(seq.Sequence[i])); lastSeq = tmp; } break; } break; case RegExType.Repeat: var rep = (RegExNodeRepeat)regExNode; switch (rep.RegExRepeatType) { case RegExRepeatType.ZeroOrOne: Apply(rep.Expression, begin, end); Transition(begin, end, RegExInputRange.EPS); break; case RegExRepeatType.ZeroOrMore: { var s1 = NewNfaState(); var s2 = NewNfaState(); Transition(begin, end, RegExInputRange.EPS); Transition(begin, s1, RegExInputRange.EPS); Apply(rep.Expression, s1, s2); Transition(s2, s1, RegExInputRange.EPS); Transition(s2, end, RegExInputRange.EPS); } break; case RegExRepeatType.OneOrMore: { var s1 = NewNfaState(); var s2 = NewNfaState(); Transition(begin, s1, RegExInputRange.EPS); Apply(rep.Expression, s1, s2); Transition(s2, s1, RegExInputRange.EPS); Transition(s2, end, RegExInputRange.EPS); } break; } break; case RegExType.Except: var except = (RegExNodeExcept)regExNode; break; case RegExType.Accept: // Add an accept state. var accept = (RegExNodeAccept)regExNode; var term = NewNfaState(accept.AcceptState); Apply(accept.Expression, begin, term); Transition(term, end, RegExInputRange.EPS); break; } }
private static void Transition(NfaState from, NfaState to, RegExInputRange via) { from.Map.Add(new KeyValuePair <RegExInputRange, NfaState>(via, to)); }