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

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

Issue 170253007: Experimental parser: always apply default transitions (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/dfa_optimizer.py ('k') | 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
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 11 matching lines...) Expand all
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 types import IntType, StringType 28 from types import IntType, StringType
29 from key_encoding import KeyEncoding 29 from key_encoding import KeyEncoding
30 from term import Term 30 from term import Term
31 from transition_key import TransitionKey 31 from transition_key import TransitionKey
32 from automaton import Action
32 33
33 def escape_for_dot(v): 34 def escape_for_dot(v):
34 v = str(v) 35 v = str(v)
35 v = v.replace('\r', '\\\\r').replace('\t', '\\\\t').replace('\n', '\\\\n') 36 v = v.replace('\r', '\\\\r').replace('\t', '\\\\t').replace('\n', '\\\\n')
36 v = v.replace('\\', '\\\\').replace('\"', '\\\"') 37 v = v.replace('\\', '\\\\').replace('\"', '\\\"')
37 return v 38 return v
38 39
39 def map_characters(encoding, term): 40 def map_characters(encoding, term):
40 if term.name() == 'LITERAL': 41 if term.name() == 'LITERAL':
41 f = lambda x : KeyEncoding.to_str(encoding, x) 42 f = lambda x : KeyEncoding.to_str(encoding, x)
(...skipping 21 matching lines...) Expand all
63 node_ix[0] += 1 64 node_ix[0] += 1
64 nodes.append(node_template % (escape_for_dot(term.name()), node_ix[0])) 65 nodes.append(node_template % (escape_for_dot(term.name()), node_ix[0]))
65 for child_ix in child_ixs: 66 for child_ix in child_ixs:
66 edges.append(edge_template % (node_ix[0], child_ix)) 67 edges.append(edge_template % (node_ix[0], child_ix))
67 return node_ix[0] 68 return node_ix[0]
68 raise Exception 69 raise Exception
69 70
70 process(term) 71 process(term)
71 return 'digraph { %s %s }' % ('\n'.join(nodes), '\n'.join(edges)) 72 return 'digraph { %s %s }' % ('\n'.join(nodes), '\n'.join(edges))
72 73
73 def automaton_to_dot(automaton): 74 def automaton_to_dot(automaton, merge = False):
74 75 terminal_set = automaton.terminal_set()
75 def f(node, (node_content, edge_content)): 76 to_skip = set([])
76 if node.action(): 77 # get a replacement action for a state's omega transition
77 action_text = escape_for_dot(node.action()) 78 def analyse_omega_chain(state):
79 omega_chain = list(state.omega_chain_iter())
80 if len(omega_chain) == 1:
81 omega_state = omega_chain[0][0]
82 # Handle match nodes
83 if omega_chain[0][1] == 0:
84 if omega_state in terminal_set:
85 to_skip.add(omega_state) # don't draw omega transition state
86 terminal_set.add(state)
87 return omega_state.action()
88 elif len(omega_chain) == 2:
89 first_action = omega_chain[0][0].action().name()
90 if ((first_action == 'store_token' or
91 first_action == 'store_harmony_token') and
92 omega_chain[1][0].action().name() == 'no_op'):
93 if (omega_chain[0][0].action().term().args() ==
94 omega_chain[1][0].action().term().args()):
95 return Action(Term('goto', omega_chain[0][0].node_number()), 0)
96 else:
97 to_skip.add(omega_chain[0][0]) # don't draw first transition
98 return Action(Term('chain',
99 omega_chain[0][0].action().term(),
100 Term('goto', omega_chain[1][0].node_number())), 0)
101 return Action.empty_action()
102 # draw state
103 skipped = set([])
104 drawn = set([])
105 def draw(node, (node_content, edge_content)):
106 if node in to_skip: # skip match nodes
107 skipped.add(node)
108 return (node_content, edge_content)
109 drawn.add(node)
110 omega_action = analyse_omega_chain(node) if merge else Action.empty_action()
111 node_action = node.action()
112 if node_action.name() == 'no_op':
113 node_action = Action.empty_action()
114 if node_action or omega_action:
115 action_text = str(node.action())
116 if omega_action:
117 action_text += ' | ' + str(omega_action)
118 action_text = '< %s >' % escape_for_dot(action_text)
78 node_content.append(' S_l%s[shape = box, label="%s"];' % 119 node_content.append(' S_l%s[shape = box, label="%s"];' %
79 (node.node_number(), action_text)) 120 (node.node_number(), action_text))
80 node_content.append(' S_%s -> S_l%s [arrowhead = none];' % 121 node_content.append(' S_%s -> S_l%s [arrowhead = none];' %
81 (node.node_number(), node.node_number())) 122 (node.node_number(), node.node_number()))
82 for key, state in node.key_state_iter(): 123 for key, state in node.key_state_iter():
83 if key == TransitionKey.epsilon(): 124 if key == TransitionKey.epsilon():
84 key = "&epsilon;" 125 key = "&epsilon;"
85 elif key == TransitionKey.omega(): 126 elif key == TransitionKey.omega():
127 if omega_action: # don't draw omega transition
128 continue
86 key = "&omega;" 129 key = "&omega;"
87 else: 130 else:
88 key = key.to_string(automaton.encoding()) 131 key = key.to_string(automaton.encoding())
89 edge_content.append(" S_%s -> S_%s [ label = \"%s\" ];" % ( 132 edge_content.append(" S_%s -> S_%s [ label = \"%s\" ];" % (
90 node.node_number(), state.node_number(), escape_for_dot(key))) 133 node.node_number(), state.node_number(), escape_for_dot(key)))
91 return (node_content, edge_content) 134 return (node_content, edge_content)
92 135
93 (node_content, edge_content) = automaton.visit_all_states(f, ([], [])) 136 (node_content, edge_content) = automaton.visit_all_states(draw, ([], []))
137
138 assert skipped == to_skip
139 terminal_set -= to_skip
140 assert automaton.node_count() == len(skipped) + len(drawn)
94 141
95 start_set = automaton.start_set() 142 start_set = automaton.start_set()
96 assert len(start_set) == 1 143 assert len(start_set) == 1
97 start_node = iter(start_set).next() 144 start_node = iter(start_set).next()
98 terminal_set = automaton.terminal_set()
99 145
100 terminals = ["S_%d;" % x.node_number() for x in terminal_set] 146 terminals = ["S_%d;" % x.node_number() for x in terminal_set]
101 start_number = start_node.node_number() 147 start_number = start_node.node_number()
102 start_shape = "circle" 148 start_shape = "circle"
103 if start_node in terminal_set: 149 if start_node in terminal_set:
104 start_shape = "doublecircle" 150 start_shape = "doublecircle"
105 151
106 return ''' 152 return '''
107 digraph finite_state_machine { 153 digraph finite_state_machine {
108 rankdir=LR; 154 rankdir=LR;
109 node [shape = %s, style=filled, bgcolor=lightgrey]; S_%s 155 node [shape = %s, style=filled, bgcolor=lightgrey]; S_%s
110 node [shape = doublecircle, style=unfilled]; %s 156 node [shape = doublecircle, style=unfilled]; %s
111 node [shape = circle]; 157 node [shape = circle];
112 %s 158 %s
113 %s 159 %s
114 } 160 }
115 ''' % (start_shape, 161 ''' % (start_shape,
116 start_number, 162 start_number,
117 " ".join(terminals), 163 " ".join(terminals),
118 "\n".join(edge_content), 164 "\n".join(edge_content),
119 "\n".join(node_content)) 165 "\n".join(node_content))
OLDNEW
« no previous file with comments | « tools/lexer_generator/dfa_optimizer.py ('k') | tools/lexer_generator/generator.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698