Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: tools/lexer_generator/dfa_path_writer.py

Issue 209473005: Experimental parser: dfa path iteration test (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tools/lexer_generator/generator.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright 2014 the V8 project authors. All rights reserved.
2 # Redistribution and use in source and binary forms, with or without
3 # modification, are permitted provided that the following conditions are
4 # met:
5 #
6 # * Redistributions of source code must retain the above copyright
7 # notice, this list of conditions and the following disclaimer.
8 # * Redistributions in binary form must reproduce the above
9 # copyright notice, this list of conditions and the following
10 # disclaimer in the documentation and/or other materials provided
11 # with the distribution.
12 # * Neither the name of Google Inc. nor the names of its
13 # contributors may be used to endorse or promote products derived
14 # from this software without specific prior written permission.
15 #
16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 import logging
29 from transition_key import TransitionKey
30
31 class Path(object):
32
33 def __init__(self, keys, states):
34 self.__keys = keys
35 self.__states = states
36 assert self.__states
37 self.__hash = None
38
39 def sub_path(self):
40 if len(self) == 1:
41 return None
42 return Path(self.__keys[:-1], self.__states[:-1])
43
44 def key_iter(self):
45 return iter(self.__keys)
46
47 def state_at(self, index):
48 return self.__states[index]
49
50 @staticmethod
51 def __hash_function((reps, l), state):
52 n = state.node_number()
53 h = (reps >> (l % 31) + 1) ^ reps ^ n ^ (n << (l % 31) + 1)
54 return (h, l + 1)
55
56 def __hash__(self):
57 if self.__hash == None:
58 self.__hash = reduce(self.__hash_function, self.__states, (101, -74))[0]
59 return self.__hash
60
61 def __eq__(self, other):
62 return (isinstance(other, self.__class__) and
63 self.__states == other.__states)
64
65 def __len__(self):
66 return len(self.__states)
67
68 class DfaPathWriter(object):
69
70 def __init__(self, dfa):
71 self.__dfa = dfa
72
73 def write_lexer_shell_test_file(self, f):
74 dfa = self.__dfa
75 complete_paths = set()
76 total_paths = 0
77 encoding = dfa.encoding()
78 start_state = dfa.start_state()
79 for path, states_in_path, is_non_looping in dfa.path_iter():
80 states = []
81 keys = []
82 for i, (key, state) in enumerate(path[1:]):
83 states.append(state)
84 keys.append(key)
85 if key == TransitionKey.omega() and is_non_looping:
86 assert i == len(path) - 2
87 p = Path(keys, states)
88 assert not p in complete_paths
89 add_tail_transition = False
90 total_paths += len(p)
91 while p != None and (p not in complete_paths):
92 complete_paths.add(p)
93 self.__write_lines(p, start_state, add_tail_transition, encoding, f)
94 p = p.sub_path()
95 add_tail_transition = True
96 logging.info("complete_paths %d" % len(complete_paths))
97 logging.info("total_paths %d" % total_paths)
98
99 __representative_map = {
100 'non_primary_letter' : 256,
101 'non_primary_whitespace' : 5760,
102 'non_primary_line_terminator' : 8232,
103 'non_primary_everything_else' : 706,
104 'non_primary_identifier_part_not_letter' : 768,
105 }
106
107 __eos_rep = -1
108 __omega_rep = -2
109
110 @staticmethod
111 def get_representatives(key, remaining = -1):
112 reps = []
113 contains_special = False
114 for name, r in key.range_iter(None):
115 if name == 'PRIMARY_RANGE':
116 reps.append(r[0])
117 if r[0] != r[1]:
118 reps.append(r[1])
119 elif name == 'CLASS':
120 reps.append(DfaPathWriter.__representative_map[r])
121 elif name == 'UNIQUE':
122 if r == 'eos':
123 assert remaining == 1
124 reps.append(DfaPathWriter.__eos_rep)
125 contains_special = True
126 else:
127 raise Exception('unimplemented %s %s' % (name, str(r)))
128 elif name == 'OMEGA':
129 assert remaining == 0
130 reps.append(DfaPathWriter.__omega_rep)
131 contains_special = True
132 else:
133 raise Exception('unimplemented %s %s' % (name, str(r)))
134 if contains_special:
135 assert len(reps) == 1
136 return reps
137
138 @staticmethod
139 def no_transition_keys(state, encoding):
140 all_keys = set(state.key_iter())
141 eos_found = False
142 all_keys.discard(TransitionKey.omega())
143 eos_key = TransitionKey.unique('eos')
144 if eos_key in all_keys:
145 all_keys.remove(eos_key)
146 eos_found = True
147 # TODO(dcarney): have inverse key return uniques as a separate list
148 inverse_key = TransitionKey.inverse_key(encoding, all_keys)
149 if not inverse_key:
150 return []
151 reps = DfaPathWriter.get_representatives(inverse_key)
152 if not eos_found:
153 reps.append(DfaPathWriter.__eos_rep)
154 return reps
155
156 @staticmethod
157 def __write_line(head, tail, f):
158 length = len(head)
159 if tail != DfaPathWriter.__eos_rep:
160 length += 1
161 if not length:
162 return
163 if tail == DfaPathWriter.__eos_rep:
164 f.write('%s\n' % ' '.join(map(str, head)))
165 elif head:
166 f.write('%s %s\n' % (' '.join(map(str, head)), str(tail)))
167 else:
168 f.write("%s\n" % str(tail))
169
170 def __write_lines(self, path, start_state, add_tail_transition, encoding, f):
171 current_state = start_state
172 reps = []
173 last_index = len(path) - 1
174 if add_tail_transition:
175 last_index += 1
176 for i, key in enumerate(path.key_iter()):
177 # current_state = current_state.transition_state_for_key(key)
178 # assert current_state == self.__states[i]
179 reps.append(self.get_representatives(key, last_index - i))
180 head = []
181 for i, x in enumerate(reps):
182 assert x
183 if x[0] >= 0:
184 # TODO(dcarney): produce a file with x[-1] here
185 head.append(x[0])
186 elif x[0] == DfaPathWriter.__eos_rep:
187 # this is a trailing eos or a trailing omega following eos.
188 assert i == len(reps) - 1 or (
189 len(x) == 1 and i == len(reps) - 2 and
190 len(reps[-1]) == 1 and reps[-1][0] == DfaPathWriter.__omega_rep)
191 assert add_tail_transition == (i == len(reps) - 1)
192 if i == len(reps) - 1:
193 add_tail_transition = False
194 elif x[0] == DfaPathWriter.__omega_rep:
195 # this is a trailing omega
196 # TODO(dcarney): produce an omega transition, not eos.
197 assert not add_tail_transition
198 assert len(x) == 1 and i == len(reps) - 1
199 else:
200 raise Exception('unreachable')
201 if not add_tail_transition:
202 self.__write_line(head, self.__eos_rep, f)
203 return
204 no_transition_keys = self.no_transition_keys(path.state_at(-1), encoding)
205 # TODO(dcarney): don't test all edges here.
206 for tail in no_transition_keys:
207 self.__write_line(head, tail, f)
OLDNEW
« no previous file with comments | « no previous file | tools/lexer_generator/generator.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698