private static INfa Any()
 {
     var start = new NfaState();
     var end = new NfaState();
     start.AddTransistion(new TerminalNfaTransition(new AnyTerminal(), end));
     return new Nfa(start, end);
 }
 private static INfa Character(RegexCharacter character)
 {
     var start = new NfaState();
     var end = new NfaState();
     var terminal = new CharacterTerminal(character.Value);
     var transition = new TerminalNfaTransition(
         terminal: terminal,
         target: end);
     start.AddTransistion(transition);
     return new Nfa(start, end);
 }
 private static INfa Character(RegexCharacterClassCharacter character, bool negate)
 {
     var start = new NfaState();
     var end = new NfaState();
     ITerminal terminal = new CharacterTerminal(character.Value);
     if (negate)
         terminal = new NegationTerminal(terminal);
     var transition = new TerminalNfaTransition(
         terminal: terminal,
         target: end);
     start.AddTransistion(transition);
     return new Nfa(start, end);
 }
 private static INfa Empty()
 {
     var start = new NfaState();
     var end = new NfaState();
     start.AddTransistion(new NullNfaTransition(end));
     return new Nfa(start, end);
 }
        private static INfa Union(INfa first, INfa second)
        {
            var start = new NfaState();
            start.AddTransistion(new NullNfaTransition(first.Start));
            start.AddTransistion(new NullNfaTransition(second.Start));

            var end = new NfaState();
            var endTransition = new NullNfaTransition(end);
            first.End.AddTransistion(endTransition);
            second.End.AddTransistion(endTransition);

            return new Nfa(start, end);
        }
 private static INfa Range(RegexCharacterRange range, bool negate)
 {
     // combine characters into a character range terminal
     var start = range.StartCharacter.Value;
     var end = range.EndCharacter.Value;
     ITerminal terminal = new RangeTerminal(start, end);
     var nfaStartState = new NfaState();
     var nfaEndState = new NfaState();
     if (negate)
         terminal = new NegationTerminal(terminal);
     nfaStartState.AddTransistion(
         new TerminalNfaTransition(terminal, nfaEndState));
     return new Nfa(nfaStartState, nfaEndState);
 }
 private static INfa Optional(INfa nfa)
 {
     var start = new NfaState();
     var end = new NfaState();
     start.AddTransistion(new NullNfaTransition(nfa.Start));
     start.AddTransistion(new NullNfaTransition(end));
     nfa.End.AddTransistion(new NullNfaTransition(end));
     return new Nfa(start, end);
 }
        private static INfa KleeneStar(INfa nfa)
        {
            var start = new NfaState();
            var nullToNfaStart = new NullNfaTransition(nfa.Start);

            start.AddTransistion(nullToNfaStart);
            nfa.End.AddTransistion(nullToNfaStart);

            var end = new NfaState();
            var nullToNewEnd = new NullNfaTransition(end);

            start.AddTransistion(nullToNewEnd);
            nfa.End.AddTransistion(nullToNewEnd);

            return new Nfa(start, end);
        }