1 ''' @file apg_py/lib/ast.py
2 @brief A class for creating and translating the Abstract Syntax Tree (AST).'''
9 '''Set a callback function for a named node.
10 Records will only be kept for nodes that have a
11 callback assigned to them. Called by both the original AST
12 and the shallow copy of the AST passed to the pattern-matching results.
13 @param nodes The list of AST nodes.
14 @param name the rule or UDT name of the node
15 @param callback the callback function for this node'''
18 nodes[lower] = callback
20 raise Exception(
'add_callback name not recognized', name)
24 '''Traverse the AST and call the user's callback functions for
25 translation of the saved AST node phrases.
26 Called by both the original AST
27 and the shallow copy of the AST passed to the pattern-matching results.
28 @param input The input string to the parser as a tuple of integers.
29 @param nodes The list of AST nodes.
30 @param records The list of AST node records.
31 @param data arbitary user data to be passed to the callback functions
34 while(i <
len(records)):
36 callback = nodes[record[
'name']]
37 if(record[
'state'] == id.SEM_PRE):
47 record[
'phrase_index'],
48 record[
'phrase_length'],
50 if(ret == id.SEM_SKIP):
54 record[
'phrase_index'],
55 record[
'phrase_length'],
57 i = record[
'that_record']
63 record[
'phrase_index'],
64 record[
'phrase_length'],
70 '''A class for capturing the AST as the parser traverses the parse tree.'''
74 @param parser the parser object to attach this AST object to'''
81 for rule
in parser.rules:
82 self.
nodesnodes[rule[
'lower']] =
None
83 for udt
in parser.udts:
84 self.
nodesnodes[udt[
'lower']] =
None
87 '''Make a copy suitable for adding callback functions
88 and doing translations.
89 This copy will not interact with the parser.
90 The primary purpose of this is so the class ApgExp (@ref exp.py)
92 do an AST translation of the parsed results and also return
93 a copy of the AST for the user to do a separate, independent
94 translation of the pattern-matched results.
98 cls.
inputinput = copy.copy(ast_to_copy.input)
99 cls.
recordsrecords = copy.deepcopy(ast_to_copy.records)
100 cls.
nodesnodes = copy.copy(ast_to_copy.nodes)
107 return ast_copy(self)
110 '''Add a callback function to the named AST node.
111 @param name The name of the node to add the callback to.
112 @param callback The callback function to add to the node.
113 The function should have the prototype:<br>
114 fn(state, input, index, length, data)
115 - state - SEM_PRE for down, SEM_POST for up (see
117 - input - the parser's input string as a tuple of
118 integers/character codes
119 - index - the index of the first character of the matched phrase
120 - length - the number of characters in the matched phrase
121 - data - the user-supplied data (see @ref Ast.translate()
126 '''Saves an AST record as the parser traverses down through a
127 node with an assigned callback function.
128 @param name The rule or UDT name of the node.
130 if(self.
nodesnodes[name]):
136 'this_record': this_record,
139 'callback': self.
nodesnodes[name],
140 'phrase_index':
None,
141 'phrase_length':
None,
144 def up(self, name, phrase_index, phrase_length):
145 '''Saves an AST record as the parser traverses up through a
146 node with an assigned callback function.
147 Completes the matching "down" record with the information
148 that was not available during the downward traversal of the node.
149 @param name The rule or UDT name of the node.
150 @param phrase_index Index of the first input character of the matched phrase.
151 @param phrase_length The number of input characters matched.
153 if(self.
nodesnodes[name]):
159 'this_record': this_record,
160 'that_record': that_record,
161 'state': id.SEM_POST,
162 'callback': self.
nodesnodes[name],
163 'phrase_index': phrase_index,
164 'phrase_length': phrase_length,
166 self.
recordsrecords[that_record][
'that_record'] = this_record
167 self.
recordsrecords[that_record][
'phrase_index'] = phrase_index
168 self.
recordsrecords[that_record][
'phrase_length'] = phrase_length
171 '''Saves the state of the AST. Should be called by the RNM operators
172 so that the state can be restored should the branch below fail.
173 The state is a list saving off the length of the list of
174 records and the index stack.
179 '''Restores the AST to a previously saved state.
180 Should be called by the RNM operators, for example,
181 if the branch below fails.
182 @param state the return value of a previous call
183 to @ref Ast.save_state()
185 del self.
recordsrecords[state[0]:]
189 '''Clear the AST for reuse by the parser.'''
194 '''Do a depth-first traversal of the AST nodes,
195 calling user-supplied callback functions
196 1) if a record for the node has been created and
197 2) if the user has attached a callback function to the node
198 with @ref Ast.add_callback().
199 @param data User-supplied data which is made available to the
200 callback functions but is otherwise ignored by the AST.'''
A class for capturing the AST as the parser traverses the parse tree.
def add_callback(self, name, callback)
Add a callback function to the named AST node.
def down(self, name)
Saves an AST record as the parser traverses down through a node with an assigned callback function.
def restore_state(self, state)
Restores the AST to a previously saved state.
def clear(self)
Clear the AST for reuse by the parser.
def save_state(self)
Saves the state of the AST.
def translate(self, data=None)
Do a depth-first traversal of the AST nodes, calling user-supplied callback functions 1) if a record ...
def up(self, name, phrase_index, phrase_length)
Saves an AST record as the parser traverses up through a node with an assigned callback function.
def __init__(self, parser)
Class constructor.
def copy(self)
Make a copy suitable for adding callback functions and doing translations.
def inner_translate(input, nodes, records, data=None)
Traverse the AST and call the user's callback functions for translation of the saved AST node phrases...
def inner_add_callback(nodes, name, callback)
Set a callback function for a named node.