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

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

Issue 172893003: Experimental parser: add dfa path iterator (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 | « src/lexer/lexer_py.re ('k') | tools/lexer_generator/code_generator.jinja » ('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 2014 the V8 project authors. All rights reserved. 1 # Copyright 2014 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 22 matching lines...) Expand all
33 33
34 @staticmethod 34 @staticmethod
35 def generate(dfa, default_action): 35 def generate(dfa, default_action):
36 return BacktrackingGenerator(dfa, default_action, None).__generate() 36 return BacktrackingGenerator(dfa, default_action, None).__generate()
37 37
38 def __init__(self, dfa, default_action, log): 38 def __init__(self, dfa, default_action, log):
39 self.__dfa = dfa 39 self.__dfa = dfa
40 self.__default_action = default_action 40 self.__default_action = default_action
41 self.__log = log 41 self.__log = log
42 42
43 @staticmethod
44 def __process_error_states(dfa, error_map, action_state_map):
45 path_map = { k : [] for k in error_map.iterkeys()}
46 error_states = set(error_map.iterkeys())
47 for path, states_in_path, terminal in dfa.path_iter():
48 matching = error_states & states_in_path
49 if not matching:
50 continue
51 last_action = None
52 path_length = 0
53 for (key, state) in path:
54 if state in error_states:
55 assert last_action != None
56 path_map[state].append([k for k, s in path[1:path_length]])
57 elif state in action_state_map:
58 last_action = state
59 path_length += 1
60 print reduce(lambda acc, x : acc + len(x), path_map.itervalues(), 0)
61 for state, key_paths in path_map.iteritems():
62 count = 0
63 action_str = map(str, error_map[state][0])
64 for key_path in key_paths:
65 print "path %d %s %s" % (
66 state.node_number(),
67 action_str,
68 " --> ".join(map(str, key_path)))
69 count += 1
70 if count > 10:
71 break
72
43 def __generate(self): 73 def __generate(self):
44 dfa = self.__dfa 74 dfa = self.__dfa
45 default_action = self.__default_action 75 default_action = self.__default_action
46 terminal_set = dfa.terminal_set() 76 terminal_set = dfa.terminal_set()
47 # Collect states that terminate currently. 77 # Collect states that terminate currently.
48 action_states = {} 78 action_states = {}
49 omega_states = set() 79 omega_states = set()
50 def f(state, acc): 80 def f(state, acc):
51 omega_state = state.omega_transition() 81 omega_state = state.omega_transition()
52 if omega_state == None: 82 if omega_state == None:
(...skipping 12 matching lines...) Expand all
65 assert omega_states == terminal_set 95 assert omega_states == terminal_set
66 # Find nodes that need backtracking edges 96 # Find nodes that need backtracking edges
67 incoming_transitions = dfa.build_incoming_transitions_map() 97 incoming_transitions = dfa.build_incoming_transitions_map()
68 backtracking_map = {} 98 backtracking_map = {}
69 store_states = set() 99 store_states = set()
70 # Start node may be an edge case. 100 # Start node may be an edge case.
71 start_state = dfa.start_state() 101 start_state = dfa.start_state()
72 if (not start_state in incoming_transitions and 102 if (not start_state in incoming_transitions and
73 not start_state in action_states): 103 not start_state in action_states):
74 action_states[start_state] = default_action 104 action_states[start_state] = default_action
105 error_map = {}
75 for state in incoming_transitions.iterkeys(): 106 for state in incoming_transitions.iterkeys():
76 if state in omega_states or state in action_states: 107 if state in omega_states or state in action_states:
77 continue 108 continue
78 assert not state.omega_transition() 109 assert not state.omega_transition()
79 seen = set([state]) 110 seen = set([state])
80 unchecked = set([state]) 111 unchecked = set([state])
81 match_edge = set() 112 match_edge = set()
82 while unchecked: 113 while unchecked:
83 next = set() 114 next = set()
84 for unchecked_state in unchecked: 115 for unchecked_state in unchecked:
85 if not unchecked_state in incoming_transitions: 116 if not unchecked_state in incoming_transitions:
86 assert unchecked_state == start_state 117 assert unchecked_state == start_state
87 match_edge.add(unchecked_state) 118 match_edge.add(unchecked_state)
88 continue 119 continue
89 for (incoming_key, incoming_state) in incoming_transitions[unchecked_s tate]: 120 for (incoming_key, incoming_state) in incoming_transitions[unchecked_s tate]:
90 assert not incoming_state in omega_states 121 assert not incoming_state in omega_states
91 assert not incoming_key == TransitionKey.omega() 122 assert not incoming_key == TransitionKey.omega()
92 if incoming_state in seen: 123 if incoming_state in seen:
93 continue 124 continue
94 if incoming_state in action_states: 125 if incoming_state in action_states:
95 match_edge.add(incoming_state) 126 match_edge.add(incoming_state)
96 seen.add(incoming_state) 127 seen.add(incoming_state)
97 else: 128 else:
98 next.add(incoming_state) 129 next.add(incoming_state)
99 seen |= unchecked 130 seen |= unchecked
100 unchecked = next - seen 131 unchecked = next - seen
101 # accumulate unique actions 132 # Accumulate unique actions.
102 actions = set(map(lambda x : action_states[x].term(), match_edge)) 133 actions = set(map(lambda x : action_states[x].term(), match_edge))
103 assert actions 134 assert actions
104 if not len(actions) == 1: 135 if not len(actions) == 1:
105 # TODO(dcarney): need to warn here after second pass 136 error_map[state] = actions, match_edge
106 # actions = set([default_action])
107 continue 137 continue
108 action = iter(actions).next() 138 action = iter(actions).next()
109 # don't install default actions 139 # don't install default actions
110 if action == default_action.term(): 140 if action == default_action.term():
111 continue 141 continue
112 store_states |= match_edge 142 store_states |= match_edge
113 backtracking_map[state.node_number()] = (action, match_edge) 143 backtracking_map[state.node_number()] = (action, match_edge)
144 # Bail if error occurred.
145 if error_map:
146 self.__process_error_states(dfa, error_map, action_states)
147 raise Exception('ambiguous backtracking')
148 # Now install backtracking everywhere.
114 def install_backtracking_action(new_states, node_number): 149 def install_backtracking_action(new_states, node_number):
115 omega_state_id = str(node_number) + '_bt' 150 omega_state_id = str(node_number) + '_bt'
116 key = TransitionKey.omega() 151 key = TransitionKey.omega()
117 new_states[str(node_number)]['transitions'][key] = omega_state_id 152 new_states[str(node_number)]['transitions'][key] = omega_state_id
118 # install new state 153 # install new state
119 old_action = backtracking_map[node_number][0] 154 old_action = backtracking_map[node_number][0]
120 new_states[omega_state_id] = { 155 new_states[omega_state_id] = {
121 'transitions' : {}, 156 'transitions' : {},
122 'action' : Action(Term('backtrack', old_action), 0), 157 'action' : Action(Term('backtrack', old_action), 0),
123 'terminal' : True, 158 'terminal' : True,
(...skipping 16 matching lines...) Expand all
140 k : str(v.node_number()) for (k, v) in old_state.key_state_iter() }, 175 k : str(v.node_number()) for (k, v) in old_state.key_state_iter() },
141 'action' : new_state_action(old_state), 176 'action' : new_state_action(old_state),
142 'terminal' : old_state in terminal_set 177 'terminal' : old_state in terminal_set
143 } 178 }
144 # install a backtracking action 179 # install a backtracking action
145 if node_number in backtracking_map: 180 if node_number in backtracking_map:
146 install_backtracking_action(new_states, node_number) 181 install_backtracking_action(new_states, node_number)
147 return new_states 182 return new_states
148 new_states = dfa.visit_all_states(convert, {}) 183 new_states = dfa.visit_all_states(convert, {})
149 return Dfa(dfa.encoding(), str(start_state.node_number()), new_states) 184 return Dfa(dfa.encoding(), str(start_state.node_number()), new_states)
OLDNEW
« no previous file with comments | « src/lexer/lexer_py.re ('k') | tools/lexer_generator/code_generator.jinja » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698