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
/*** rule-check.c --- Checks for grammar validity.
32
 *
33
 ** Author: Steve Folkes <smf@hermes.mod.uk>
34
 *
35
 *** Commentary:
36
 *
37
 * This file implements the routines that check to see if the grammar is
38
 * valid.  There are for checks that are made:
39
 *
40
 *	- The first sets of all alternatives in a rule are checked to ensure
41
 *	that they are disjoint (this includes the predicate first sets).  This
42
 *	also includes checking that there is only one see through alternative.
43
 *
44
 *	- The follow set of each rule is computed, and checked to ensure that
45
 *	if the rule is see through, its follow set does not intersect with its
46
 *	first set (this includes predicate follow and first sets).
47
 *
48
 *	- If there is a see through alternative, this is computed.
49
 *
50
 *	- The first set of each alternative is computed.
51
 *
52
 *** Change Log:
53
 * $Log: rule-check.c,v $
54
 * Revision 1.1.1.1  1998/01/17  15:57:46  release
55
 * First version to be checked into rolling release.
56
 *
57
 * Revision 1.3  1994/12/15  09:58:35  smf
58
 * Brought into line with OSSG C Coding Standards Document, as per
59
 * "CR94_178.sid+tld-update".
60
 *
61
 * Revision 1.2  1994/08/22  09:37:22  smf
62
 * Fixed bug DR114:ids-too-long.
63
 *
64
 * Revision 1.1.1.1  1994/07/25  16:04:38  smf
65
 * Initial import of SID 1.8 non shared files.
66
 *
67
**/
68
 
69
/****************************************************************************/
70
 
71
#include "rule.h"
72
#include "basic.h"
73
#include "bitvec.h"
74
#include "gen-errors.h"
75
 
76
/*--------------------------------------------------------------------------*/
77
 
78
static void
79
rule_check_first_set_1 PROTO_N ((rule, grammar))
80
		       PROTO_T (RuleP    rule X
81
				GrammarP grammar)
82
{
83
    BoolT         is_empty            = rule_has_empty_alt (rule);
84
    BoolT         is_empty_mesg_shown = FALSE;
85
    BitVecT       test;
86
    EntryListT    predicate_list;
87
    AltP          alt;
88
    BasicClosureT closure;
89
 
90
    closure.grammar = grammar;
91
    bitvec_init (&test);
92
    entry_list_init (&predicate_list);
93
    for (alt = rule_alt_head (rule); alt; alt = alt_next (alt)) {
94
	ItemP item        = alt_item_head (alt);
95
	ItemP initial     = item;
96
	BoolT see_through = TRUE;
97
 
98
	for (; see_through && item; item = item_next (item)) {
99
	    EntryP entry = item_entry (item);
100
 
101
	    switch (item_type (item)) EXHAUSTIVE {
102
	      case ET_PREDICATE:
103
		ASSERT (item == initial);
104
		if (entry_list_contains (&predicate_list, entry)) {
105
		    E_predicate_collision (rule, entry_key (entry));
106
		} else {
107
		    entry_list_add (&predicate_list, entry);
108
		}
109
		see_through = FALSE;
110
		break;
111
	      case ET_ACTION:
112
	      case ET_RENAME:
113
		break;
114
	      case ET_BASIC: {
115
		  unsigned terminal = basic_terminal (entry_get_basic (entry));
116
 
117
		  see_through = FALSE;
118
		  if (bitvec_is_set (&test, terminal)) {
119
		      BitVecT tmp;
120
 
121
		      bitvec_init (&tmp);
122
		      bitvec_set (&tmp, terminal);
123
		      bitvec_and (&tmp, &test);
124
		      closure.bitvec = &tmp;
125
		      E_first_set_collision (rule, &closure);
126
		      bitvec_destroy (&tmp);
127
		  } else {
128
		      bitvec_set (&test, terminal);
129
		  }
130
	      }
131
		break;
132
	      case ET_RULE: {
133
		  RuleP      item_rule  = entry_get_rule (entry);
134
		  EntryListP item_preds = rule_predicate_first (item_rule);
135
		  EntryListT tmp_list;
136
		  BitVecP    bitvec;
137
 
138
		  entry_list_intersection (&tmp_list, &predicate_list,
139
					   item_preds);
140
		  if (!entry_list_is_empty (&tmp_list)) {
141
		      E_predicate_list_collision (rule, &tmp_list);
142
		  }
143
		  entry_list_destroy (&tmp_list);
144
		  entry_list_append (&predicate_list, item_preds);
145
		  bitvec      = rule_first_set (item_rule);
146
		  see_through = rule_is_see_through (item_rule);
147
		  if (bitvec_intersects (&test, bitvec)) {
148
		      BitVecT tmp;
149
 
150
		      bitvec_copy (&tmp, bitvec);
151
		      bitvec_and (&tmp, &test);
152
		      closure.bitvec = &tmp;
153
		      E_first_set_collision (rule, &closure);
154
		      bitvec_destroy (&tmp);
155
		  } else {
156
		      bitvec_or (&test, bitvec);
157
		  }
158
	      }
159
		break;
160
	      case ET_NON_LOCAL:
161
	      case ET_TYPE:
162
	      case ET_NAME:
163
		UNREACHED;
164
	    }
165
	}
166
	if (see_through) {
167
	    if (is_empty) {
168
		if (!is_empty_mesg_shown) {
169
		    E_multiple_see_through_alts (rule);
170
		    is_empty_mesg_shown = TRUE;
171
		}
172
	    } else {
173
		is_empty = TRUE;
174
	    }
175
	}
176
    }
177
    bitvec_destroy (&test);
178
}
179
 
180
static void			rule_compute_follow_set_1
181
	PROTO_S ((RuleP, GrammarP, BitVecP, EntryListP, ClashListP));
182
 
183
static void
184
rule_compute_follow_set_3 PROTO_N ((grammar, item, context, pred_context,
185
				    clashes))
186
			  PROTO_T (GrammarP   grammar X
187
				   ItemP      item X
188
				   BitVecP    context X
189
				   EntryListP pred_context X
190
				   ClashListP clashes)
191
{
192
    if (item != NIL (ItemP)) {
193
	EntryP entry;
194
 
195
	rule_compute_follow_set_3 (grammar, item_next (item), context,
196
				   pred_context, clashes);
197
	entry = item_entry (item);
198
	switch (item_type (item)) EXHAUSTIVE {
199
	  case ET_PREDICATE:
200
	    entry_list_destroy (pred_context);
201
	    entry_list_init (pred_context);
202
	    entry_list_add (pred_context, entry);
203
	    clashes->next = NIL (ClashListP);
204
	    break;
205
	  case ET_ACTION:
206
	  case ET_RENAME:
207
	    break;
208
	  case ET_RULE: {
209
	      RuleP rule = entry_get_rule (entry);
210
 
211
	      clashes->item = item;
212
	      rule_compute_follow_set_1 (rule, grammar, context, pred_context,
213
					 clashes);
214
	      if (rule_is_see_through (rule)) {
215
		  bitvec_or (context, rule_first_set (rule));
216
		  entry_list_append (pred_context,
217
				     rule_predicate_first (rule));
218
	      } else {
219
		  bitvec_replace (context, rule_first_set (rule));
220
		  entry_list_destroy (pred_context);
221
		  entry_list_init (pred_context);
222
		  entry_list_append (pred_context,
223
				     rule_predicate_first (rule));
224
		  clashes->next = NIL (ClashListP);
225
	      }
226
	  }
227
	    break;
228
	  case ET_BASIC: {
229
	      BasicP basic = entry_get_basic (entry);
230
 
231
	      bitvec_empty (context);
232
	      bitvec_set (context, basic_terminal (basic));
233
	      clashes->next = NIL (ClashListP);
234
	  }
235
	    break;
236
	  case ET_NON_LOCAL:
237
	  case ET_NAME:
238
	  case ET_TYPE:
239
	    UNREACHED;
240
	}
241
    }
242
}
243
 
244
static void
245
rule_compute_follow_set_2 PROTO_N ((rule, grammar, alt, context, pred_context,
246
				    clashes))
247
			  PROTO_T (RuleP      rule X
248
				   GrammarP   grammar X
249
				   AltP       alt X
250
				   BitVecP    context X
251
				   EntryListP pred_context X
252
				   ClashListP clashes)
253
{
254
    BitVecT    tmp;
255
    EntryListT tmp_list;
256
    ClashListT clash;
257
 
258
    clash.next = clashes;
259
    clash.rule = rule;
260
    clash.alt  = alt;
261
    bitvec_copy (&tmp, context);
262
    entry_list_copy (&tmp_list, pred_context);
263
    rule_compute_follow_set_3 (grammar, alt_item_head (alt), &tmp, &tmp_list,
264
			       &clash);
265
    bitvec_destroy (&tmp);
266
    entry_list_destroy (&tmp_list);
267
}
268
 
269
static void
270
rule_compute_follow_set_1 PROTO_N ((rule, grammar, context, pred_context,
271
				    clashes))
272
			  PROTO_T (RuleP      rule X
273
				   GrammarP   grammar X
274
				   BitVecP    context X
275
				   EntryListP pred_context X
276
				   ClashListP clashes)
277
{
278
    BitVecP       follow      = rule_follow_set (rule);
279
    EntryListP    pred_follow = rule_predicate_follow (rule);
280
    BitVecP       first       = rule_first_set (rule);
281
    EntryListP    pred_first  = rule_predicate_first (rule);
282
    BitVecT       test;
283
    AltP          alt;
284
    BasicClosureT closure;
285
 
286
    if (rule_has_started_follows (rule)) {
287
	bitvec_copy (&test, follow);
288
	bitvec_or (follow, context);
289
	if (bitvec_equal (&test, follow) &&
290
	    entry_list_includes (pred_follow, pred_context)) {
291
	    bitvec_destroy (&test);
292
	    return;
293
	}
294
	entry_list_append (pred_follow, pred_context);
295
	bitvec_destroy (&test);
296
    } else {
297
	bitvec_replace (follow, context);
298
	entry_list_append (pred_follow, pred_context);
299
	rule_started_follows (rule);
300
    }
301
    closure.grammar = grammar;
302
    if (rule_is_see_through (rule)) {
303
	EntryListT tmp_list;
304
 
305
	if (bitvec_intersects (follow, first)) {
306
	    bitvec_copy (&test, follow);
307
	    bitvec_and (&test, first);
308
	    closure.bitvec = &test;
309
	    E_follow_set_collision (rule, &closure, clashes);
310
	    bitvec_not (&test);
311
	    bitvec_and (first, &test);
312
	    bitvec_destroy (&test);
313
	}
314
	entry_list_intersection (&tmp_list, pred_follow, pred_first);
315
	if (!entry_list_is_empty (&tmp_list)) {
316
	    E_predicate_follow_set_coll (rule, &tmp_list, clashes);
317
	    entry_list_unlink_used (pred_first, &tmp_list);
318
	}
319
	entry_list_destroy (&tmp_list);
320
    }
321
    if ((alt = rule_get_handler (rule)) != NIL (AltP)) {
322
	rule_compute_follow_set_2 (rule, grammar, alt, follow, pred_follow,
323
				   clashes);
324
    }
325
    for (alt = rule_alt_head (rule); alt; alt = alt_next (alt)) {
326
	rule_compute_follow_set_2 (rule, grammar, alt, follow, pred_follow,
327
				   clashes);
328
    }
329
}
330
 
331
static void
332
rule_compute_see_through_alt_1 PROTO_N ((rule))
333
			       PROTO_T (RuleP rule)
334
{
335
    if (!rule_has_empty_alt (rule)) {
336
	AltP alt;
337
 
338
	for (alt = rule_alt_head (rule); alt; alt = alt_next (alt)) {
339
	    ItemP item;
340
 
341
	    for (item = alt_item_head (alt); item; item = item_next (item)) {
342
		RuleP item_rule;
343
 
344
		if ((!item_is_action (item)) && (!item_is_rename (item)) &&
345
		    ((!item_is_rule (item)) ||
346
		     ((item_rule = entry_get_rule (item_entry (item))),
347
		      (!rule_is_see_through (item_rule))))) {
348
		    goto next_alt;
349
		}
350
	    }
351
	    rule_set_see_through_alt (rule, alt);
352
	    return;
353
	  next_alt:;
354
	}
355
    }
356
}
357
 
358
static void
359
rule_compute_alt_first_sets_1 PROTO_N ((rule))
360
			      PROTO_T (RuleP rule)
361
{
362
    AltP alt;
363
 
364
    for (alt = rule_alt_head (rule); alt; alt = alt_next (alt)) {
365
	BitVecP alt_firsts  = alt_first_set (alt);
366
	ItemP   item        = alt_item_head (alt);
367
	ItemP   initial     = item;
368
	BoolT   see_through = TRUE;
369
 
370
	for (; see_through && item; item = item_next (item)) {
371
	    EntryP entry = item_entry (item);
372
 
373
	    switch (item_type (item)) EXHAUSTIVE {
374
	      case ET_PREDICATE:
375
		ASSERT (item == initial);
376
		see_through = FALSE;
377
		break;
378
	      case ET_ACTION:
379
	      case ET_RENAME:
380
		break;
381
	      case ET_BASIC:
382
		see_through = FALSE;
383
		bitvec_set (alt_firsts,
384
			    basic_terminal (entry_get_basic (entry)));
385
		break;
386
	      case ET_RULE: {
387
		  RuleP item_rule = entry_get_rule (entry);
388
 
389
		  see_through = rule_is_see_through (item_rule);
390
		  bitvec_or (alt_firsts, rule_first_set (item_rule));
391
	      }
392
		break;
393
	      case ET_NON_LOCAL:
394
	      case ET_TYPE:
395
	      case ET_NAME:
396
		UNREACHED;
397
	    }
398
	}
399
	if (see_through) {
400
	    bitvec_or (alt_firsts, rule_follow_set (rule));
401
	}
402
    }
403
}
404
 
405
/*--------------------------------------------------------------------------*/
406
 
407
void
408
rule_check_first_set PROTO_N ((entry, gclosure))
409
		     PROTO_T (EntryP   entry X
410
			      GenericP gclosure)
411
{
412
    GrammarP grammar = (GrammarP) gclosure;
413
 
414
    if (entry_is_rule (entry)) {
415
	RuleP rule = entry_get_rule (entry);
416
 
417
	rule_check_first_set_1 (rule, grammar);
418
    }
419
}
420
 
421
void
422
rule_compute_follow_set PROTO_N ((entry, gclosure))
423
			PROTO_T (EntryP   entry X
424
				 GenericP gclosure)
425
{
426
    GrammarP grammar = (GrammarP) gclosure;
427
 
428
    if (entry_is_rule (entry)) {
429
	RuleP   rule = entry_get_rule (entry);
430
	BitVecT    outer;
431
	EntryListT pred_outer;
432
 
433
	bitvec_init (&outer);
434
	entry_list_init (&pred_outer);
435
	rule_compute_follow_set_1 (rule, grammar, &outer, &pred_outer,
436
				   NIL (ClashListP));
437
	bitvec_destroy (&outer);
438
	entry_list_destroy (&pred_outer);
439
    }
440
}
441
 
442
void
443
rule_compute_see_through_alt PROTO_N ((entry, gclosure))
444
			     PROTO_T (EntryP   entry X
445
				      GenericP gclosure)
446
{
447
    UNUSED (gclosure);
448
    if (entry_is_rule (entry)) {
449
	RuleP rule = entry_get_rule (entry);
450
 
451
	rule_compute_see_through_alt_1 (rule);
452
    }
453
}
454
 
455
void
456
rule_compute_alt_first_sets PROTO_N ((entry, gclosure))
457
			    PROTO_T (EntryP   entry X
458
				     GenericP gclosure)
459
{
460
    UNUSED (gclosure);
461
    if (entry_is_rule (entry)) {
462
	RuleP rule = entry_get_rule (entry);
463
 
464
	rule_compute_alt_first_sets_1 (rule);
465
    }
466
}
467
 
468
void
469
write_clashes PROTO_N ((ostream, clashes))
470
	      PROTO_T (OStreamP   ostream X
471
		       ClashListP clashes)
472
{
473
    write_newline (ostream);
474
    while (clashes) {
475
	write_rule_lhs (ostream, clashes->rule);
476
	write_alt_highlighting (ostream, clashes->alt, clashes->item);
477
	write_cstring (ostream, "};");
478
	write_newline (ostream);
479
	clashes = clashes->next;
480
    }
481
}
482
 
483
/*
484
 * Local variables(smf):
485
 * eval: (include::add-path-entry "../os-interface" "../library")
486
 * eval: (include::add-path-entry "../generated")
487
 * end:
488
**/