Subversion Repositories tendra.SVN

Rev

Rev 5 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
6 7u83 2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
6 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
6 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
6 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
6 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
6 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
/*** rule-check.c --- Checks for grammar validity.
62
 *
63
 ** Author: Steve Folkes <smf@hermes.mod.uk>
64
 *
65
 *** Commentary:
66
 *
67
 * This file implements the routines that check to see if the grammar is
68
 * valid.  There are for checks that are made:
69
 *
70
 *	- The first sets of all alternatives in a rule are checked to ensure
71
 *	that they are disjoint (this includes the predicate first sets).  This
72
 *	also includes checking that there is only one see through alternative.
73
 *
74
 *	- The follow set of each rule is computed, and checked to ensure that
75
 *	if the rule is see through, its follow set does not intersect with its
76
 *	first set (this includes predicate follow and first sets).
77
 *
78
 *	- If there is a see through alternative, this is computed.
79
 *
80
 *	- The first set of each alternative is computed.
81
 *
82
 *** Change Log:
83
 * $Log: rule-check.c,v $
84
 * Revision 1.1.1.1  1998/01/17  15:57:46  release
85
 * First version to be checked into rolling release.
86
 *
87
 * Revision 1.3  1994/12/15  09:58:35  smf
88
 * Brought into line with OSSG C Coding Standards Document, as per
89
 * "CR94_178.sid+tld-update".
90
 *
91
 * Revision 1.2  1994/08/22  09:37:22  smf
92
 * Fixed bug DR114:ids-too-long.
93
 *
94
 * Revision 1.1.1.1  1994/07/25  16:04:38  smf
95
 * Initial import of SID 1.8 non shared files.
96
 *
97
**/
98
 
99
/****************************************************************************/
100
 
101
#include "rule.h"
102
#include "basic.h"
103
#include "bitvec.h"
104
#include "gen-errors.h"
105
 
106
/*--------------------------------------------------------------------------*/
107
 
108
static void
6 7u83 109
rule_check_first_set_1(RuleP rule, GrammarP grammar)
2 7u83 110
{
6 7u83 111
    BoolT         is_empty            = rule_has_empty_alt(rule);
2 7u83 112
    BoolT         is_empty_mesg_shown = FALSE;
113
    BitVecT       test;
114
    EntryListT    predicate_list;
115
    AltP          alt;
116
    BasicClosureT closure;
117
 
118
    closure.grammar = grammar;
6 7u83 119
    bitvec_init(&test);
120
    entry_list_init(&predicate_list);
121
    for (alt = rule_alt_head(rule); alt; alt = alt_next(alt)) {
122
	ItemP item        = alt_item_head(alt);
2 7u83 123
	ItemP initial     = item;
124
	BoolT see_through = TRUE;
125
 
6 7u83 126
	for (; see_through && item; item = item_next(item)) {
127
	    EntryP entry = item_entry(item);
2 7u83 128
 
6 7u83 129
	    switch (item_type(item))EXHAUSTIVE {
2 7u83 130
	      case ET_PREDICATE:
6 7u83 131
		ASSERT(item == initial);
132
		if (entry_list_contains(&predicate_list, entry)) {
133
		    E_predicate_collision(rule, entry_key(entry));
2 7u83 134
		} else {
6 7u83 135
		    entry_list_add(&predicate_list, entry);
2 7u83 136
		}
137
		see_through = FALSE;
138
		break;
139
	      case ET_ACTION:
140
	      case ET_RENAME:
141
		break;
142
	      case ET_BASIC: {
6 7u83 143
		  unsigned terminal = basic_terminal(entry_get_basic(entry));
2 7u83 144
 
145
		  see_through = FALSE;
6 7u83 146
		  if (bitvec_is_set(&test, terminal)) {
2 7u83 147
		      BitVecT tmp;
148
 
6 7u83 149
		      bitvec_init(&tmp);
150
		      bitvec_set(&tmp, terminal);
151
		      bitvec_and(&tmp, &test);
2 7u83 152
		      closure.bitvec = &tmp;
6 7u83 153
		      E_first_set_collision(rule, &closure);
154
		      bitvec_destroy(&tmp);
2 7u83 155
		  } else {
6 7u83 156
		      bitvec_set(&test, terminal);
2 7u83 157
		  }
158
	      }
159
		break;
160
	      case ET_RULE: {
6 7u83 161
		  RuleP      item_rule  = entry_get_rule(entry);
162
		  EntryListP item_preds = rule_predicate_first(item_rule);
2 7u83 163
		  EntryListT tmp_list;
164
		  BitVecP    bitvec;
165
 
6 7u83 166
		  entry_list_intersection(&tmp_list, &predicate_list,
167
					  item_preds);
168
		  if (!entry_list_is_empty(&tmp_list)) {
169
		      E_predicate_list_collision(rule, &tmp_list);
2 7u83 170
		  }
6 7u83 171
		  entry_list_destroy(&tmp_list);
172
		  entry_list_append(&predicate_list, item_preds);
173
		  bitvec      = rule_first_set(item_rule);
174
		  see_through = rule_is_see_through(item_rule);
175
		  if (bitvec_intersects(&test, bitvec)) {
2 7u83 176
		      BitVecT tmp;
177
 
6 7u83 178
		      bitvec_copy(&tmp, bitvec);
179
		      bitvec_and(&tmp, &test);
2 7u83 180
		      closure.bitvec = &tmp;
6 7u83 181
		      E_first_set_collision(rule, &closure);
182
		      bitvec_destroy(&tmp);
2 7u83 183
		  } else {
6 7u83 184
		      bitvec_or(&test, bitvec);
2 7u83 185
		  }
186
	      }
187
		break;
188
	      case ET_NON_LOCAL:
189
	      case ET_TYPE:
190
	      case ET_NAME:
191
		UNREACHED;
192
	    }
193
	}
194
	if (see_through) {
195
	    if (is_empty) {
196
		if (!is_empty_mesg_shown) {
6 7u83 197
		    E_multiple_see_through_alts(rule);
2 7u83 198
		    is_empty_mesg_shown = TRUE;
199
		}
200
	    } else {
201
		is_empty = TRUE;
202
	    }
203
	}
204
    }
6 7u83 205
    bitvec_destroy(&test);
2 7u83 206
}
207
 
6 7u83 208
static void rule_compute_follow_set_1(RuleP, GrammarP, BitVecP, EntryListP,
209
				      ClashListP);
2 7u83 210
 
211
static void
6 7u83 212
rule_compute_follow_set_3(GrammarP grammar, ItemP item, BitVecP context,
213
			  EntryListP pred_context, ClashListP clashes)
2 7u83 214
{
6 7u83 215
    if (item != NIL(ItemP)) {
2 7u83 216
	EntryP entry;
217
 
6 7u83 218
	rule_compute_follow_set_3(grammar, item_next(item), context,
219
				  pred_context, clashes);
220
	entry = item_entry(item);
221
	switch (item_type(item))EXHAUSTIVE {
2 7u83 222
	  case ET_PREDICATE:
6 7u83 223
	    entry_list_destroy(pred_context);
224
	    entry_list_init(pred_context);
225
	    entry_list_add(pred_context, entry);
226
	    clashes->next = NIL(ClashListP);
2 7u83 227
	    break;
228
	  case ET_ACTION:
229
	  case ET_RENAME:
230
	    break;
231
	  case ET_RULE: {
6 7u83 232
	      RuleP rule = entry_get_rule(entry);
2 7u83 233
 
234
	      clashes->item = item;
6 7u83 235
	      rule_compute_follow_set_1(rule, grammar, context, pred_context,
236
					clashes);
237
	      if (rule_is_see_through(rule)) {
238
		  bitvec_or(context, rule_first_set(rule));
239
		  entry_list_append(pred_context, rule_predicate_first(rule));
2 7u83 240
	      } else {
6 7u83 241
		  bitvec_replace(context, rule_first_set(rule));
242
		  entry_list_destroy(pred_context);
243
		  entry_list_init(pred_context);
244
		  entry_list_append(pred_context, rule_predicate_first(rule));
245
		  clashes->next = NIL(ClashListP);
2 7u83 246
	      }
247
	  }
248
	    break;
249
	  case ET_BASIC: {
6 7u83 250
	      BasicP basic = entry_get_basic(entry);
2 7u83 251
 
6 7u83 252
	      bitvec_empty(context);
253
	      bitvec_set(context, basic_terminal(basic));
254
	      clashes->next = NIL(ClashListP);
2 7u83 255
	  }
256
	    break;
257
	  case ET_NON_LOCAL:
258
	  case ET_NAME:
259
	  case ET_TYPE:
260
	    UNREACHED;
261
	}
262
    }
263
}
264
 
265
static void
6 7u83 266
rule_compute_follow_set_2(RuleP rule, GrammarP grammar, AltP alt,
267
			  BitVecP context, EntryListP pred_context,
268
			  ClashListP clashes)
2 7u83 269
{
270
    BitVecT    tmp;
271
    EntryListT tmp_list;
272
    ClashListT clash;
273
 
274
    clash.next = clashes;
275
    clash.rule = rule;
276
    clash.alt  = alt;
6 7u83 277
    bitvec_copy(&tmp, context);
278
    entry_list_copy(&tmp_list, pred_context);
279
    rule_compute_follow_set_3(grammar, alt_item_head(alt), &tmp, &tmp_list,
280
			      &clash);
281
    bitvec_destroy(&tmp);
282
    entry_list_destroy(&tmp_list);
2 7u83 283
}
284
 
285
static void
6 7u83 286
rule_compute_follow_set_1(RuleP rule, GrammarP grammar, BitVecP context,
287
			  EntryListP pred_context, ClashListP clashes)
2 7u83 288
{
6 7u83 289
    BitVecP       follow      = rule_follow_set(rule);
290
    EntryListP    pred_follow = rule_predicate_follow(rule);
291
    BitVecP       first       = rule_first_set(rule);
292
    EntryListP    pred_first  = rule_predicate_first(rule);
2 7u83 293
    BitVecT       test;
294
    AltP          alt;
295
    BasicClosureT closure;
296
 
6 7u83 297
    if (rule_has_started_follows(rule)) {
298
	bitvec_copy(&test, follow);
299
	bitvec_or(follow, context);
300
	if (bitvec_equal(&test, follow) &&
301
	    entry_list_includes(pred_follow, pred_context)) {
302
	    bitvec_destroy(&test);
2 7u83 303
	    return;
304
	}
6 7u83 305
	entry_list_append(pred_follow, pred_context);
306
	bitvec_destroy(&test);
2 7u83 307
    } else {
6 7u83 308
	bitvec_replace(follow, context);
309
	entry_list_append(pred_follow, pred_context);
310
	rule_started_follows(rule);
2 7u83 311
    }
312
    closure.grammar = grammar;
6 7u83 313
    if (rule_is_see_through(rule)) {
2 7u83 314
	EntryListT tmp_list;
315
 
6 7u83 316
	if (bitvec_intersects(follow, first)) {
317
	    bitvec_copy(&test, follow);
318
	    bitvec_and(&test, first);
2 7u83 319
	    closure.bitvec = &test;
6 7u83 320
	    E_follow_set_collision(rule, &closure, clashes);
321
	    bitvec_not(&test);
322
	    bitvec_and(first, &test);
323
	    bitvec_destroy(&test);
2 7u83 324
	}
6 7u83 325
	entry_list_intersection(&tmp_list, pred_follow, pred_first);
326
	if (!entry_list_is_empty(&tmp_list)) {
327
	    E_predicate_follow_set_coll(rule, &tmp_list, clashes);
328
	    entry_list_unlink_used(pred_first, &tmp_list);
2 7u83 329
	}
6 7u83 330
	entry_list_destroy(&tmp_list);
2 7u83 331
    }
6 7u83 332
    if ((alt = rule_get_handler(rule)) != NIL(AltP)) {
333
	rule_compute_follow_set_2(rule, grammar, alt, follow, pred_follow,
2 7u83 334
				   clashes);
335
    }
6 7u83 336
    for (alt = rule_alt_head(rule); alt; alt = alt_next(alt)) {
337
	rule_compute_follow_set_2(rule, grammar, alt, follow, pred_follow,
338
				  clashes);
2 7u83 339
    }
340
}
341
 
342
static void
6 7u83 343
rule_compute_see_through_alt_1(RuleP rule)
2 7u83 344
{
6 7u83 345
    if (!rule_has_empty_alt(rule)) {
2 7u83 346
	AltP alt;
347
 
6 7u83 348
	for (alt = rule_alt_head(rule); alt; alt = alt_next(alt)) {
2 7u83 349
	    ItemP item;
350
 
6 7u83 351
	    for (item = alt_item_head(alt); item; item = item_next(item)) {
2 7u83 352
		RuleP item_rule;
353
 
6 7u83 354
		if ((!item_is_action(item)) && (!item_is_rename(item)) &&
355
		    ((!item_is_rule(item)) ||
356
		     ((item_rule = entry_get_rule(item_entry(item))),
357
		      (!rule_is_see_through(item_rule))))) {
2 7u83 358
		    goto next_alt;
359
		}
360
	    }
6 7u83 361
	    rule_set_see_through_alt(rule, alt);
2 7u83 362
	    return;
363
	  next_alt:;
364
	}
365
    }
366
}
367
 
368
static void
6 7u83 369
rule_compute_alt_first_sets_1(RuleP rule)
2 7u83 370
{
371
    AltP alt;
372
 
6 7u83 373
    for (alt = rule_alt_head(rule); alt; alt = alt_next(alt)) {
374
	BitVecP alt_firsts  = alt_first_set(alt);
375
	ItemP   item        = alt_item_head(alt);
2 7u83 376
	ItemP   initial     = item;
377
	BoolT   see_through = TRUE;
378
 
6 7u83 379
	for (; see_through && item; item = item_next(item)) {
380
	    EntryP entry = item_entry(item);
2 7u83 381
 
6 7u83 382
	    switch (item_type(item))EXHAUSTIVE {
2 7u83 383
	      case ET_PREDICATE:
6 7u83 384
		ASSERT(item == initial);
2 7u83 385
		see_through = FALSE;
386
		break;
387
	      case ET_ACTION:
388
	      case ET_RENAME:
389
		break;
390
	      case ET_BASIC:
391
		see_through = FALSE;
6 7u83 392
		bitvec_set(alt_firsts, basic_terminal(entry_get_basic(entry)));
2 7u83 393
		break;
394
	      case ET_RULE: {
6 7u83 395
		  RuleP item_rule = entry_get_rule(entry);
2 7u83 396
 
6 7u83 397
		  see_through = rule_is_see_through(item_rule);
398
		  bitvec_or(alt_firsts, rule_first_set(item_rule));
2 7u83 399
	      }
400
		break;
401
	      case ET_NON_LOCAL:
402
	      case ET_TYPE:
403
	      case ET_NAME:
404
		UNREACHED;
405
	    }
406
	}
407
	if (see_through) {
6 7u83 408
	    bitvec_or(alt_firsts, rule_follow_set(rule));
2 7u83 409
	}
410
    }
411
}
412
 
413
/*--------------------------------------------------------------------------*/
414
 
415
void
6 7u83 416
rule_check_first_set(EntryP entry, GenericP gclosure)
2 7u83 417
{
6 7u83 418
    GrammarP grammar = (GrammarP)gclosure;
2 7u83 419
 
6 7u83 420
    if (entry_is_rule(entry)) {
421
	RuleP rule = entry_get_rule(entry);
2 7u83 422
 
6 7u83 423
	rule_check_first_set_1(rule, grammar);
2 7u83 424
    }
425
}
426
 
427
void
6 7u83 428
rule_compute_follow_set(EntryP entry, GenericP gclosure)
2 7u83 429
{
6 7u83 430
    GrammarP grammar = (GrammarP)gclosure;
2 7u83 431
 
6 7u83 432
    if (entry_is_rule(entry)) {
433
	RuleP   rule = entry_get_rule(entry);
2 7u83 434
	BitVecT    outer;
435
	EntryListT pred_outer;
436
 
6 7u83 437
	bitvec_init(&outer);
438
	entry_list_init(&pred_outer);
439
	rule_compute_follow_set_1(rule, grammar, &outer, &pred_outer,
440
				  NIL(ClashListP));
441
	bitvec_destroy(&outer);
442
	entry_list_destroy(&pred_outer);
2 7u83 443
    }
444
}
445
 
446
void
6 7u83 447
rule_compute_see_through_alt(EntryP entry, GenericP gclosure)
2 7u83 448
{
6 7u83 449
    UNUSED(gclosure);
450
    if (entry_is_rule(entry)) {
451
	RuleP rule = entry_get_rule(entry);
2 7u83 452
 
6 7u83 453
	rule_compute_see_through_alt_1(rule);
2 7u83 454
    }
455
}
456
 
457
void
6 7u83 458
rule_compute_alt_first_sets(EntryP entry, GenericP gclosure)
2 7u83 459
{
6 7u83 460
    UNUSED(gclosure);
461
    if (entry_is_rule(entry)) {
462
	RuleP rule = entry_get_rule(entry);
2 7u83 463
 
6 7u83 464
	rule_compute_alt_first_sets_1(rule);
2 7u83 465
    }
466
}
467
 
468
void
6 7u83 469
write_clashes(OStreamP ostream, ClashListP clashes)
2 7u83 470
{
6 7u83 471
    write_newline(ostream);
2 7u83 472
    while (clashes) {
6 7u83 473
	write_rule_lhs(ostream, clashes->rule);
474
	write_alt_highlighting(ostream, clashes->alt, clashes->item);
475
	write_cstring(ostream, "};");
476
	write_newline(ostream);
2 7u83 477
	clashes = clashes->next;
478
    }
479
}
480
 
481
/*
482
 * Local variables(smf):
483
 * eval: (include::add-path-entry "../os-interface" "../library")
484
 * eval: (include::add-path-entry "../generated")
485
 * end:
486
**/