| OLD | NEW |
| 1 # Copyright 2013 the V8 project authors. All rights reserved. | 1 # Copyright 2013 the V8 project authors. All rights reserved. |
| 2 # Redistribution and use in source and binary forms, with or without | 2 # Redistribution and use in source and binary forms, with or without |
| 3 # modification, are permitted provided that the following conditions are | 3 # modification, are permitted provided that the following conditions are |
| 4 # met: | 4 # met: |
| 5 # | 5 # |
| 6 # * Redistributions of source code must retain the above copyright | 6 # * Redistributions of source code must retain the above copyright |
| 7 # notice, this list of conditions and the following disclaimer. | 7 # notice, this list of conditions and the following disclaimer. |
| 8 # * Redistributions in binary form must reproduce the above | 8 # * Redistributions in binary form must reproduce the above |
| 9 # copyright notice, this list of conditions and the following | 9 # copyright notice, this list of conditions and the following |
| 10 # disclaimer in the documentation and/or other materials provided | 10 # disclaimer in the documentation and/or other materials provided |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 "literal" : (257, 257), | 35 "literal" : (257, 257), |
| 36 } | 36 } |
| 37 __lower_bound = 0 | 37 __lower_bound = 0 |
| 38 __upper_bound = reduce(lambda acc, (k, v): max(acc, v[1]), __class_bounds.item
s(), 0) | 38 __upper_bound = reduce(lambda acc, (k, v): max(acc, v[1]), __class_bounds.item
s(), 0) |
| 39 | 39 |
| 40 __cached_keys = {} | 40 __cached_keys = {} |
| 41 | 41 |
| 42 __unique_key_counter = -1 | 42 __unique_key_counter = -1 |
| 43 | 43 |
| 44 @staticmethod | 44 @staticmethod |
| 45 def alphabet_iter(): |
| 46 for k, (lower, upper) in TransitionKey.__class_bounds.items(): |
| 47 for i in range(lower, upper + 1): |
| 48 yield i |
| 49 |
| 50 @staticmethod |
| 45 def __in_latin_1(char): | 51 def __in_latin_1(char): |
| 46 bound = TransitionKey.__class_bounds["latin_1"] | 52 bound = TransitionKey.__class_bounds["latin_1"] |
| 47 return (bound[0] <= char and char <= bound[1]) | 53 return (bound[0] <= char and char <= bound[1]) |
| 48 | 54 |
| 49 @staticmethod | 55 @staticmethod |
| 50 def __is_class_range(r): | 56 def __is_class_range(r): |
| 51 return r[0] == r[1] and not TransitionKey.__in_latin_1(r[0]) | 57 return r[0] == r[1] and not TransitionKey.__in_latin_1(r[0]) |
| 52 | 58 |
| 53 @staticmethod | 59 @staticmethod |
| 54 def __is_unique_range(r): | 60 def __is_unique_range(r): |
| (...skipping 24 matching lines...) Expand all Loading... |
| 79 assert name == 'epsilon' | 85 assert name == 'epsilon' |
| 80 assert not name in TransitionKey.__cached_keys | 86 assert not name in TransitionKey.__cached_keys |
| 81 else: | 87 else: |
| 82 TransitionKey.__verify_ranges(ranges, True) | 88 TransitionKey.__verify_ranges(ranges, True) |
| 83 key = TransitionKey() | 89 key = TransitionKey() |
| 84 key.__ranges = tuple(ranges) # immutable | 90 key.__ranges = tuple(ranges) # immutable |
| 85 key.__name = name | 91 key.__name = name |
| 86 key.__cached_hash = None | 92 key.__cached_hash = None |
| 87 return key | 93 return key |
| 88 | 94 |
| 95 def __is_unique(self): |
| 96 return len(self.__ranges) == 1 and self.__is_unique_range(self.__ranges[0]) |
| 97 |
| 89 @staticmethod | 98 @staticmethod |
| 90 def __cached_key(name, bounds_getter): | 99 def __cached_key(name, bounds_getter): |
| 91 if not name in TransitionKey.__cached_keys: | 100 if not name in TransitionKey.__cached_keys: |
| 92 bounds = bounds_getter(name) | 101 bounds = bounds_getter(name) |
| 93 TransitionKey.__cached_keys[name] = TransitionKey.__create(bounds, name) | 102 TransitionKey.__cached_keys[name] = TransitionKey.__create(bounds, name) |
| 94 return TransitionKey.__cached_keys[name] | 103 return TransitionKey.__cached_keys[name] |
| 95 | 104 |
| 96 @staticmethod | 105 @staticmethod |
| 97 def epsilon(): | 106 def epsilon(): |
| 98 return TransitionKey.__cached_key("epsilon", lambda name : []) | 107 return TransitionKey.__cached_key("epsilon", lambda name : []) |
| 99 | 108 |
| 100 @staticmethod | 109 @staticmethod |
| 101 def any(): | 110 def any(): |
| 102 return TransitionKey.__cached_key("any", | 111 return TransitionKey.__cached_key("any", |
| 103 lambda name : TransitionKey.__class_bounds.values()) | 112 lambda name : TransitionKey.__class_bounds.values()) |
| 104 | 113 |
| 105 @staticmethod | 114 @staticmethod |
| 106 def single_char(char): | 115 def single_char(char): |
| 107 char = ord(char) | 116 char = ord(char) |
| 108 assert TransitionKey.__in_latin_1(char) | 117 assert TransitionKey.__in_latin_1(char) |
| 109 return TransitionKey.__create([(char, char)]) | 118 return TransitionKey.__create([(char, char)]) |
| 110 | 119 |
| 111 @staticmethod | 120 @staticmethod |
| 112 def unique_key(name): | 121 def unique(name): |
| 113 def get_bounds(name): | 122 def get_bounds(name): |
| 114 bound = TransitionKey.__unique_key_counter | 123 bound = TransitionKey.__unique_key_counter |
| 115 TransitionKey.__unique_key_counter -= 1 | 124 TransitionKey.__unique_key_counter -= 1 |
| 116 return [(bound, bound)] | 125 return [(bound, bound)] |
| 117 name = "__" + name | 126 name = "__" + name |
| 118 return TransitionKey.__cached_key(name, get_bounds) | 127 return TransitionKey.__cached_key(name, get_bounds) |
| 119 | 128 |
| 120 @staticmethod | 129 @staticmethod |
| 121 def __process_graph(graph, ranges, key_map): | 130 def __process_graph(graph, ranges, key_map): |
| 122 key = graph[0] | 131 key = graph[0] |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 to_push.append(v) | 244 to_push.append(v) |
| 236 else: | 245 else: |
| 237 ranges.append((left, v)) | 246 ranges.append((left, v)) |
| 238 left = v + 1 | 247 left = v + 1 |
| 239 if to_push: | 248 if to_push: |
| 240 current = range_map[i + 1] | 249 current = range_map[i + 1] |
| 241 range_map[i + 1] = (current[0], sort(current[1] + to_push)) | 250 range_map[i + 1] = (current[0], sort(current[1] + to_push)) |
| 242 return ranges | 251 return ranges |
| 243 | 252 |
| 244 @staticmethod | 253 @staticmethod |
| 245 def disjoint_keys(key_set): | 254 def __disjoint_ranges_from_key_set(key_set): |
| 246 key_set.discard(TransitionKey.epsilon()) | |
| 247 if not key_set: | 255 if not key_set: |
| 248 return [] | 256 return [] |
| 249 range_map = {} | 257 range_map = {} |
| 250 for x in key_set: | 258 for x in key_set: |
| 259 assert not x.__is_unique() |
| 260 assert x != TransitionKey.epsilon |
| 251 for r in x.__ranges: | 261 for r in x.__ranges: |
| 252 if not r[0] in range_map: | 262 if not r[0] in range_map: |
| 253 range_map[r[0]] = [] | 263 range_map[r[0]] = [] |
| 254 range_map[r[0]].append(r[1]) | 264 range_map[r[0]].append(r[1]) |
| 255 ranges = TransitionKey.__disjoint_keys(range_map) | 265 ranges = TransitionKey.__disjoint_keys(range_map) |
| 256 TransitionKey.__verify_ranges(ranges, False) | 266 TransitionKey.__verify_ranges(ranges, False) |
| 267 return ranges |
| 268 |
| 269 @staticmethod |
| 270 def disjoint_keys(key_set): |
| 271 ranges = TransitionKey.__disjoint_ranges_from_key_set(key_set) |
| 257 return map(lambda x : TransitionKey.__create([x]), ranges) | 272 return map(lambda x : TransitionKey.__create([x]), ranges) |
| 258 | 273 |
| 259 @staticmethod | 274 @staticmethod |
| 275 def inverse_key(key_set): |
| 276 ranges = TransitionKey.__disjoint_ranges_from_key_set(key_set) |
| 277 inverse = TransitionKey.__invert_ranges(ranges) |
| 278 if not inverse: |
| 279 return None |
| 280 return TransitionKey.__create(inverse) |
| 281 |
| 282 @staticmethod |
| 260 def __key_from_ranges(invert, ranges): | 283 def __key_from_ranges(invert, ranges): |
| 261 range_map = {} | 284 range_map = {} |
| 262 for r in ranges: | 285 for r in ranges: |
| 263 if not r[0] in range_map: | 286 if not r[0] in range_map: |
| 264 range_map[r[0]] = [] | 287 range_map[r[0]] = [] |
| 265 range_map[r[0]].append(r[1]) | 288 range_map[r[0]].append(r[1]) |
| 266 ranges = TransitionKey.__disjoint_keys(range_map) | 289 ranges = TransitionKey.__disjoint_keys(range_map) |
| 267 ranges = TransitionKey.__merge_ranges(ranges) | 290 ranges = TransitionKey.__merge_ranges(ranges) |
| 268 if invert: | 291 if invert: |
| 269 ranges = TransitionKey.__invert_ranges(ranges) | 292 ranges = TransitionKey.__invert_ranges(ranges) |
| (...skipping 19 matching lines...) Expand all Loading... |
| 289 @staticmethod | 312 @staticmethod |
| 290 def merged_key(keys): | 313 def merged_key(keys): |
| 291 f = lambda acc, key: acc + list(key.__ranges) | 314 f = lambda acc, key: acc + list(key.__ranges) |
| 292 return TransitionKey.__key_from_ranges(False, reduce(f, keys, [])) | 315 return TransitionKey.__key_from_ranges(False, reduce(f, keys, [])) |
| 293 | 316 |
| 294 @staticmethod | 317 @staticmethod |
| 295 def __invert_ranges(ranges): | 318 def __invert_ranges(ranges): |
| 296 inverted = [] | 319 inverted = [] |
| 297 last = None | 320 last = None |
| 298 classes = set(TransitionKey.__class_bounds.values()) | 321 classes = set(TransitionKey.__class_bounds.values()) |
| 299 classes.remove(TransitionKey.__class_bounds["latin_1"]) | 322 latin_1 = TransitionKey.__class_bounds["latin_1"] |
| 323 classes.remove(latin_1) |
| 300 for r in ranges: | 324 for r in ranges: |
| 301 assert not TransitionKey.__is_unique_range(r) | 325 assert not TransitionKey.__is_unique_range(r) |
| 302 if TransitionKey.__is_class_range(r): | 326 if TransitionKey.__is_class_range(r): |
| 303 classes.remove(r) | 327 classes.remove(r) |
| 304 continue | 328 continue |
| 305 if last == None: | 329 if last == None: |
| 306 if r[0] != TransitionKey.__lower_bound: | 330 if r[0] != TransitionKey.__lower_bound: |
| 307 inverted.append((TransitionKey.__lower_bound, r[0] - 1)) | 331 inverted.append((TransitionKey.__lower_bound, r[0] - 1)) |
| 308 elif last[1] + 1 < r[0]: | 332 elif last[1] + 1 < r[0]: |
| 309 inverted.append((last[1] + 1, r[0] - 1)) | 333 inverted.append((last[1] + 1, r[0] - 1)) |
| 310 last = r | 334 last = r |
| 311 upper_bound = TransitionKey.__class_bounds["latin_1"][1] | 335 upper_bound = latin_1[1] |
| 312 if last != None and last[1] < upper_bound: | 336 if last == None: |
| 337 inverted.append(latin_1) |
| 338 elif last[1] < upper_bound: |
| 313 inverted.append((last[1] + 1, upper_bound)) | 339 inverted.append((last[1] + 1, upper_bound)) |
| 314 inverted += list(classes) | 340 inverted += list(classes) |
| 315 return inverted | 341 return inverted |
| OLD | NEW |