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

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

Issue 57923002: Experimental parser: add embedded actions (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/automata_test.py ('k') | tools/lexer_generator/nfa.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 nfa import Nfa 28 from nfa import Nfa
29 from transition_keys import TransitionKey
29 30
30 class DfaState: 31 class DfaState:
31 32
32 def __init__(self, name, node_number): 33 def __init__(self, name, node_number):
33 self.__name = name 34 self.__name = name
34 self.__node_number = node_number 35 self.__node_number = node_number
35 self.__transitions = {} 36 self.__transitions = {}
36 37
37 def name(self): 38 def name(self):
38 return self.__name 39 return self.__name
39 40
40 def node_number(self): 41 def node_number(self):
41 return self.__node_number 42 return self.__node_number
42 43
43 def add_transition(self, key, state): 44 def add_transition(self, key, action, state):
44 assert not self.__transitions.has_key(key) 45 assert not self.__transitions.has_key(key)
45 self.__transitions[key] = state 46 self.__transitions[key] = (state, action)
47
48 def set_action(self, action):
49 assert self.__action == None
50 self.__action = action
46 51
47 def transitions(self): 52 def transitions(self):
48 return self.__transitions 53 return self.__transitions
49 54
50 class Dfa: 55 class Dfa:
51 56
52 def __init__(self, start_name, mapping, end_names): 57 def __init__(self, start_name, mapping):
58 self.__terminal_set = set()
53 name_map = {} 59 name_map = {}
54 offset = 0 60 action_map = {}
55 self.__terminal_set = set() 61 for i, name in enumerate(mapping.keys()):
56 for name in mapping.keys(): 62 name_map[name] = DfaState(name, i)
57 dfa_state = DfaState(name, offset) 63 for name, node_data in mapping.items():
58 name_map[name] = dfa_state 64 node = name_map[name]
59 offset += 1 65 if node_data['terminal']:
60 if name in end_names: 66 self.__terminal_set.add(node)
61 self.__terminal_set.add(dfa_state) 67 inversion = {}
62 for name, values in mapping.items(): 68 for key, (state, action) in node_data['transitions'].items():
63 for key, value in values.items(): 69 if not state in inversion:
64 name_map[name].add_transition(key, name_map[value]) 70 inversion[state] = {}
71 # TODO fix this
72 action_key = str(action)
73 if not action_key in action_map:
74 action_map[action_key] = action
75 if not action_key in inversion[state]:
76 inversion[state][action_key] = []
77 inversion[state][action_key].append(key)
78 for state, values in inversion.items():
79 for action_key, keys in values.items():
80 merged_key = TransitionKey.merged_key(keys)
81 action = action_map[action_key]
82 node.add_transition(merged_key, action, name_map[state])
65 self.__start = name_map[start_name] 83 self.__start = name_map[start_name]
66 assert self.__terminal_set 84 assert self.__terminal_set
67 85
68 @staticmethod 86 @staticmethod
69 def __visit_edges(start, visitor, state): 87 def __visit_edges(start, visitor, state):
70 edge = set([start]) 88 edge = set([start])
71 visited = set() 89 visited = set()
90 first = lambda v: [x[0] for x in v]
72 while edge: 91 while edge:
73 f = lambda (next_edge, state), node: ( 92 f = lambda (next_edge, state), node: (
74 next_edge | set(node.transitions().values()), 93 next_edge | set(first(node.transitions().values())),
75 visitor(node, state)) 94 visitor(node, state))
76 (next_edge, state) = reduce(f, edge, (set(), state)) 95 (next_edge, state) = reduce(f, edge, (set(), state))
77 visited |= edge 96 visited |= edge
78 edge = next_edge - visited 97 edge = next_edge - visited
79 return state 98 return state
80 99
81 def matches(self, string): 100 def collect_actions(self, string):
82 state = self.__start 101 state = self.__start
83 for c in string: 102 for c in string:
84 next_state = None 103 next = [s for k, s in state.transitions().items() if k.matches_char(c)]
85 for key, transition_state in state.transitions().items(): 104 if not next:
86 if key.matches_char(c): 105 yield ('MISS',)
87 next_state = transition_state 106 return
88 break 107 assert len(next) == 1
89 if not next_state: 108 (state, action) = next[0]
90 return False 109 if action:
91 state = next_state 110 yield action
92 return state in self.__terminal_set 111 if state in self.__terminal_set:
112 yield ('TERMINATE', )
113 else:
114 yield ('MISS',)
115
116 def matches(self, string):
117 actions = list(self.collect_actions(string))
118 return actions and actions[-1][0] == 'TERMINATE'
93 119
94 def to_dot(self): 120 def to_dot(self):
95 121
96 def f(node, node_content): 122 def f(node, node_content):
97 for key, value in node.transitions().items(): 123 for key, (state, action) in node.transitions().items():
98 node_content.append( 124 node_content.append(
99 " S_%s -> S_%s [ label = \"%s\" ];" % 125 " S_%s -> S_%s [ label = \"%s\" ];" %
100 (node.node_number(), value.node_number(), key)) 126 (node.node_number(), state.node_number(), key))
101 return node_content 127 return node_content
102 128
103 node_content = self.__visit_edges(self.__start, f, []) 129 node_content = self.__visit_edges(self.__start, f, [])
104 terminals = ["S_%d;" % x.node_number() for x in self.__terminal_set] 130 terminals = ["S_%d;" % x.node_number() for x in self.__terminal_set]
105 start_number = self.__start.node_number() 131 start_number = self.__start.node_number()
106 start_shape = "circle" 132 start_shape = "circle"
107 if self.__start in self.__terminal_set: 133 if self.__start in self.__terminal_set:
108 start_shape = "doublecircle" 134 start_shape = "doublecircle"
109 135
110 return ''' 136 return '''
111 digraph finite_state_machine { 137 digraph finite_state_machine {
112 rankdir=LR; 138 rankdir=LR;
113 node [shape = %s, style=filled, bgcolor=lightgrey]; S_%s 139 node [shape = %s, style=filled, bgcolor=lightgrey]; S_%s
114 node [shape = doublecircle, style=unfilled]; %s 140 node [shape = doublecircle, style=unfilled]; %s
115 node [shape = circle]; 141 node [shape = circle];
116 %s 142 %s
117 } 143 }
118 ''' % (start_shape, 144 ''' % (start_shape,
119 start_number, 145 start_number,
120 " ".join(terminals), 146 " ".join(terminals),
121 "\n".join(node_content)) 147 "\n".join(node_content))
OLDNEW
« no previous file with comments | « tools/lexer_generator/automata_test.py ('k') | tools/lexer_generator/nfa.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698