Mercurial > pub > ImplabNet
comparison Implab/Automaton/RegularExpressions/RegularExpressionVisitor.cs @ 177:a0ff6a0e9c44 ref20160224
refactoring
| author | cin |
|---|---|
| date | Wed, 23 Mar 2016 01:42:00 +0300 |
| parents | 92d5278d1b10 |
| children | d5c5db0335ee |
comparison
equal
deleted
inserted
replaced
| 176:0c3c69fe225b | 177:a0ff6a0e9c44 |
|---|---|
| 10 /// регулярное выражение и вычисляет followpos, затем используется метод | 10 /// регулярное выражение и вычисляет followpos, затем используется метод |
| 11 /// <see cref="BuildDFA(IDFADefinition)"/> для построения автомата. | 11 /// <see cref="BuildDFA(IDFADefinition)"/> для построения автомата. |
| 12 /// </summary> | 12 /// </summary> |
| 13 public class RegularExpressionVisitor<TTag> : IVisitor<TTag> { | 13 public class RegularExpressionVisitor<TTag> : IVisitor<TTag> { |
| 14 int m_idx; | 14 int m_idx; |
| 15 Token<TTag> m_root; | 15 Token m_root; |
| 16 HashSet<int> m_firstpos; | 16 HashSet<int> m_firstpos; |
| 17 HashSet<int> m_lastpos; | 17 HashSet<int> m_lastpos; |
| 18 | 18 |
| 19 readonly Dictionary<int, HashSet<int>> m_followpos = new Dictionary<int, HashSet<int>>(); | 19 readonly Dictionary<int, HashSet<int>> m_followpos = new Dictionary<int, HashSet<int>>(); |
| 20 readonly Dictionary<int, int> m_indexes = new Dictionary<int, int>(); | 20 readonly Dictionary<int, int> m_indexes = new Dictionary<int, int>(); |
| 21 readonly Dictionary<int, TTag> m_ends = new Dictionary<int, TTag>(); | 21 readonly HashSet<int> m_ends = new HashSet<int>(); |
| 22 readonly Dictionary<int, TTag> m_tags = new Dictionary<int, TTag>(); | |
| 22 | 23 |
| 23 public Dictionary<int, HashSet<int>> FollowposMap { | 24 public Dictionary<int, HashSet<int>> FollowposMap { |
| 24 get { return m_followpos; } | 25 get { return m_followpos; } |
| 25 } | 26 } |
| 26 | 27 |
| 28 HashSet<int> set; | 29 HashSet<int> set; |
| 29 return m_followpos.TryGetValue(pos, out set) ? set : m_followpos[pos] = new HashSet<int>(); | 30 return m_followpos.TryGetValue(pos, out set) ? set : m_followpos[pos] = new HashSet<int>(); |
| 30 } | 31 } |
| 31 | 32 |
| 32 bool Nullable(object n) { | 33 bool Nullable(object n) { |
| 33 if (n is EmptyToken<TTag> || n is StarToken<TTag>) | 34 if (n is EmptyToken || n is StarToken) |
| 34 return true; | 35 return true; |
| 35 var altToken = n as AltToken<TTag>; | 36 var altToken = n as AltToken; |
| 36 if (altToken != null) | 37 if (altToken != null) |
| 37 return Nullable(altToken.Left) || Nullable(altToken.Right); | 38 return Nullable(altToken.Left) || Nullable(altToken.Right); |
| 38 var catToken = n as CatToken<TTag>; | 39 var catToken = n as CatToken; |
| 39 if (catToken != null) | 40 if (catToken != null) |
| 40 return Nullable(catToken.Left) && Nullable(catToken.Right); | 41 return Nullable(catToken.Left) && Nullable(catToken.Right); |
| 41 return false; | 42 return false; |
| 42 } | 43 } |
| 43 | 44 |
| 44 | 45 |
| 45 public void Visit(AltToken<TTag> token) { | 46 public void Visit(AltToken token) { |
| 46 if (m_root == null) | 47 if (m_root == null) |
| 47 m_root = token; | 48 m_root = token; |
| 48 var firtspos = new HashSet<int>(); | 49 var firtspos = new HashSet<int>(); |
| 49 var lastpos = new HashSet<int>(); | 50 var lastpos = new HashSet<int>(); |
| 50 | 51 |
| 58 | 59 |
| 59 m_firstpos = firtspos; | 60 m_firstpos = firtspos; |
| 60 m_lastpos = lastpos; | 61 m_lastpos = lastpos; |
| 61 } | 62 } |
| 62 | 63 |
| 63 public void Visit(StarToken<TTag> token) { | 64 public void Visit(StarToken token) { |
| 64 if (m_root == null) | 65 if (m_root == null) |
| 65 m_root = token; | 66 m_root = token; |
| 66 token.Token.Accept(this); | 67 token.Token.Accept(this); |
| 67 | 68 |
| 68 foreach (var i in m_lastpos) | 69 foreach (var i in m_lastpos) |
| 69 Followpos(i).UnionWith(m_firstpos); | 70 Followpos(i).UnionWith(m_firstpos); |
| 70 } | 71 } |
| 71 | 72 |
| 72 public void Visit(CatToken<TTag> token) { | 73 public void Visit(CatToken token) { |
| 73 if (m_root == null) | 74 if (m_root == null) |
| 74 m_root = token; | 75 m_root = token; |
| 75 | 76 |
| 76 var firtspos = new HashSet<int>(); | 77 var firtspos = new HashSet<int>(); |
| 77 var lastpos = new HashSet<int>(); | 78 var lastpos = new HashSet<int>(); |
| 95 foreach (var i in leftLastpos) | 96 foreach (var i in leftLastpos) |
| 96 Followpos(i).UnionWith(rightFirstpos); | 97 Followpos(i).UnionWith(rightFirstpos); |
| 97 | 98 |
| 98 } | 99 } |
| 99 | 100 |
| 100 public void Visit(EmptyToken<TTag> token) { | 101 public void Visit(EmptyToken token) { |
| 101 if (m_root == null) | 102 if (m_root == null) |
| 102 m_root = token; | 103 m_root = token; |
| 103 } | 104 } |
| 104 | 105 |
| 105 public void Visit(SymbolToken<TTag> token) { | 106 public void Visit(SymbolToken token) { |
| 106 if (m_root == null) | 107 if (m_root == null) |
| 107 m_root = token; | 108 m_root = token; |
| 108 m_idx++; | 109 m_idx++; |
| 109 m_indexes[m_idx] = token.Value; | 110 m_indexes[m_idx] = token.Value; |
| 110 m_firstpos = new HashSet<int>(new[] { m_idx }); | 111 m_firstpos = new HashSet<int>(new[] { m_idx }); |
| 117 m_idx++; | 118 m_idx++; |
| 118 m_indexes[m_idx] = DFAConst.UNCLASSIFIED_INPUT; | 119 m_indexes[m_idx] = DFAConst.UNCLASSIFIED_INPUT; |
| 119 m_firstpos = new HashSet<int>(new[] { m_idx }); | 120 m_firstpos = new HashSet<int>(new[] { m_idx }); |
| 120 m_lastpos = new HashSet<int>(new[] { m_idx }); | 121 m_lastpos = new HashSet<int>(new[] { m_idx }); |
| 121 Followpos(m_idx); | 122 Followpos(m_idx); |
| 122 m_ends.Add(m_idx, token.Tag); | 123 m_ends.Add(m_idx); |
| 124 m_tags.Add(m_idx, token.Tag); | |
| 125 } | |
| 126 | |
| 127 public void Visit(EndToken token) { | |
| 128 if (m_root == null) | |
| 129 m_root = token; | |
| 130 m_idx++; | |
| 131 m_indexes[m_idx] = DFAConst.UNCLASSIFIED_INPUT; | |
| 132 m_firstpos = new HashSet<int>(new[] { m_idx }); | |
| 133 m_lastpos = new HashSet<int>(new[] { m_idx }); | |
| 134 Followpos(m_idx); | |
| 135 m_ends.Add(m_idx); | |
| 123 } | 136 } |
| 124 | 137 |
| 125 public void BuildDFA(ITaggedDFABuilder<TTag> dfa) { | 138 public void BuildDFA(ITaggedDFABuilder<TTag> dfa) { |
| 126 Safe.ArgumentNotNull(dfa,"dfa"); | 139 Safe.ArgumentNotNull(dfa,"dfa"); |
| 127 | 140 |
| 155 if (m_indexes[p] == a) { | 168 if (m_indexes[p] == a) { |
| 156 next.UnionWith(Followpos(p)); | 169 next.UnionWith(Followpos(p)); |
| 157 } | 170 } |
| 158 } | 171 } |
| 159 if (next.Count > 0) { | 172 if (next.Count > 0) { |
| 160 int s2 = states.Translate(next); | 173 int s2; |
| 161 if (s2 == DFAConst.UNCLASSIFIED_INPUT) { | 174 if (states.Contains(next)) { |
| 175 s2 = states.Translate(next); | |
| 176 } else { | |
| 162 s2 = states.DefineSymbol(next); | 177 s2 = states.DefineSymbol(next); |
| 163 | 178 |
| 164 tags = GetStateTags(next); | 179 if (IsFinal(next)) { |
| 165 if (tags != null && tags.Length > 0) { | 180 |
| 166 dfa.MarkFinalState(s2); | 181 dfa.MarkFinalState(s2); |
| 167 dfa.SetStateTag(s2, tags); | 182 tags = GetStateTags(next); |
| 183 if (tags != null && tags.Length > 0) | |
| 184 dfa.SetStateTag(s2, tags); | |
| 168 } | 185 } |
| 169 | 186 |
| 170 queue.Enqueue(next); | 187 queue.Enqueue(next); |
| 171 } | 188 } |
| 172 dfa.Add(new AutomatonTransition(s1, s2, a)); | 189 dfa.Add(new AutomatonTransition(s1, s2, a)); |
| 173 } | 190 } |
| 174 } | 191 } |
| 175 } | 192 } |
| 176 } | 193 } |
| 177 | 194 |
| 195 bool IsFinal(IEnumerable<int> state) { | |
| 196 Debug.Assert(state != null); | |
| 197 return state.Any(m_ends.Contains); | |
| 198 } | |
| 199 | |
| 178 TTag[] GetStateTags(IEnumerable<int> state) { | 200 TTag[] GetStateTags(IEnumerable<int> state) { |
| 179 Debug.Assert(state != null); | 201 Debug.Assert(state != null); |
| 180 return state.Where(m_ends.ContainsKey).Select(pos => m_ends[pos]).ToArray(); | 202 return state.Where(m_tags.ContainsKey).Select(pos => m_tags[pos]).ToArray(); |
| 181 } | 203 } |
| 182 | 204 |
| 183 } | 205 } |
| 184 } | 206 } |
