private Tuple <NfaState, NfaState> buildNfa(Exp ast) { NfaState start = null; NfaState terminal = null; if (ast.Type != Exp.ExpType.Concat) { start = CreateState(); terminal = CreateState(); } switch (ast.Type) { case Exp.ExpType.Token: { AddEdge(start, terminal, ast.C); break; } case Exp.ExpType.Concat: { var nfa1 = buildNfa(ast.E1); var nfa2 = buildNfa(ast.E2); start = nfa1.Item1; terminal = nfa2.Item2; AddEdge(nfa1.Item2, nfa2.Item1, EPSILON); break; } case Exp.ExpType.Alter: { var nfa1 = buildNfa(ast.E1); var nfa2 = buildNfa(ast.E2); AddEdge(start, nfa1.Item1, EPSILON); AddEdge(start, nfa2.Item1, EPSILON); AddEdge(nfa1.Item2, terminal, EPSILON); AddEdge(nfa2.Item2, terminal, EPSILON); break; } case Exp.ExpType.Kleene: { var nfa = buildNfa(ast.E1); AddEdge(start, terminal, EPSILON); AddEdge(start, nfa.Item1, EPSILON); AddEdge(nfa.Item2, nfa.Item1, EPSILON); AddEdge(nfa.Item2, terminal, EPSILON); break; } } return(new Tuple <NfaState, NfaState> (start, terminal)); }