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

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/algol60/src/utilities/sid/grammar.c – Rev 7

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