Subversion Repositories tendra.SVN

Rev

Rev 2 | Go to most recent revision | Details | Compare with Previous | 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-factor.c --- Factorisation of rules.
32
 *
33
 ** Author: Steve Folkes <smf@hermes.mod.uk>
34
 *
35
 *** Commentary:
36
 *
37
 * This file implements the SID factorisation routines.
38
 *
39
 * The factorisation process consists of the following phases:
40
 *
41
 * 1. The rule is reordered so that alternatives with the same initial item
42
 * are grouped together, for example the rule:
43
 *
44
 * 	A = x A,
45
 * 	    x B,
46
 * 	    y A,
47
 * 	    z A,
48
 * 	    y B;
49
 *
50
 * would be reordered to:
51
 *
52
 * 	A = x A,
53
 * 	    x B,
54
 * 	    y A,
55
 * 	    y B,
56
 * 	    z A;
57
 *
58
 * and three groups would have been created:
59
 *
60
 * 	x A, x B
61
 *
62
 * 	y A, y B
63
 *
64
 * 	z A
65
 *
66
 * Each group has its first set calculated (this is the union of the first
67
 * sets of each of the alternatives in the group), and its priority.  The
68
 * priority of a group is one more than the priority of the rule with the
69
 * highest priority in any of the group's alternatives, which is not preceded
70
 * by an action.  If there is no such rule, then the group's priority is one.
71
 *
72
 * The ``rule_group_by_initial_item'' function is responsible for this
73
 * re-ordering.  It uses the rule's alternative tail pointer (``alt_tail'') to
74
 * indicate where in the rule it should start the grouping from.  Nothing
75
 * before this point is modified (it is assumed that it is already grouped).
76
 * The pointer will always be restored to the end of the alternative list by
77
 * the time this function returns.
78
 *
79
 * 2. Having split the rule up into groups, it then looks at each group to see
80
 * if there are alternatives of the form:
81
 *
82
 * 	B C ...
83
 *
84
 * where "B" is a see through rule, and the first set of "B" contains some
85
 * terminals from the first set of "C ...".  If it finds any, it removes the
86
 * group from the rule, and expands "B" in all alternatives in the group,
87
 * putting the new alternatives at the end of the rule.  It also looks for
88
 * alternatives that begin with a rule which has a predicate in its first set,
89
 * in which case it also expands the rule in all alternatives in the group.
90
 * It then recomputes the groups for the new alternatives, and tries again.
91
 * This phase and the next phase are implemented by the function
92
 * ``rule_expand_item_clashes''.  It is not possible to expand a rule that has
93
 * an exception handler into another rule that has an exception handler
94
 * (unless the exception handlers are identical).
95
 *
96
 * 3. The next phase is to check to see if any of the groups have common
97
 * terminals in their first sets.  If this is the case (and the first item in
98
 * each alternative in at least one of the groups is a rule), then the group
99
 * with the highest priority is removed from the rule, and the first item is
100
 * expanded in all alternatives in the group, putting the new alternatives at
101
 * the end of the rule.  It then recalculates the groups for the new
102
 * alternatives, and tries again.
103
 *
104
 * 4. The last stage is to change a group of the form:
105
 *
106
 * 	  B C
107
 * 	| B D
108
 *
109
 * into
110
 *
111
 * 	  B X
112
 *
113
 * 	X = C
114
 * 	  | D
115
 *
116
 * where "X" is a newly created rule.  The algorithm actually removes all
117
 * initial items that are the same for all members of the group.  It also
118
 * performs renaming of the result names of the final item in the group of
119
 * identical items if necessary.
120
 * 
121
 * It is possible that this final stage of the factorization process will go
122
 * on forever.  To prevent this, there is a limit on the number of new rules
123
 * that can be created.  This stage of the factorisation process is
124
 * implemented by the functions ``rule_factor_2'', ``rule_factor_3'', and
125
 * ``rule_factor_4''.
126
 *
127
 * When the new rule is created, the ``rule_compute_first_set_1'' function is
128
 * called to calculate its first set, whether or not it is see through and its
129
 * priority.  The new rules are created untraced, to ensure that the
130
 * factorisation process will be applied to them as well.
131
 *
132
 *** Change Log:
133
 * $Log: rule-factor.c,v $
134
 * Revision 1.1.1.1  1998/01/17  15:57:46  release
135
 * First version to be checked into rolling release.
136
 *
137
 * Revision 1.2  1994/12/15  09:58:37  smf
138
 * Brought into line with OSSG C Coding Standards Document, as per
139
 * "CR94_178.sid+tld-update".
140
 *
141
 * Revision 1.1.1.1  1994/07/25  16:04:38  smf
142
 * Initial import of SID 1.8 non shared files.
143
 *
144
**/
145
 
146
/****************************************************************************/
147
 
148
#include "rule.h"
149
#include "basic.h"
150
#include "bitvec.h"
151
#include "entry-list.h"
152
#include "gen-errors.h"
153
#include "types.h"
154
 
155
/*--------------------------------------------------------------------------*/
156
 
157
typedef struct AltGroupT {
158
    struct AltGroupT	       *next;
159
    BitVecT			first_set;
160
    EntryListT			predicate_first;
161
    unsigned			priority;
162
    AltP		       *alt_ref;
163
} AltGroupT, *AltGroupP;
164
 
165
typedef struct AltGroupListT {
166
    AltGroupP			head;
167
    AltGroupP		       *tail;
168
} AltGroupListT, *AltGroupListP;
169
 
170
/*--------------------------------------------------------------------------*/
171
 
172
static unsigned			rule_factor_limit = 1000;
173
 
174
/*--------------------------------------------------------------------------*/
175
 
176
static unsigned			rule_overlaps
177
	PROTO_S ((ItemP, BitVecP, EntryListP));
178
 
179
static AltGroupP
180
group_create PROTO_N ((item, alt_ref))
181
	     PROTO_T (ItemP item X
182
		      AltP *alt_ref)
183
{
184
    AltGroupP group = ALLOCATE (AltGroupT);
185
 
186
    group->next     = NIL (AltGroupP);
187
    bitvec_init (&(group->first_set));
188
    entry_list_init (&(group->predicate_first));
189
    group->priority = rule_overlaps (item, &(group->first_set),
190
				     &(group->predicate_first));
191
    group->alt_ref  = alt_ref;
192
    return (group);
193
}
194
 
195
static AltGroupP
196
group_deallocate PROTO_N ((group))
197
		 PROTO_T (AltGroupP group)
198
{
199
    AltGroupP next = group->next;
200
 
201
    bitvec_destroy (&(group->first_set));
202
    entry_list_destroy (&(group->predicate_first));
203
    DEALLOCATE (group);
204
    return (next);
205
}
206
 
207
/*--------------------------------------------------------------------------*/
208
 
209
static unsigned
210
rule_overlaps PROTO_N ((initial_item, first_set, predicate_first))
211
	      PROTO_T (ItemP      initial_item X
212
		       BitVecP    first_set X
213
		       EntryListP predicate_first)
214
{
215
    unsigned priority    = 0;
216
    BoolT    see_through = TRUE;
217
    BoolT    no_action   = TRUE;
218
    ItemP    item;
219
 
220
    for (item = initial_item; see_through && (item != NIL (ItemP));
221
	 item = item_next (item)) {
222
	switch (item_type (item)) EXHAUSTIVE {
223
	  case ET_PREDICATE:
224
	    ASSERT (item == initial_item);
225
	    entry_list_add_if_missing (predicate_first, item_entry (item));
226
	    see_through = FALSE;
227
	    break;
228
	  case ET_RENAME:
229
	  case ET_ACTION:
230
	    no_action = FALSE;
231
	    break;
232
	  case ET_RULE: {
233
	      EntryP   entry         = item_entry (item);
234
	      RuleP    item_rule     = entry_get_rule (entry);
235
	      unsigned item_priority = rule_get_priority (item_rule);
236
 
237
	      bitvec_or (first_set, rule_first_set (item_rule));
238
	      entry_list_append (predicate_first,
239
				 rule_predicate_first (item_rule));
240
	      see_through = rule_is_see_through (item_rule);
241
	      if ((item_priority > priority) && no_action) {
242
		  priority = item_priority;
243
	      }
244
	  }
245
	    break;
246
	  case ET_BASIC: {
247
	      BasicP basic = entry_get_basic (item_entry (item));
248
 
249
	      see_through = FALSE;
250
	      bitvec_set (first_set, basic_terminal (basic));
251
	  }
252
	    break;
253
	  case ET_NON_LOCAL:
254
	  case ET_NAME:
255
	  case ET_TYPE:
256
	    UNREACHED;
257
	}
258
    }
259
    return (priority + 1);
260
}
261
 
262
static void
263
rule_group_by_initial_item PROTO_N ((rule, groups))
264
			   PROTO_T (RuleP         rule X
265
				    AltGroupListP groups)
266
{
267
    AltP *alt_ref = (rule->alt_tail);
268
    AltP  alt;
269
 
270
  next_alt:
271
    while ((alt = *alt_ref) != NIL (AltP)) {
272
	ItemP     item = alt_item_head (alt);
273
	AltGroupP group;
274
 
275
	for (group = groups->head; group; group = group->next) {
276
	    AltP *group_alt_ref = group->alt_ref;
277
	    ItemP alt_item      = alt_item_head (*group_alt_ref);
278
 
279
	    if (((item_entry (item) == item_entry (alt_item)) &&
280
		 types_equal_numbers (item_param (item),
281
				      item_param (alt_item)) &&
282
		 types_equal_numbers (item_result (item),
283
				      item_result (alt_item))) ||
284
		(item_is_rename (item) && item_is_rename (alt_item) &&
285
		 types_equal_names (item_param (item),
286
				    item_param (alt_item)) &&
287
		 types_equal_names (item_result (item),
288
				    item_result (alt_item)))) {
289
		unsigned priority;
290
 
291
		*alt_ref        = alt_next (alt);
292
		alt_set_next (alt, *group_alt_ref);
293
		*group_alt_ref  = alt;
294
		priority        = rule_overlaps (item, &(group->first_set),
295
						 &(group->predicate_first));
296
		if (priority > group->priority) {
297
		    group->priority = priority;
298
		}
299
		goto next_alt;
300
	    }
301
	}
302
	group           = group_create (item, alt_ref);
303
	*(groups->tail) = group;
304
	groups->tail    = &(group->next);
305
	alt_ref         = alt_next_ref (alt);
306
    }
307
    rule->alt_tail = alt_ref;
308
}
309
 
310
static void			rule_factor_1
311
	PROTO_S ((RuleP, FactorClosureP));
312
 
313
static void
314
rule_expand PROTO_N ((rule, closure, group, groups))
315
	    PROTO_T (RuleP          rule X
316
		     FactorClosureP closure X
317
		     AltGroupP      group X
318
		     AltGroupListP  groups)
319
{
320
    AltP       alt       = (*(group->alt_ref));
321
    ItemP      item      = alt_item_head (alt);
322
    RuleP      item_rule = entry_get_rule (item_entry (item));
323
    AltP       handler   = rule_get_handler (item_rule);
324
    AltGroupP *last;
325
    AltP      *tail;
326
    TypeTransT translator;
327
 
328
    rule_factor_1 (item_rule, closure);
329
    if (handler && (!alt_equal (handler, rule_get_handler (rule)))) {
330
	E_factor_handler_mismatch (item_rule, rule);
331
    }
332
    if (!non_local_list_is_empty (rule_non_locals (item_rule))) {
333
	E_factor_nl_entry (item_rule, rule);
334
    }
335
    for (last = &(groups->head); *last != group; last = &((*last)->next)) {
336
	/*NOTHING*/
337
    }
338
    if (((*last) = (group->next)) != NIL (AltGroupP)) {
339
	*(group->alt_ref)       = *(group->next->alt_ref);
340
	*(group->next->alt_ref) = NIL (AltP);
341
	group->next->alt_ref    = group->alt_ref;
342
    } else {
343
	groups->tail            = last;
344
	*(group->alt_ref)       = NIL (AltP);
345
	rule->alt_tail          = group->alt_ref;
346
    }
347
    (void) group_deallocate (group);
348
    tail = rule->alt_tail;
349
    while (alt) {
350
	AltP       item_alt = rule_alt_head (item_rule);
351
	SaveTransT state;
352
 
353
	trans_init (&translator, rule_param (rule), rule_result (rule), alt);
354
	trans_add_translations (&translator, rule_param (item_rule),
355
				item_param (alt_item_head (alt)));
356
	trans_add_translations (&translator, rule_result (item_rule),
357
				item_result (alt_item_head (alt)));
358
	trans_save_state (&translator, &state);
359
	if (rule_has_empty_alt (item_rule)) {
360
	    AltP new_alt = alt_create_merge (NIL (ItemP),
361
					     item_next (alt_item_head (alt)),
362
					     &translator, closure->table);
363
 
364
	    *tail = new_alt;
365
	    tail  = alt_next_ref (new_alt);
366
	    trans_restore_state (&translator, &state);
367
	}
368
	for (; item_alt; item_alt = alt_next (item_alt)) {
369
	    AltP new_alt = alt_create_merge (alt_item_head (item_alt),
370
					     item_next (alt_item_head (alt)),
371
					     &translator, closure->table);
372
 
373
	    *tail = new_alt;
374
	    tail  = alt_next_ref (new_alt);
375
	    trans_restore_state (&translator, &state);
376
	}
377
	trans_destroy (&translator);
378
	alt = alt_deallocate (alt);
379
    }
380
}
381
 
382
static BoolT
383
rule_expand_item_clashes PROTO_N ((rule, closure, groups))
384
			 PROTO_T (RuleP          rule X
385
				  FactorClosureP closure X
386
				  AltGroupListP  groups)
387
{
388
    BitVecP   bitvec1 = &(closure->bitvec1);
389
    BitVecP   bitvec2 = &(closure->bitvec2);
390
    AltGroupP group;
391
 
392
    for (group = groups->head; group; group = group->next) {
393
	AltGroupP group2;
394
	AltP      first_alt = (*(group->alt_ref));
395
	ItemP     item      = alt_item_head (first_alt);
396
 
397
	if (item_is_rule (item)) {
398
	    RuleP item_rule = entry_get_rule (item_entry (item));
399
 
400
	    if (!entry_list_is_empty (rule_predicate_first (item_rule))) {
401
		rule_expand (rule, closure, group, groups);
402
		return (TRUE);
403
	    } else if (rule_is_see_through (item_rule)) {
404
		AltP       alt = first_alt;
405
		AltP       end = NIL (AltP);
406
		EntryListT predicate_first;
407
 
408
		if (group->next) {
409
		    end = *(group->next->alt_ref);
410
		}
411
		bitvec_replace (bitvec1, rule_first_set (item_rule));
412
		do {
413
		    bitvec_empty (bitvec2);
414
		    entry_list_init (&predicate_first);
415
		    (void) rule_overlaps (item_next (alt_item_head (alt)),
416
					  bitvec2, &predicate_first);
417
		    if (bitvec_intersects (bitvec1, bitvec2) ||
418
			(!entry_list_is_empty (&predicate_first))) {
419
			entry_list_destroy (&predicate_first);
420
			rule_expand (rule, closure, group, groups);
421
			return (TRUE);
422
		    }
423
		    entry_list_destroy (&predicate_first);
424
		} while ((alt = alt_next (alt)) != end);
425
	    }
426
	    for (group2 = groups->head; group2; group2 = group2->next) {
427
		if ((group2 != group) &&
428
		    (bitvec_intersects (&(group2->first_set),
429
					&(group->first_set)))) {
430
		    if (group->priority > group2->priority) {
431
			rule_expand (rule, closure, group, groups);
432
		    } else {
433
			rule_expand (rule, closure, group2, groups);
434
		    }
435
		    return (TRUE);
436
		}
437
	    }
438
	}
439
    }
440
    return (FALSE);
441
}
442
 
443
/*--------------------------------------------------------------------------*/
444
 
445
static ItemP
446
rule_create_factored PROTO_N ((params, result, alt, table))
447
		     PROTO_T (TypeTupleP params X
448
			      TypeTupleP result X
449
			      AltP       alt X
450
			      TableP     table)
451
{
452
    static unsigned factorised_rules = 0;
453
    EntryP          new_entry;
454
    ItemP           new_item;
455
    RuleP           new_rule;
456
 
457
    if (factorised_rules == rule_factor_limit) {
458
	E_too_many_factorisations (rule_factor_limit);
459
	UNREACHED;
460
    }
461
    factorised_rules ++;
462
    new_entry = table_add_generated_rule (table, FALSE);
463
    new_rule  = entry_get_rule (new_entry);
464
    types_copy (rule_param (new_rule), params);
465
    types_copy (rule_result (new_rule), result);
466
    while (alt) {
467
	AltP tmp_alt = alt;
468
 
469
	alt = alt_next (alt);
470
	alt_set_next (tmp_alt, NIL (AltP));
471
	if (alt_item_head (tmp_alt)) {
472
	    rule_add_alt (new_rule, tmp_alt);
473
	} else {
474
	    rule_add_empty_alt (new_rule);
475
	    (void) alt_deallocate (tmp_alt);
476
	}
477
    }
478
    rule_compute_first_set_1 (new_rule);
479
    new_item  = item_create (new_entry);
480
    types_assign (item_param (new_item), params);
481
    types_assign (item_result (new_item), result);
482
    types_make_references (rule_param (new_rule), item_param (new_item));
483
    return (new_item);
484
}
485
 
486
static BoolT
487
rule_factor_4 PROTO_N ((rule, old_alt, new_alt, table, predicate_id, params,
488
		     items_equal_ref))
489
	      PROTO_T (RuleP      rule X
490
		       AltP       old_alt X
491
		       AltP       new_alt X
492
		       TableP     table X
493
		       EntryP     predicate_id X
494
		       TypeTupleP params X
495
		       BoolP      items_equal_ref)
496
{
497
    ItemP       old_item     = alt_item_head (old_alt);
498
    BoolT       result_equal = TRUE;
499
    AltP        alt;
500
    TypeBTransT translator;
501
 
502
    for (alt = alt_next (old_alt); alt; alt = alt_next (alt)) {
503
	ItemP item = alt_item_head (alt);
504
 
505
	if (((item == NIL (ItemP)) && (old_item != NIL (ItemP))) ||
506
	    ((item != NIL (ItemP)) && (old_item == NIL (ItemP)))) {
507
	    *items_equal_ref = FALSE;
508
	    return (TRUE);
509
	} else if ((item == NIL (ItemP)) && (old_item == NIL (ItemP))) {
510
	    /*NOTHING*/
511
	} else if (((item_entry (old_item) == item_entry (item)) &&
512
		    types_equal_numbers (item_param (old_item),
513
					 item_param (item)) &&
514
		    types_equal_numbers (item_result (old_item),
515
					 item_result (item))) ||
516
		   (item_is_rename (item) && item_is_rename (old_item) &&
517
		    types_equal_names (item_param (item),
518
				       item_param (old_item)) &&
519
		    types_equal_names (item_result (item),
520
				       item_result (old_item)))) {
521
	    if (result_equal) {
522
		result_equal = types_equal_names (item_result (old_item),
523
						  item_result (item));
524
	    }
525
	} else {
526
	    *items_equal_ref = FALSE;
527
	    return (TRUE);
528
	}
529
    }
530
    if (old_item == NIL (ItemP)) {
531
	*items_equal_ref = FALSE;
532
	return (FALSE);
533
    }
534
    btrans_init (&translator);
535
    for (alt = old_alt; alt; alt = alt_next (alt)) {
536
	ItemP item = alt_unlink_item_head (alt);
537
 
538
	if (!result_equal) {
539
	    ItemP new_item;
540
 
541
	    if (alt == old_alt) {
542
		new_item = btrans_generate_non_pred_names (&translator,
543
							   item_result (item),
544
							   rule_result (rule),
545
							   predicate_id,
546
							   table);
547
		types_translate (item_result (item), &translator);
548
	    } else {
549
		new_item = btrans_regen_non_pred_names (&translator,
550
							item_result (item),
551
							rule_result (rule),
552
							table);
553
	    }
554
	    item_translate_list (alt_item_head (alt), &translator);
555
	    if (new_item) {
556
		alt_add_item (alt, new_item);
557
	    }
558
	}
559
	if (alt == old_alt) {
560
	    types_add_new_names (params, item_result (item), predicate_id);
561
	    alt_add_item (new_alt, item);
562
	} else {
563
	    (void) item_deallocate (item);
564
	}
565
    }
566
    btrans_destroy (&translator);
567
    return (TRUE);
568
}
569
 
570
static void
571
rule_factor_3 PROTO_N ((rule, table, predicate_id, old_alt, new_alt))
572
	      PROTO_T (RuleP  rule X
573
		       TableP table X
574
		       EntryP predicate_id X
575
		       AltP   old_alt X
576
		       AltP   new_alt)
577
{
578
    BoolT       items_equal = TRUE;
579
    BoolT       found_items;
580
    TypeTupleT  params;
581
    TypeTupleT  result;
582
 
583
    types_copy (&params, rule_param (rule));
584
    types_copy (&result, rule_result (rule));
585
    do {
586
	found_items = rule_factor_4 (rule, old_alt, new_alt, table,
587
				     predicate_id, &params, &items_equal);
588
    } while (items_equal);
589
    if (found_items) {
590
	ItemP new_item;
591
 
592
	types_unlink_used (&result, &params);
593
	types_unlink_unused (&params, old_alt);
594
	new_item = rule_create_factored (&params, &result, old_alt, table);
595
	alt_add_item (new_alt, new_item);
596
    } else {
597
	types_destroy (&params);
598
	while (old_alt) {
599
	    AltP tmp_alt = old_alt;
600
 
601
	    old_alt = alt_next (old_alt);
602
	    ASSERT (alt_item_head (tmp_alt) == NIL (ItemP));
603
	    (void) alt_deallocate (tmp_alt);
604
	}
605
    }
606
}
607
 
608
static void
609
rule_factor_2 PROTO_N ((rule, table, predicate_id, groups))
610
	      PROTO_T (RuleP         rule X
611
		       TableP        table X
612
		       EntryP        predicate_id X
613
		       AltGroupListP groups)
614
{
615
    AltGroupP group;
616
 
617
    for (group = groups->head; group; group = group_deallocate (group)) {
618
	AltP alt = *(group->alt_ref);
619
	AltP new_alt;
620
 
621
	if (group->next) {
622
	    if (group->next->alt_ref == alt_next_ref (*(group->alt_ref))) {
623
		goto done;
624
	    }
625
	    new_alt                 = alt_create ();
626
	    alt_set_next (new_alt, *(group->next->alt_ref));
627
	    *(group->next->alt_ref) = NIL (AltP);
628
	    group->next->alt_ref    = alt_next_ref (new_alt);
629
	} else {
630
	    if (alt_next (*(group->alt_ref)) == NIL (AltP)) {
631
		goto done;
632
	    }
633
	    new_alt        = alt_create ();
634
	    rule->alt_tail = alt_next_ref (new_alt);
635
	}
636
	*(group->alt_ref) = new_alt;
637
	rule_factor_3 (rule, table, predicate_id, alt, new_alt);
638
      done:;
639
    }
640
}
641
 
642
static void
643
rule_factor_1 PROTO_N ((rule, closure))
644
	      PROTO_T (RuleP          rule X
645
		       FactorClosureP closure)
646
{
647
    AltGroupListT groups;
648
 
649
    groups.head = NIL (AltGroupP);
650
    groups.tail = &(groups.head);
651
    if (rule_is_factored (rule)) {
652
	return;
653
    }
654
    rule_factored (rule);
655
    rule->alt_tail = &(rule->alt_head);
656
    do {
657
	rule_renumber (rule, FALSE, closure->predicate_id);
658
	rule_group_by_initial_item (rule, &groups);
659
    } while (rule_expand_item_clashes (rule, closure, &groups));
660
    rule_factor_2 (rule, closure->table, closure->predicate_id, &groups);
661
}
662
 
663
/*--------------------------------------------------------------------------*/
664
 
665
void
666
rule_factor PROTO_N ((entry, gclosure))
667
	    PROTO_T (EntryP   entry X
668
		     GenericP gclosure)
669
{
670
    FactorClosureP closure = (FactorClosureP) gclosure;
671
 
672
    if (entry_is_rule (entry)) {
673
	RuleP rule = entry_get_rule (entry);
674
 
675
	rule_factor_1 (rule, closure);
676
    }
677
}
678
 
679
void
680
rule_set_factor_limit PROTO_N ((limit))
681
		      PROTO_T (unsigned limit)
682
{
683
    rule_factor_limit = limit;
684
}
685
 
686
/*
687
 * Local variables(smf):
688
 * eval: (include::add-path-entry "../os-interface" "../library")
689
 * eval: (include::add-path-entry "../generated")
690
 * end:
691
**/