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

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

Issue 54533002: Experimental parser: more tests, better key logic (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 7 years, 1 month 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 | « tools/lexer_generator/transition_key_test.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 # with the distribution. 11 # with the distribution.
12 # * Neither the name of Google Inc. nor the names of its 12 # * Neither the name of Google Inc. nor the names of its
13 # contributors may be used to endorse or promote products derived 13 # contributors may be used to endorse or promote products derived
14 # from this software without specific prior written permission. 14 # from this software without specific prior written permission.
15 # 15 #
16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28
29 class TransitionKey: 28 class TransitionKey:
30 29
31 __lower_bound = 0 30 __lower_bound = 0
32 __latin_1_upper_bound = 255 31 __latin_1_upper_bound = 255
33 __unicode_whitespace_bounds = (256, 256) 32 __unicode_whitespace_bounds = (256, 256)
34 __unicode_literal_bounds = (257, 257) 33 __unicode_literal_bounds = (257, 257)
35 __upper_bound = 257 34 __upper_bound = 257
36 35
37 @staticmethod 36 @staticmethod
37 def __verify_ranges(ranges):
38 last = (TransitionKey.__lower_bound - 1, TransitionKey.__lower_bound - 1)
39 for r in ranges:
40 assert TransitionKey.__lower_bound <= r[0]
41 assert r[1] <= TransitionKey.__upper_bound
42 assert r[0] <= r[1]
43 assert last[1] < r[0]
44 # TODO check classes are always disjoint points
45 last = r
46
47 @staticmethod
38 def __create(ranges): 48 def __create(ranges):
39 # TODO - verify ranges 49 TransitionKey.__verify_ranges(ranges)
40 key = TransitionKey() 50 key = TransitionKey()
41 key.__ranges = ranges 51 key.__ranges = ranges
42 key.__cached_hash = None 52 key.__cached_hash = None
43 return key 53 return key
44 54
45 __cached_epsilon = None 55 __cached_epsilon = None
46 @staticmethod 56 @staticmethod
47 def epsilon(): 57 def epsilon():
48 if (TransitionKey.__cached_epsilon == None): 58 if (TransitionKey.__cached_epsilon == None):
49 TransitionKey.__cached_epsilon = TransitionKey.__create([]) 59 TransitionKey.__cached_epsilon = TransitionKey.__create([])
50 return TransitionKey.__cached_epsilon 60 return TransitionKey.__cached_epsilon
51 61
52 __cached_any = None 62 __cached_any = None
53 @staticmethod 63 @staticmethod
54 def any(): 64 def any():
55 if (TransitionKey.__cached_any == None): 65 if (TransitionKey.__cached_any == None):
56 bounds = [(TransitionKey.__lower_bound, TransitionKey.__upper_bound)] 66 bounds = [
67 (TransitionKey.__lower_bound, TransitionKey.__latin_1_upper_bound),
68 TransitionKey.__unicode_whitespace_bounds,
69 TransitionKey.__unicode_literal_bounds,
70 ]
57 TransitionKey.__cached_any = TransitionKey.__create(bounds) 71 TransitionKey.__cached_any = TransitionKey.__create(bounds)
58 return TransitionKey.__cached_any 72 return TransitionKey.__cached_any
59 73
60 @staticmethod 74 @staticmethod
61 def single_char(char): 75 def single_char(char):
62 char = ord(char) 76 char = ord(char)
63 assert (TransitionKey.__lower_bound <= char and 77 assert (TransitionKey.__lower_bound <= char and
64 char <= TransitionKey.__latin_1_upper_bound) 78 char <= TransitionKey.__latin_1_upper_bound)
65 return TransitionKey.__create([(char, char)]) 79 return TransitionKey.__create([(char, char)])
66 80
67 @staticmethod 81 @staticmethod
68 def character_class(invert, graph): 82 def character_class(invert, graph):
69 # TODO 83 # TODO
70 return TransitionKey.__create([(129, 129)]) 84 return TransitionKey.__create([(129, 129)])
71 85
72 def matches_char(self, char): 86 def matches_char(self, char):
73 char = ord(char) 87 char = ord(char)
88 # TODO class checks
74 for r in self.__ranges: 89 for r in self.__ranges:
75 if r[0] <= char and char <= r[1]: return True 90 if r[0] <= char and char <= r[1]: return True
76 return False 91 return False
77 92
78 def matches_key(self, key): 93 def matches_key(self, key):
79 assert isinstance(key, self.__class__) 94 assert isinstance(key, self.__class__)
80 assert key != TransitionKey.epsilon() 95 assert key != TransitionKey.epsilon()
81 if self == key: return True 96 assert len(key.__ranges) == 1
82 if self == TransitionKey.epsilon(): return False 97 subkey = key.__ranges[0]
83 # TODO 98 for k in self.__ranges:
99 if k[0] <= subkey[0] and k[1] >= subkey[1]: return True
84 return False 100 return False
85 101
86 def __hash__(self): 102 def __hash__(self):
87 if self.__cached_hash == None: 103 if self.__cached_hash == None:
88 initial_hash = hash((-1, TransitionKey.__upper_bound + 1)) 104 initial_hash = hash((-1, TransitionKey.__upper_bound + 1))
89 f = lambda acc, r: acc ^ hash(r) 105 f = lambda acc, r: acc ^ hash(r)
90 self.__cached_hash = reduce(f, self.__ranges, initial_hash) 106 self.__cached_hash = reduce(f, self.__ranges, initial_hash)
91 return self.__cached_hash 107 return self.__cached_hash
92 108
93 def __eq__(self, other): 109 def __eq__(self, other):
94 return isinstance(other, self.__class__) and self.__ranges == other.__ranges 110 return isinstance(other, self.__class__) and self.__ranges == other.__ranges
95 111
96 @staticmethod 112 @staticmethod
97 def __print_range(r): 113 def __print_range(r):
114 def to_str(x):
115 if x <= TransitionKey.__latin_1_upper_bound:
116 return chr(x)
117 if x == TransitionKey.__unicode_literal_bounds[0]:
118 return "literal"
119 if x == TransitionKey.__unicode_whitespace_bounds[0]:
120 return "whitespace"
121 assert False
98 if r[0] == r[1]: 122 if r[0] == r[1]:
99 return "'%s'" % chr(r[0]) 123 return "'%s'" % to_str(r[0])
100 else: 124 else:
101 return "['%s'-'%s']" % (chr(r[0]), chr(r[1])) 125 return "['%s'-'%s']" % (to_str(r[0]), to_str(r[1]))
102 126
103 def __str__(self): 127 def __str__(self):
104 if self == self.epsilon(): 128 if self == self.epsilon():
105 return "epsilon" 129 return "epsilon"
106 if self == self.any(): 130 if self == self.any():
107 return "any" 131 return "any"
108 return ", ".join(TransitionKey.__print_range(x) for x in self.__ranges) 132 return ", ".join(TransitionKey.__print_range(x) for x in self.__ranges)
109 133
110 @staticmethod 134 @staticmethod
111 def merge_key_set(key_set): 135 def disjoint_keys(key_set):
112 key_set -= set([TransitionKey.epsilon()]) 136 ranges = sorted(reduce(lambda acc, x : acc + x.__ranges, key_set, []))
113 # TODO need intersections and symmetric differences 137 for i in range(0, len(ranges)):
114 return key_set 138 right = ranges[i][1]
139 limit = i
140 for j in range(i + 1, len(ranges)):
141 if ranges[j][0] > right:
142 break
143 assert ranges[j][0] >= ranges[i][0]
144 limit = j
145 if limit == i: continue
146 for j in range(i + 1, limit + 1):
147 ranges[j] = (right, ranges[j][1])
148 TransitionKey.__verify_ranges(ranges)
149 return map(lambda x : TransitionKey.__create([x]), ranges)
OLDNEW
« no previous file with comments | « tools/lexer_generator/transition_key_test.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698