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

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

Issue 152513004: Experimental parser: some tuple removal (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 10 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 | « tools/lexer_generator/code_generator.py ('k') | tools/lexer_generator/lexer_test.py » ('j') | 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 from transition_keys import TransitionKey 28 from transition_keys import TransitionKey
29 from automaton import Action 29 from automaton import Term, Action
30 from dfa import Dfa 30 from dfa import Dfa
31 31
32 # --- Optimization: Replacing tokens with gotos --- 32 # --- Optimization: Replacing tokens with gotos ---
33 # 33 #
34 # This optimization reduces the code size for grammars which have constructs 34 # This optimization reduces the code size for grammars which have constructs
35 # similar to keywords and identifiers. Consider the following grammar: 35 # similar to keywords and identifiers. Consider the following grammar:
36 # 36 #
37 # "baz" <|token(BAZ)|> 37 # "baz" <|token(BAZ)|>
38 # "bazz" <|token(BAZZ)|> 38 # "bazz" <|token(BAZZ)|>
39 # 39 #
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 for key, transition_state in state.key_state_iter(): 168 for key, transition_state in state.key_state_iter():
169 if not transition_state in incoming_transitions: 169 if not transition_state in incoming_transitions:
170 incoming_transitions[transition_state] = [] 170 incoming_transitions[transition_state] = []
171 incoming_transitions[transition_state].append((key,state)) 171 incoming_transitions[transition_state].append((key,state))
172 dfa.visit_all_states(build_incoming_transitions) 172 dfa.visit_all_states(build_incoming_transitions)
173 173
174 def is_replacement_candidate(state): 174 def is_replacement_candidate(state):
175 action = state.action() 175 action = state.action()
176 if not action or not action.match_action(): 176 if not action or not action.match_action():
177 return False 177 return False
178 if (action.match_action()[0] == 'token' or 178 if (action.match_action().name() == 'token' or
179 action.match_action()[0] == 'harmony_token'): 179 action.match_action().name() == 'harmony_token'):
180 return True 180 return True
181 return False 181 return False
182 182
183 replacements = {} 183 replacements = {}
184 for state, incoming in incoming_transitions.items(): 184 for state, incoming in incoming_transitions.items():
185 if len(incoming) < 10: 185 if len(incoming) < 10:
186 continue 186 continue
187 if not is_replacement_candidate(state): 187 if not is_replacement_candidate(state):
188 continue 188 continue
189 # check to see if incoming edges are matched by an outgoing edge 189 # check to see if incoming edges are matched by an outgoing edge
(...skipping 28 matching lines...) Expand all
218 'removals' : 0, 218 'removals' : 0,
219 'goto_start' : 0, 219 'goto_start' : 0,
220 'store_token_and_goto' : 0, 220 'store_token_and_goto' : 0,
221 'store_harmony_token_and_goto' : 0, 221 'store_harmony_token_and_goto' : 0,
222 } 222 }
223 store_states = set([]) 223 store_states = set([])
224 # generate a store action to replace an existing action 224 # generate a store action to replace an existing action
225 def replacement_action(old_action, transition_state): 225 def replacement_action(old_action, transition_state):
226 assert old_action.match_action() 226 assert old_action.match_action()
227 state_id = name(transition_state) 227 state_id = name(transition_state)
228 if old_action.match_action()[0] == 'token': 228 if old_action.match_action().name() == 'token':
229 old_token = old_action.match_action()[1] 229 old_token = old_action.match_action().args()[0]
230 if (transition_state.action().match_action()[0] == 'token' and 230 if (transition_state.action().match_action().name() == 'token' and
231 transition_state.action().match_action()[1] == old_token): 231 transition_state.action().match_action().args()[0] == old_token):
232 # no need to store token 232 # no need to store token
233 match_action = ('goto_start', (state_id,)) 233 match_action = Term('goto_start', state_id)
234 counters['goto_start'] += 1 234 counters['goto_start'] += 1
235 else: 235 else:
236 counters['store_token_and_goto'] += 1 236 counters['store_token_and_goto'] += 1
237 match_action = ('store_token_and_goto', (old_token, state_id)) 237 match_action = Term('store_token_and_goto', old_token, state_id)
238 elif old_action.match_action()[0] == 'harmony_token': 238 elif old_action.match_action().name() == 'harmony_token':
239 match_action = ('store_harmony_token_and_goto', 239 new_args = list(old_action.match_action().args()) + [state_id]
240 (old_action.match_action()[1][0], 240 match_action = Term('store_harmony_token_and_goto', *new_args)
241 old_action.match_action()[1][1],
242 old_action.match_action()[1][2],
243 state_id))
244 counters['store_harmony_token_and_goto'] += 1 241 counters['store_harmony_token_and_goto'] += 1
245 else: 242 else:
246 raise Exception(old_action.match_action()) 243 raise Exception(old_action.match_action())
247 return Action(old_action.entry_action(), match_action, 244 return Action(old_action.entry_action(), match_action,
248 old_action.precedence()) 245 old_action.precedence())
249 # map the old state to the new state, with fewer transitions and 246 # map the old state to the new state, with fewer transitions and
250 # goto actions 247 # goto actions
251 def replace_state(state, acc): 248 def replace_state(state, acc):
252 new_state = { 249 new_state = {
253 'transitions' : {}, 250 'transitions' : {},
(...skipping 17 matching lines...) Expand all
271 new_state['action'] = replacement_action(state.action(), replacement) 268 new_state['action'] = replacement_action(state.action(), replacement)
272 # will need to patch up transition_state 269 # will need to patch up transition_state
273 store_states.add(name(transition_state)) 270 store_states.add(name(transition_state))
274 assert not state_replacements 271 assert not state_replacements
275 self.__dfa.visit_all_states(replace_state) 272 self.__dfa.visit_all_states(replace_state)
276 # now patch up all states with stores 273 # now patch up all states with stores
277 start_name = name(self.__dfa.start_state()) 274 start_name = name(self.__dfa.start_state())
278 for state_id in store_states: 275 for state_id in store_states:
279 old_action = states[state_id]['action'] 276 old_action = states[state_id]['action']
280 assert not old_action.entry_action() 277 assert not old_action.entry_action()
281 assert old_action.match_action()[0] == 'token', 'unimplemented' 278 assert old_action.match_action().name() == 'token', 'unimplemented'
282 entry_action = ('store_token', old_action.match_action()[1]) 279 entry_action = Term('store_token', old_action.match_action().args()[0])
283 match_action = ('do_stored_token', state_id) 280 match_action = Term('do_stored_token', state_id)
284 precedence = old_action.precedence() 281 precedence = old_action.precedence()
285 states[state_id]['action'] = Action( 282 states[state_id]['action'] = Action(
286 entry_action, match_action, precedence) 283 entry_action, match_action, precedence)
287 # The state might be only reachable via gotos; make sure it's connected in 284 # The state might be only reachable via gotos; make sure it's connected in
288 # the state graph by adding a bogus transition from the start state. This 285 # the state graph by adding a bogus transition from the start state. This
289 # transition doens't match any character. 286 # transition doens't match any character.
290 states[start_name]['transitions'][ 287 states[start_name]['transitions'][
291 TransitionKey.unique('no_match')] = state_id 288 TransitionKey.unique('no_match')] = state_id
292 289
293 if self.__log: 290 if self.__log:
294 print 'goto_start inserted %s' % counters['goto_start'] 291 print 'goto_start inserted %s' % counters['goto_start']
295 print 'store_token_and_goto inserted %s' % ( 292 print 'store_token_and_goto inserted %s' % (
296 counters['store_token_and_goto']) 293 counters['store_token_and_goto'])
297 print 'store_harmony_token_and_goto %s' % ( 294 print 'store_harmony_token_and_goto %s' % (
298 counters['store_harmony_token_and_goto']) 295 counters['store_harmony_token_and_goto'])
299 print 'transitions removed %s' % counters['removals'] 296 print 'transitions removed %s' % counters['removals']
300 print 'do_stored_token actions added %s' % len(store_states) 297 print 'do_stored_token actions added %s' % len(store_states)
301 self.__dfa = Dfa(self.__dfa.encoding(), start_name, states) 298 self.__dfa = Dfa(self.__dfa.encoding(), start_name, states)
302 299
303 @staticmethod 300 @staticmethod
304 def optimize(dfa, log): 301 def optimize(dfa, log):
305 optimizer = DfaOptimizer(dfa, log) 302 optimizer = DfaOptimizer(dfa, log)
306 optimizer.replace_tokens_with_gotos() 303 optimizer.replace_tokens_with_gotos()
307 return optimizer.__dfa 304 return optimizer.__dfa
OLDNEW
« no previous file with comments | « tools/lexer_generator/code_generator.py ('k') | tools/lexer_generator/lexer_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698