1 using System;
2 using System.Collections;
3
4
5
6
7
8 namespace soulcm.scmlg
9 {
10 public List<NfaState*> EpsilonClosure(const List<NfaState*>& states)
11 {
12 List<NfaState*> stack;
13 for (NfaState* state : states)
14 {
15 stack.Add(state);
16 }
17 List<NfaState*> epsilonClosure = states;
18 while (!stack.IsEmpty())
19 {
20 NfaState* s = stack.Back();
21 stack.RemoveLast();
22 List<NfaState*> u = s->Next(eps);
23 for (NfaState* v : u)
24 {
25 if (Find(epsilonClosure.CBegin(), epsilonClosure.CEnd(), v) == epsilonClosure.CEnd())
26 {
27 epsilonClosure.Add(v);
28 stack.Add(v);
29 }
30 }
31 }
32 return epsilonClosure;
33 }
34 public List<NfaState*> EpsilonClosure(NfaState* state)
35 {
36 List<NfaState*> states(1, state);
37 return EpsilonClosure(states);
38 }
39 public List<NfaState*> Move(const List<NfaState*>& states, uchar c)
40 {
41 List<NfaState*> next;
42 for (NfaState* state : states)
43 {
44 List<NfaState*> n = state->Next(c);
45 for (NfaState* s : n)
46 {
47 if (Find(next.CBegin(), next.CEnd(), s) == next.CEnd())
48 {
49 next.Add(s);
50 }
51 }
52 }
53 return next;
54 }
55 public Dfa Compile(LexerContext& lexerContext, Nfa& nfa)
56 {
57 Dfa dfa;
58 List<NfaState*> start = EpsilonClosure(nfa.Start());
59 DfaState* s = lexerContext.MakeDfaState(start);
60 s->Mark();
61 List<DfaState*> stack;
62 stack.Add(s);
63 while (!stack.IsEmpty())
64 {
65 DfaState* state = stack.Back();
66 stack.RemoveLast();
67 dfa.AddState(state);
68 for (Class* cls : lexerContext.Partition())
69 {
70 if (!cls->Chars().IsEmpty())
71 {
72 uchar c = cls->Chars().Front();
73 List<NfaState*> next = EpsilonClosure(Move(state->NfaStates(), c));
74 if (next.IsEmpty())
75 {
76 state->AddNext(null);
77 }
78 else
79 {
80 DfaState* n = lexerContext.MakeDfaState(next);
81 state->AddNext(n);
82 if (!n->IsMarked())
83 {
84 n->Mark();
85 stack.Add(n);
86 }
87 }
88 }
89 }
90 }
91 dfa.Finalize();
92 return dfa;
93 }
94 }