ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libBASS/parse_tree.c
Revision: 675
Committed: Mon Aug 11 19:38:44 2003 UTC (20 years, 10 months ago) by mmeineke
Content type: text/plain
File size: 10545 byte(s)
Log Message:
Added zConstraint into the BASS language syntax.

File Contents

# Content
1 #include <stdlib.h>
2 #include <stdio.h>
3
4 #include <parse_tree.h>
5 #include <simError.h>
6
7 #ifdef IS_MPI
8 #define __is_lex__
9 #include <mpiBASS.h>
10 #endif
11
12 void walk_down( struct node_tag* the_node, struct namespc the_namespc );
13 int mol_index; // keeps track of the number of molecules
14 int comp_index; // keeps track of the number of components.
15
16 /*
17 * This is the parse tree function that is called by the yacc
18 * routine. It passes the global node and namespace to the recursive
19 * walk_down routine to explore the node tree.
20 */
21
22 void pt_me( struct node_tag* head_node ){
23
24 struct namespc global_namespc;
25
26 if( head_node->type != GLOBAL_HEAD ){
27 sprintf( painCave.errMsg,
28 "Parse tree error: The head node was not the global node.\n" );
29 painCave.isFatal = 1;
30 simError();
31 #ifdef IS_MPI
32 mpiInterfaceExit();
33 #endif //is_mpi
34 }
35
36 global_namespc.index = 0;
37 global_namespc.type = GLOBAL_HEAD;
38
39 mol_index = 0;
40 comp_index = 0;
41 walk_down( head_node->next_stmt, global_namespc );
42 // closed global namespace and exit
43
44 }
45
46 /*
47 * This is the main logic workhorse routine for the node tree
48 * parser. It recursively walks down the node list and calls the
49 * appropriate interface functions acording to the node types. It will
50 * also set the appropriate namespace for the nodes.
51 *
52 * Note: the nodes only know about the namespace of their
53 * current level, the namespace above themselves is hidden.
54 */
55
56 void walk_down( struct node_tag* the_node, struct namespc the_namespc ){
57
58 struct namespc current_namespc;
59
60 if( the_node != NULL ){
61
62 if( the_node->type == GLOBAL_HEAD ){
63 print_tree_error( the_node, "Too many global regions" );
64 }
65
66 if( the_node->stmt_list != NULL ){
67
68 // the statement is a block node of some sort
69
70 switch( the_node->type ){
71
72 case COMPONENT_HEAD:
73 if( the_namespc.type != GLOBAL_HEAD ){
74 print_tree_error( the_node,
75 "component block is not in the global namespace" );
76 }
77 else{
78 init_component( comp_index );
79 current_namespc.index = comp_index;
80 current_namespc.type = COMPONENT_HEAD;
81 walk_down( the_node->stmt_list, current_namespc );
82 comp_index++;
83 }
84 break;
85
86 case MOLECULE_HEAD:
87 if( the_namespc.type != GLOBAL_HEAD ){
88 print_tree_error( the_node,
89 "Molecule block is not in the global namespace" );
90 }
91 else{
92 init_molecule( mol_index );
93 current_namespc.index = mol_index;
94 current_namespc.type = MOLECULE_HEAD;
95 walk_down( the_node->stmt_list, current_namespc );
96 mol_index++;
97 }
98 break;
99
100 case ATOM_HEAD:
101 if( the_namespc.type != MOLECULE_HEAD ){
102 print_tree_error( the_node,
103 "The atom block is not in a molecule namespace" );
104 }
105 else{
106 init_atom( the_node->index );
107 current_namespc.index = the_node->index;
108 current_namespc.type = the_node->type;
109 walk_down( the_node->stmt_list, current_namespc );
110 }
111 break;
112
113 case BOND_HEAD:
114 if( the_namespc.type != MOLECULE_HEAD ){
115 print_tree_error( the_node,
116 "The bond block is not in a molecule namespace" );
117 }
118 else{
119 init_bond( the_node->index );
120 current_namespc.index = the_node->index;
121 current_namespc.type = the_node->type;
122 walk_down( the_node->stmt_list, current_namespc );
123 }
124 break;
125
126 case BEND_HEAD:
127 if( the_namespc.type != MOLECULE_HEAD ){
128 print_tree_error( the_node,
129 "The bend block is not in a molecule namespace" );
130 }
131 else{
132 init_bend( the_node->index );
133 current_namespc.index = the_node->index;
134 current_namespc.type = the_node->type;
135 walk_down( the_node->stmt_list, current_namespc );
136 }
137 break;
138
139 case TORSION_HEAD:
140 if( the_namespc.type != MOLECULE_HEAD ){
141 print_tree_error( the_node,
142 "The torsion block is not in "
143 "a molecule namespace" );
144 }
145 else{
146 init_torsion( the_node->index );
147 current_namespc.index = the_node->index;
148 current_namespc.type = the_node->type;
149 walk_down( the_node->stmt_list, current_namespc );
150 }
151 break;
152
153 case ZCONSTRAINT_HEAD:
154 if( the_namespc.type != GLOBAL_HEAD ){
155 print_tree_error( the_node,
156 "The Zconstraint block is not in "
157 "the global namespace" );
158 }
159 else{
160 init_zconstraint( the_node->index );
161 current_namespc.index = the_node->index;
162 current_namespc.type = the_node->type;
163 walk_down( the_node->stmt_list, current_namespc );
164 }
165 break;
166
167 default:
168 print_tree_error( the_node, "Not a valid code block" );
169 }
170 }
171
172 else{
173
174 // the node is a statement
175
176 switch( the_node->type ){
177
178 case MEMBER_STMT:
179 switch( the_namespc.type ){
180 case BOND_HEAD: // fall through
181 case BEND_HEAD: // fall through
182 case TORSION_HEAD: // same for the first three
183 init_members( the_node, the_namespc );
184 break;
185
186 default:
187 print_tree_error( the_node,
188 "Member statement not in a bond, bend, "
189 "or torsion" );
190 break;
191 }
192 break;
193
194 case CONSTRAINT_STMT:
195 switch( the_namespc.type ){
196 case BOND_HEAD: // fall through
197 case BEND_HEAD: // fall through
198 case TORSION_HEAD: // same for the first three
199 init_constraint( the_node, the_namespc );
200 break;
201
202 default:
203 print_tree_error( the_node,
204 "Constraint statement not in a bond, bend, "
205 "or torsion" );
206 break;
207 }
208 break;
209
210 case ASSIGNMENT_STMT:
211 init_assignment( the_node, the_namespc );
212 break;
213
214 case POSITION_STMT:
215 if( the_namespc.type != ATOM_HEAD ){
216 print_tree_error( the_node,
217 "position statement is not located in an "
218 "atom block" );
219 }
220
221 init_position( the_node, the_namespc );
222 break;
223
224 case ORIENTATION_STMT:
225 if( the_namespc.type != ATOM_HEAD ){
226 print_tree_error( the_node,
227 "orientation statement is not located in an "
228 "atom block" );
229 }
230
231 init_orientation( the_node, the_namespc );
232 break;
233
234 default:
235 print_tree_error( the_node, "unrecognized statement" );
236 break;
237 }
238 }
239
240 // recurse down to the next node
241
242 walk_down( the_node->next_stmt, the_namespc );
243 }
244
245 // send an end of block signal
246 else end_of_block();
247
248 // we're done
249 }
250
251
252
253 /*
254 * This is a routine utilized by the node parsers to make printing
255 * error messages easy.
256 */
257
258 void print_tree_error( struct node_tag* err_node, char* err_msg ){
259
260 switch( err_node->type ){
261
262 case GLOBAL_HEAD:
263 sprintf( painCave.errMsg,
264 "Parse tree error: global head node error -> %s\n",
265 err_msg );
266 break;
267
268 case COMPONENT_HEAD:
269 sprintf( painCave.errMsg,
270 "Parse tree error: component head node error -> %s\n",
271 err_msg );
272 break;
273
274 case MOLECULE_HEAD:
275 sprintf( painCave.errMsg,
276 "Parse tree error: molecule head node error -> %s\n",
277 err_msg );
278 break;
279
280 case ATOM_HEAD:
281 sprintf( painCave.errMsg,
282 "Parse tree error: atom head node error [%d] -> %s\n",
283 err_node->index,
284 err_msg );
285 break;
286
287 case BOND_HEAD:
288 sprintf( painCave.errMsg,
289 "Parse tree error: bond head node error [%d] -> %s\n",
290 err_node->index,
291 err_msg );
292 break;
293
294 case BEND_HEAD:
295 sprintf( painCave.errMsg,
296 "Parse tree error: bend head node error [%d] -> %s\n",
297 err_node->index,
298 err_msg );
299 break;
300
301 case TORSION_HEAD:
302 sprintf( painCave.errMsg,
303 "Parse tree error: torsion head node error [%d] -> %s\n",
304 err_node->index,
305 err_msg );
306 break;
307
308 case ZCONSTRAINT_HEAD:
309 sprintf( painCave.errMsg,
310 "Parse tree error: Zconstraint head node error [%d] -> %s\n",
311 err_node->index,
312 err_msg );
313 break;
314
315 case MEMBER_STMT:
316 sprintf( painCave.errMsg,
317 "Parse tree error: member node error => ( %d, %d, %d, %d )\n"
318 " -> %s\n",
319 err_node->the_data.mbr.a,
320 err_node->the_data.mbr.b,
321 err_node->the_data.mbr.c,
322 err_node->the_data.mbr.d,
323 err_msg );
324 break;
325
326 case CONSTRAINT_STMT:
327 sprintf( painCave.errMsg,
328 "Parse tree error: constraint node error => ( %lf )\n"
329 " -> %s\n",
330 err_node->the_data.cnstr.constraint_val,
331 err_msg );
332 break;
333
334 case ASSIGNMENT_STMT:
335 sprintf( painCave.errMsg,
336 "Parse tree error: assignment node error\n"
337 " => %s = ",
338 err_node->the_data.asmt.identifier );
339
340 switch( err_node->the_data.asmt.type ){
341
342 case STR_ASSN:
343 sprintf( painCave.errMsg,
344 "%s",
345 err_node->the_data.asmt.rhs.str_ptr );
346 break;
347
348 case INT_ASSN:
349 sprintf( painCave.errMsg,
350 "%d",
351 err_node->the_data.asmt.rhs.i_val );
352 break;
353
354 case DOUBLE_ASSN:
355 sprintf( painCave.errMsg,
356 "%lf",
357 err_node->the_data.asmt.rhs.d_val );
358 break;
359 }
360
361 sprintf( painCave.errMsg,
362 "\n"
363 " -> %s\n",
364 err_msg );
365 break;
366
367 case POSITION_STMT:
368 sprintf( painCave.errMsg,
369 "Parse tree error: position node error => ( %lf, %lf, %lf )\n"
370 " -> %s\n",
371 err_node->the_data.pos.x,
372 err_node->the_data.pos.y,
373 err_node->the_data.pos.z,
374 err_msg );
375 break;
376
377 case ORIENTATION_STMT:
378 sprintf( painCave.errMsg,
379 "Parse tree error: orientation node error => ( %lf, %lf, %lf )\n"
380 " -> %s\n",
381 err_node->the_data.ort.x,
382 err_node->the_data.ort.y,
383 err_node->the_data.ort.z,
384 err_msg );
385 break;
386
387 default:
388 sprintf( painCave.errMsg,
389 "Parse tree error: unknown node type -> %s\n",
390 err_msg );
391 }
392
393 painCave.isFatal = 1;
394 simError();
395 #ifdef IS_MPI
396 mpiInterfaceExit();
397 #endif //is_mpi
398
399 }
400
401
402 /*
403 * recursive walkdown and kill of the node tree
404 * note: looks mighty similar to the walkdown routine.
405 */
406
407 void kill_tree( struct node_tag* the_node ){
408
409 // These two are needed to get rid of the integer list
410
411 struct integer_list_tag* current_il;
412 struct integer_list_tag* temp_il;
413
414
415 if( the_node != NULL ){
416
417 if( the_node->stmt_list != NULL ){
418
419 // the statement is a block node of some sort
420
421 kill_tree( the_node->stmt_list );
422 }
423
424 else{
425
426 // the node is a statement
427
428 switch( the_node->type ){
429
430 case ASSIGNMENT_STMT:
431
432 if( the_node->the_data.asmt.type == STR_ASSN )
433 free( the_node->the_data.asmt.rhs.str_ptr );
434
435 free( the_node->the_data.asmt.identifier );
436 break;
437
438 default:
439 // nothing to do here, everyone else can be freed normally.
440 break;
441 }
442 }
443
444 // recurse down to the next node
445
446 kill_tree( the_node->next_stmt );
447 free( the_node );
448 }
449
450 // we're done
451 }