Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – tendra.SVN – Blame – /branches/tendra5/src/utilities/sid/grammar.c – Rev 2

Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/*** grammar.c --- Grammar transforms frontend.
32
 *
33
 ** Author: Steve Folkes <smf@hermes.mod.uk>
34
 *
35
 *** Commentary:
36
 *
37
 * This file implements the SID transformation front-end routines.
38
 *
39
 * Before any of these routines are called, the grammar should have been read
40
 * in by the parser.  The functions should be called in the following order.
41
 *
42
 *	``grammar_check_complete''
43
 *
44
 * This function traces the grammar that is accessible from the entry points,
45
 * and ensures that there are no unused rules, basics, actions or types, and
46
 * that all of the rules are defined.
47
 *
48
 *	``grammar_remove_left_recursion''
49
 *
50
 * This function applies several functions from the file "rule.c" to the rules
51
 * in the grammar, to detect left cycles (this is done by the
52
 * "grammar_find_cycles" function).  When such a cycle is found, it calls
53
 * ``rule_remove_left_cycle'' (defined in the file "rule-lre.c") to remove the
54
 * cycle.  The function removes any left recursion from the rules, replacing
55
 * it with a right recursive equivalent.  See the file "rule-lre.c" for more
56
 * details.
57
 *
58
 * The cycle detection algorithm works as follows: firstly a list of rules is
59
 * built by the function ``rule_build_root_list''; this list acts as the root
60
 * node of the graph.  The remainder of the graph is built up from the
61
 * leftmost rule invocations (if any) in each alternative of each production.
62
 * This graph is depth first searched by the function ``rule_compute_dfs'', to
63
 * produce an ordered list of productions.  The reverse graph (which is
64
 * computed by applying the function ``rule_compute_reverse_list'' to each
65
 * production, at the same time as the dfs is being performed) is then depth
66
 * first searched in the order specified by the list, using the function
67
 * ``rule_compute_reverse_dfs''.  The result of this is the set of left
68
 * cycles.  The algorithm is explained fully in {"Data Structures and
69
 * Algorithms"; Aho, Hopcroft, Ullman; Addison Wesley; ISBN 0-201-00023-7;
70
 * page 222}.
71
 *
72
 *	``grammar_compute_first_sets''
73
 *
74
 * This function applies the ``rule_compute_first_set'' function to all rules
75
 * in the grammar.  The function computes the first set for each rule.  It
76
 * also computes a priority for the rule, and whether the rule is see through
77
 * or not.  See the file "rule-first.c" for more details.
78
 *
79
 *	``grammar_factor''
80
 *
81
 * This function applies the ``rule_factor'' function to all of the rules in
82
 * the grammar.  The function does a number of transformations on the rules to
83
 * make them more likely to be LL(1).  See the file "rule-factor.c" for more
84
 * details.
85
 *
86
 *	``grammar_simplify''
87
 *
88
 * This function calls the ``rule_remove_duplicates'' function on the grammar,
89
 * to remove any rules that have identical form.  See the file "rule-simp.c"
90
 * for more details.
91
 *
92
 *	``grammar_compute_inlining''
93
 *
94
 * This function applies a number of functions to the rules in the grammar in
95
 * order to indicate which rules should be inlined during the output phase.
96
 * See the file "rule-tail.c" for more details.
97
 *
98
 *	``grammar_check_collisions''
99
 *
100
 * This function applies a number of functions to the rules in the grammar in
101
 * order to check that the grammar is valid.  It also causes the first sets
102
 * for all of the alternatives within a rule to be calculated, and if there is
103
 * a see through alternative.  See the file "rule-check.c" for more details.
104
 *
105
 *	``grammar_recompute_alt_names''
106
 *
107
 * This function applies the ``rule_recompute_alt_names'' function to all
108
 * rules in the grammar.  The function recomputes the identifier names that
109
 * are used within each alternative of the rule.  See the file "rule-names.c"
110
 * for more details.
111
 *
112
 *	``grammar_compute_mutations''
113
 *
114
 * This function applies the ``rule_compute_mutations'' function to all rules
115
 * in the grammar.  The function computes the mutation effects from actions
116
 * that mutate their parameters.  See the file "rule-mutate.c" for more
117
 * details.
118
 *
119
 *** Change Log:
120
 * $Log: grammar.c,v $
121
 * Revision 1.1.1.1  1998/01/17  15:57:46  release
122
 * First version to be checked into rolling release.
123
 *
124
 * Revision 1.2  1994/12/15  09:58:13  smf
125
 * Brought into line with OSSG C Coding Standards Document, as per
126
 * "CR94_178.sid+tld-update".
127
 *
128
 * Revision 1.1.1.1  1994/07/25  16:04:34  smf
129
 * Initial import of SID 1.8 non shared files.
130
 *
131
**/
132
 
133
/****************************************************************************/
134
 
135
#include "grammar.h"
136
#include "action.h"
137
#include "basic.h"
138
#include "gen-errors.h"
139
#include "name.h"
140
#include "rule.h"
141
#include "type.h"
142
 
143
/*--------------------------------------------------------------------------*/
144
 
145
static void
146
grammar_trace_ignored PROTO_N ((entry, gclosure))
147
		      PROTO_T (EntryP   entry X
148
			       GenericP gclosure)
149
{
150
    UNUSED (gclosure);
151
    if (entry_is_basic (entry)) {
152
	BasicP basic = entry_get_basic (entry);
153
 
154
	if (basic_get_ignored (basic)) {
155
	    entry_iter (entry, TRUE,
156
			NIL (void (*) PROTO_S ((EntryP, GenericP))),
157
			NIL (GenericP));
158
	}
159
    }
160
}
161
 
162
static void
163
grammar_check_1 PROTO_N ((entry, gclosure))
164
		PROTO_T (EntryP   entry X
165
			 GenericP gclosure)
166
{
167
    UNUSED (gclosure);
168
    switch (entry_type (entry)) EXHAUSTIVE {
169
      case ET_RULE:
170
	if (!rule_is_defined (entry_get_rule (entry))) {
171
	    E_rule_not_defined (entry_key (entry));
172
	}
173
	if (!entry_is_traced (entry)) {
174
	    E_rule_not_used (entry_key (entry));
175
	}
176
	break;
177
      case ET_BASIC:
178
	if (!entry_is_traced (entry)) {
179
	    E_basic_not_used (entry_key (entry));
180
	}
181
	break;
182
      case ET_ACTION:
183
	if (!entry_is_traced (entry)) {
184
	    E_action_not_used (entry_key (entry));
185
	}
186
	break;
187
      case ET_TYPE:
188
	if (!entry_is_traced (entry)) {
189
	    E_type_not_used (entry_key (entry));
190
	}
191
	break;
192
      case ET_NON_LOCAL:
193
	if (!entry_is_traced (entry)) {
194
	    E_non_local_not_used (entry_key (entry));
195
	}
196
	break;
197
      case ET_NAME:
198
      case ET_RENAME:
199
	break;
200
      case ET_PREDICATE:
201
	UNREACHED;
202
    }
203
}
204
 
205
static void
206
grammar_find_cycles PROTO_N ((grammar, type))
207
		    PROTO_T (GrammarP   grammar X
208
			     CycleTypeT type)
209
{
210
    TableP     table         = grammar_table (grammar);
211
    EntryP     predicate_id  = grammar_get_predicate_id (grammar);
212
    RuleP      dfs_list_head = NIL (RuleP);
213
    RuleListT  root_list;
214
    RuleP      rule;
215
 
216
    rule_list_init (&root_list);
217
    table_iter (table, rule_build_root_list, (GenericP) &root_list);
218
    rule_list_terminate (&root_list);
219
    for (rule = rule_list_head (&root_list); rule;
220
	 rule = rule_next_in_root_list (rule)) {
221
	rule_compute_reverse_list (rule, type);
222
	rule_compute_dfs (rule, type, &dfs_list_head);
223
    }
224
    for (rule = rule_list_head (&root_list); rule;
225
	 rule = rule_next_in_root_list (rule)) {
226
	rule_set_dfs_state (rule, DFS_UNTRACED);
227
    }
228
    for (rule = dfs_list_head; rule; rule = rule_get_next_in_dfs (rule)) {
229
	if (!rule_has_no_cycles (rule)) {
230
	    RuleP reverse_dfs_list_head = NIL (RuleP);
231
 
232
	    rule_compute_reverse_dfs (rule, rule, &reverse_dfs_list_head);
233
	    if (reverse_dfs_list_head) {
234
		switch (type) EXHAUSTIVE {
235
		  case CT_LEFT:
236
		    rule_remove_left_cycle (reverse_dfs_list_head,
237
					    predicate_id, table);
238
		    break;
239
		  case CT_TAIL:
240
		    rule_handle_tails (reverse_dfs_list_head);
241
		    break;
242
		  case CT_ALL:
243
		    rule_handle_need_functions (reverse_dfs_list_head);
244
		    break;
245
		  case CT_MUTATE:
246
		    UNREACHED;
247
		}
248
	    }
249
	}
250
    }
251
    for (rule = rule_list_head (&root_list); rule;
252
	 rule = rule_next_in_root_list (rule)) {
253
	rule_reinit_reverse_list (rule);
254
    }
255
}
256
 
257
static void
258
write_grammar_1 PROTO_N ((entry, gclosure))
259
		PROTO_T (EntryP   entry X
260
			 GenericP gclosure)
261
{
262
    OStreamP ostream = (OStreamP) gclosure;
263
 
264
    if (entry_is_rule (entry)) {
265
	write_rule (ostream, entry_get_rule (entry));
266
	write_newline (ostream);
267
    }
268
}
269
 
270
/*--------------------------------------------------------------------------*/
271
 
272
void
273
grammar_init PROTO_N ((grammar))
274
	     PROTO_T (GrammarP grammar)
275
{
276
    TableP table = grammar_table (grammar);
277
 
278
    table_init (table);
279
    entry_list_init (grammar_entry_list (grammar));
280
    grammar->terminal       = 0;
281
    grammar->predicate_type = NIL (EntryP);
282
    grammar->predicate_id   = table_add_generated_name (table);
283
}
284
 
285
#ifdef FS_FAST
286
#undef grammar_table
287
#endif /* defined (FS_FAST) */
288
TableP
289
grammar_table PROTO_N ((grammar))
290
	      PROTO_T (GrammarP grammar)
291
{
292
    return (&(grammar->table));
293
}
294
#ifdef FS_FAST
295
#define grammar_table(g) (&((g)->table))
296
#endif /* defined (FS_FAST) */
297
 
298
#ifdef FS_FAST
299
#undef grammar_entry_list
300
#endif /* defined (FS_FAST) */
301
EntryListP
302
grammar_entry_list PROTO_N ((grammar))
303
		   PROTO_T (GrammarP grammar)
304
{
305
    return (&(grammar->entry_list));
306
}
307
#ifdef FS_FAST
308
#define grammar_entry_list(g) (&((g)->entry_list))
309
#endif /* defined (FS_FAST) */
310
 
311
#ifdef FS_FAST
312
#undef grammar_max_terminal
313
#endif /* defined (FS_FAST) */
314
unsigned
315
grammar_max_terminal PROTO_N ((grammar))
316
		     PROTO_T (GrammarP grammar)
317
{
318
    return (grammar->terminal);
319
}
320
#ifdef FS_FAST
321
#define grammar_max_terminal(g) ((g)->terminal)
322
#endif /* defined (FS_FAST) */
323
 
324
unsigned
325
grammar_next_terminal PROTO_N ((grammar))
326
		      PROTO_T (GrammarP grammar)
327
{
328
    if (grammar->terminal == UINT_MAX) {
329
	E_too_many_terminals ();
330
	UNREACHED;
331
    }
332
    return (grammar->terminal ++);
333
}
334
 
335
#ifdef FS_FAST
336
#undef grammar_get_predicate_type
337
#endif /* defined (FS_FAST) */
338
EntryP
339
grammar_get_predicate_type PROTO_N ((grammar))
340
			   PROTO_T (GrammarP grammar)
341
{
342
    return (grammar->predicate_type);
343
}
344
#ifdef FS_FAST
345
#define grammar_get_predicate_type(g) ((g)->predicate_type)
346
#endif /* defined (FS_FAST) */
347
 
348
#ifdef FS_FAST
349
#undef grammar_set_predicate_type
350
#endif /* defined (FS_FAST) */
351
void
352
grammar_set_predicate_type PROTO_N ((grammar, type))
353
			   PROTO_T (GrammarP grammar X
354
				    EntryP   type)
355
{
356
    grammar->predicate_type = type;
357
}
358
#ifdef FS_FAST
359
#define grammar_set_predicate_type(g, t) ((g)->predicate_type = (t))
360
#endif /* defined (FS_FAST) */
361
 
362
#ifdef FS_FAST
363
#undef grammar_get_predicate_id
364
#endif /* defined (FS_FAST) */
365
EntryP
366
grammar_get_predicate_id PROTO_N ((grammar))
367
			 PROTO_T (GrammarP grammar)
368
{
369
    return (grammar->predicate_id);
370
}
371
#ifdef FS_FAST
372
#define grammar_get_predicate_id(g) ((g)->predicate_id)
373
#endif /* defined (FS_FAST) */
374
 
375
void
376
grammar_check_complete PROTO_N ((grammar))
377
		       PROTO_T (GrammarP grammar)
378
{
379
    TableP     table      = grammar_table (grammar);
380
    EntryListP entry_list = grammar_entry_list (grammar);
381
 
382
    table_untrace (table);
383
    entry_list_iter_table (entry_list, TRUE,
384
			   NIL (void (*) PROTO_S ((EntryP, GenericP))),
385
			   NIL (GenericP));
386
    table_iter (table, grammar_trace_ignored, NIL (GenericP));
387
    table_iter (table, grammar_check_1, NIL (GenericP));
388
}
389
 
390
void
391
grammar_remove_left_recursion PROTO_N ((grammar))
392
			      PROTO_T (GrammarP grammar)
393
{
394
    grammar_find_cycles (grammar, CT_LEFT);
395
}
396
 
397
void
398
grammar_compute_first_sets PROTO_N ((grammar))
399
			   PROTO_T (GrammarP grammar)
400
{
401
    TableP table = grammar_table (grammar);
402
 
403
    table_iter (table, rule_compute_first_set, NIL (GenericP));
404
}
405
 
406
void
407
grammar_factor PROTO_N ((grammar))
408
	       PROTO_T (GrammarP grammar)
409
{
410
    TableP         table      = grammar_table (grammar);
411
    EntryListP     entry_list = grammar_entry_list (grammar);
412
    FactorClosureT closure;
413
 
414
    bitvec_init (&(closure.bitvec1));
415
    bitvec_init (&(closure.bitvec2));
416
    closure.table        = table;
417
    closure.predicate_id = grammar_get_predicate_id (grammar);
418
    table_untrace (table);
419
    entry_list_iter_table (entry_list, FALSE, rule_factor,
420
			   (GenericP) &closure);
421
    table_unlink_untraced_rules (table);
422
    bitvec_destroy (&(closure.bitvec1));
423
    bitvec_destroy (&(closure.bitvec2));
424
}
425
 
426
void
427
grammar_simplify PROTO_N ((grammar))
428
		 PROTO_T (GrammarP grammar)
429
{
430
    TableP       table        = grammar_table (grammar);
431
    EntryListP   entry_list   = grammar_entry_list (grammar);
432
    EntryP       predicate_id = grammar_get_predicate_id (grammar);
433
 
434
    rule_remove_duplicates (table, predicate_id);
435
    table_untrace (table);
436
    entry_list_iter_table (entry_list, FALSE,
437
			   NIL (void (*) PROTO_S ((EntryP, GenericP))),
438
			   NIL (GenericP));
439
    table_unlink_untraced_rules (table);
440
}
441
 
442
void
443
grammar_compute_inlining PROTO_N ((grammar))
444
			 PROTO_T (GrammarP grammar)
445
{
446
    TableP     table         = grammar_table (grammar);
447
 
448
    if (rule_get_inline_tail_calls ()) {
449
	grammar_find_cycles (grammar, CT_TAIL);
450
    }
451
    table_iter (table, rule_compute_all_basics, NIL (GenericP));
452
    table_iter (table, rule_compute_inlining, NIL (GenericP));
453
    table_iter (table, rule_compute_needed_functions, NIL (GenericP));
454
    grammar_find_cycles (grammar, CT_ALL);
455
}
456
 
457
void
458
grammar_check_collisions PROTO_N ((grammar))
459
			 PROTO_T (GrammarP grammar)
460
{
461
    TableP table = grammar_table (grammar);
462
 
463
    table_iter (table, rule_check_first_set, (GenericP) grammar);
464
    table_iter (table, rule_compute_follow_set, (GenericP) grammar);
465
    table_iter (table, rule_compute_see_through_alt, NIL (GenericP));
466
    table_iter (table, rule_compute_alt_first_sets, NIL (GenericP));
467
}
468
 
469
void
470
grammar_recompute_alt_names PROTO_N ((grammar))
471
			    PROTO_T (GrammarP grammar)
472
{
473
    TableP table        = grammar_table (grammar);
474
    EntryP predicate_id = grammar_get_predicate_id (grammar);
475
 
476
    table_iter (table, rule_recompute_alt_names, (GenericP) predicate_id);
477
}
478
 
479
void
480
grammar_compute_mutations PROTO_N ((grammar))
481
			  PROTO_T (GrammarP grammar)
482
{
483
    TableP    table = grammar_table (grammar);
484
    RuleListT root_list;
485
    RuleP     rule;
486
 
487
    rule_list_init (&root_list);
488
    table_iter (table, rule_build_root_list, (GenericP) &root_list);
489
    rule_list_terminate (&root_list);
490
    for (rule = rule_list_head (&root_list); rule;
491
	 rule = rule_next_in_root_list (rule)) {
492
	rule_compute_reverse_list (rule, CT_MUTATE);
493
    }
494
    table_iter (table, rule_compute_mutations, NIL (GenericP));
495
    for (rule = rule_list_head (&root_list); rule;
496
	 rule = rule_next_in_root_list (rule)) {
497
	rule_reinit_reverse_list (rule);
498
    }    
499
}
500
 
501
void
502
write_grammar PROTO_N ((ostream, grammar))
503
	      PROTO_T (OStreamP ostream X
504
		       GrammarP grammar)
505
{
506
    TableP     table      = grammar_table (grammar);
507
    EntryListP entry_list = grammar_entry_list (grammar);
508
 
509
    table_untrace (table);
510
    entry_list_iter_table (entry_list, FALSE, write_grammar_1,
511
			   (GenericP) ostream);
512
}
513
 
514
/*
515
 * Local variables(smf):
516
 * eval: (include::add-path-entry "../os-interface" "../library")
517
 * eval: (include::add-path-entry "../generated")
518
 * end:
519
**/