GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/yacc/lalr.c Lines: 254 255 99.6 %
Date: 2017-11-07 Branches: 137 142 96.5 %

Line Branch Exec Source
1
/*	$OpenBSD: lalr.c,v 1.19 2017/05/25 20:11:03 tedu Exp $	*/
2
/*	$NetBSD: lalr.c,v 1.4 1996/03/19 03:21:33 jtc Exp $	*/
3
4
/*
5
 * Copyright (c) 1989 The Regents of the University of California.
6
 * All rights reserved.
7
 *
8
 * This code is derived from software contributed to Berkeley by
9
 * Robert Paul Corbett.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions and the following disclaimer.
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in the
18
 *    documentation and/or other materials provided with the distribution.
19
 * 3. Neither the name of the University nor the names of its contributors
20
 *    may be used to endorse or promote products derived from this software
21
 *    without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
 * SUCH DAMAGE.
34
 */
35
36
#include "defs.h"
37
38
typedef struct shorts {
39
	struct shorts *next;
40
	short value;
41
} shorts;
42
43
int tokensetsize;
44
short *lookaheads;
45
short *LAruleno;
46
unsigned *LA;
47
short *accessing_symbol;
48
core **state_table;
49
shifts **shift_table;
50
reductions **reduction_table;
51
short *goto_map;
52
short *from_state;
53
short *to_state;
54
55
short **transpose(short **, int);
56
void set_state_table(void);
57
void set_accessing_symbol(void);
58
void set_shift_table(void);
59
void set_reduction_table(void);
60
void set_maxrhs(void);
61
void initialize_LA(void);
62
void set_goto_map(void);
63
void initialize_F(void);
64
void build_relations(void);
65
void compute_FOLLOWS(void);
66
void compute_lookaheads(void);
67
int map_goto(int, int);
68
void digraph(short **);
69
void add_lookback_edge(int, int, int);
70
void traverse(int);
71
72
static int infinity;
73
static int maxrhs;
74
static int ngotos;
75
static unsigned *F;
76
static short **includes;
77
static shorts **lookback;
78
static short **R;
79
static short *INDEX;
80
static short *VERTICES;
81
static int top;
82
83
void
84
lalr(void)
85
{
86
30
	tokensetsize = WORDSIZE(ntokens);
87
88
15
	set_state_table();
89
15
	set_accessing_symbol();
90
15
	set_shift_table();
91
15
	set_reduction_table();
92
15
	set_maxrhs();
93
15
	initialize_LA();
94
15
	set_goto_map();
95
15
	initialize_F();
96
15
	build_relations();
97
15
	compute_FOLLOWS();
98
15
	compute_lookaheads();
99
15
	free_derives();
100
15
	free_nullable();
101
15
}
102
103
104
void
105
set_state_table(void)
106
{
107
	core *sp;
108
109
30
	state_table = NEW2(nstates, core *);
110
6880
	for (sp = first_state; sp; sp = sp->next)
111
3425
		state_table[sp->number] = sp;
112
15
}
113
114
115
void
116
set_accessing_symbol(void)
117
{
118
	core *sp;
119
120
30
	accessing_symbol = NEW2(nstates, short);
121
6880
	for (sp = first_state; sp; sp = sp->next)
122
3425
		accessing_symbol[sp->number] = sp->accessing_symbol;
123
15
}
124
125
126
void
127
set_shift_table(void)
128
{
129
	shifts *sp;
130
131
30
	shift_table = NEW2(nstates, shifts *);
132
4214
	for (sp = first_shift; sp; sp = sp->next)
133
2092
		shift_table[sp->number] = sp;
134
15
}
135
136
137
void
138
set_reduction_table(void)
139
{
140
	reductions *rp;
141
142
30
	reduction_table = NEW2(nstates, reductions *);
143
4156
	for (rp = first_reduction; rp; rp = rp->next)
144
2063
		reduction_table[rp->number] = rp;
145
15
}
146
147
148
void
149
set_maxrhs(void)
150
{
151
	short *itemp, *item_end;
152
	int length, max;
153
154
	length = 0;
155
	max = 0;
156
30
	item_end = ritem + nitems;
157
12112
	for (itemp = ritem; itemp < item_end; itemp++) {
158
6041
		if (*itemp >= 0) {
159
4161
			length++;
160
4161
		} else {
161
1936
			if (length > max) max = length;
162
			length = 0;
163
		}
164
	}
165
166
15
	maxrhs = max;
167
15
}
168
169
170
void
171
initialize_LA(void)
172
{
173
	int i, j, k;
174
	reductions *rp;
175
176
30
	lookaheads = NEW2(nstates + 1, short);
177
178
	k = 0;
179
6880
	for (i = 0; i < nstates; i++) {
180
3425
		lookaheads[i] = k;
181
3425
		rp = reduction_table[i];
182
3425
		if (rp)
183
2063
			k += rp->nreds;
184
	}
185
15
	lookaheads[nstates] = k;
186
187
15
	LA = NEW2(k * tokensetsize, unsigned);
188
15
	LAruleno = NEW2(k, short);
189
15
	lookback = NEW2(k, shorts *);
190
191
	k = 0;
192
6880
	for (i = 0; i < nstates; i++) {
193
3425
		rp = reduction_table[i];
194
3425
		if (rp) {
195
8354
			for (j = 0; j < rp->nreds; j++) {
196
2114
				LAruleno[k] = rp->rules[j];
197
2114
				k++;
198
			}
199
		}
200
	}
201
15
}
202
203
void
204
set_goto_map(void)
205
{
206
	shifts *sp;
207
	int i, k, symbol;
208
	int state1, state2;
209
	short *temp_map;
210
211
30
	goto_map = NEW2(nvars + 1, short) - ntokens;
212
15
	temp_map = NEW2(nvars + 1, short) - ntokens;
213
214
15
	ngotos = 0;
215
4214
	for (sp = first_shift; sp; sp = sp->next) {
216
9396
		for (i = sp->nshifts - 1; i >= 0; i--) {
217
4555
			symbol = accessing_symbol[sp->shift[i]];
218
219
4555
			if (ISTOKEN(symbol)) break;
220
221
2606
			if (ngotos == MAXSHORT)
222
				fatal("too many gotos");
223
224
2606
			ngotos++;
225
2606
			goto_map[symbol]++;
226
		}
227
	}
228
229
	k = 0;
230
1250
	for (i = ntokens; i < nsyms; i++) {
231
610
		temp_map[i] = k;
232
610
		k += goto_map[i];
233
	}
234
235
1250
	for (i = ntokens; i < nsyms; i++)
236
610
		goto_map[i] = temp_map[i];
237
238
15
	goto_map[nsyms] = ngotos;
239
15
	temp_map[nsyms] = ngotos;
240
241
15
	from_state = NEW2(ngotos, short);
242
15
	to_state = NEW2(ngotos, short);
243
244
4214
	for (sp = first_shift; sp; sp = sp->next) {
245
2092
		state1 = sp->number;
246
9396
		for (i = sp->nshifts - 1; i >= 0; i--) {
247
4555
			state2 = sp->shift[i];
248
4555
			symbol = accessing_symbol[state2];
249
250
4555
			if (ISTOKEN(symbol)) break;
251
252
2606
			k = temp_map[symbol]++;
253
2606
			from_state[k] = state1;
254
2606
			to_state[k] = state2;
255
		}
256
	}
257
258
15
	free(temp_map + ntokens);
259
15
}
260
261
262
263
/*  Map_goto maps a state/symbol pair into its numeric representation.	*/
264
265
int
266
map_goto(int state, int symbol)
267
{
268
	int high, low, middle, s;
269
270
15084
	low = goto_map[symbol];
271
7542
	high = goto_map[symbol + 1];
272
273
7542
	for (;;) {
274
28918
		assert(low <= high);
275
28918
		middle = (low + high) >> 1;
276
28918
		s = from_state[middle];
277
28918
		if (s == state)
278
7542
			return (middle);
279
21376
		else if (s < state)
280
11121
			low = middle + 1;
281
		else
282
10255
			high = middle - 1;
283
	}
284
}
285
286
287
void
288
initialize_F(void)
289
{
290
	int i, j, k;
291
	shifts *sp;
292
	short *edge, *rp, **reads;
293
	unsigned int *rowp;
294
	int nedges, stateno, symbol, nwords;
295
296
30
	nwords = ngotos * tokensetsize;
297
15
	F = NEW2(nwords, unsigned);
298
299
15
	reads = NEW2(ngotos, short *);
300
15
	edge = NEW2(ngotos + 1, short);
301
	nedges = 0;
302
303
15
	rowp = F;
304
5242
	for (i = 0; i < ngotos; i++) {
305
2606
		stateno = to_state[i];
306
2606
		sp = shift_table[stateno];
307
308
2606
		if (sp) {
309
1566
			k = sp->nshifts;
310
311
22190
			for (j = 0; j < k; j++) {
312
10116
				symbol = accessing_symbol[sp->shift[j]];
313
10116
				if (ISVAR(symbol))
314
					break;
315
9529
				SETBIT(rowp, symbol);
316
			}
317
318
5822
			for (; j < k; j++) {
319
2128
				symbol = accessing_symbol[sp->shift[j]];
320
2128
				if (nullable[symbol])
321
223
					edge[nedges++] = map_goto(stateno, symbol);
322
			}
323
324
1566
			if (nedges) {
325
206
				reads[i] = rp = NEW2(nedges + 1, short);
326
327
858
				for (j = 0; j < nedges; j++)
328
223
					rp[j] = edge[j];
329
330
206
				rp[nedges] = -1;
331
				nedges = 0;
332
206
			}
333
		}
334
335
2606
		rowp += tokensetsize;
336
	}
337
338
15
	SETBIT(F, 0);
339
15
	digraph(reads);
340
341
5242
	for (i = 0; i < ngotos; i++)
342
2606
		free(reads[i]);
343
344
15
	free(reads);
345
15
	free(edge);
346
15
}
347
348
349
void
350
build_relations(void)
351
{
352
	int i, j, k;
353
	short *rulep, *rp;
354
	shifts *sp;
355
	int length, nedges, done;
356
	int state1, stateno, symbol1, symbol2;
357
	short *shortp, *edge, *states;
358
	short **new_includes;
359
360
30
	includes = NEW2(ngotos, short *);
361
15
	edge = NEW2(ngotos + 1, short);
362
15
	states = NEW2(maxrhs + 1, short);
363
364
5242
	for (i = 0; i < ngotos; i++) {
365
		nedges = 0;
366
2606
		state1 = from_state[i];
367
2606
		symbol1 = accessing_symbol[to_state[i]];
368
369
32676
		for (rulep = derives[symbol1]; *rulep >= 0; rulep++) {
370
			length = 1;
371
13732
			states[0] = state1;
372
			stateno = state1;
373
374
91458
			for (rp = ritem + rrhs[*rulep]; *rp >= 0; rp++) {
375
				symbol2 = *rp;
376
31997
				sp = shift_table[stateno];
377
31997
				k = sp->nshifts;
378
379
621476
				for (j = 0; j < k; j++) {
380
310738
					stateno = sp->shift[j];
381
310738
					if (accessing_symbol[stateno] == symbol2)
382
						break;
383
				}
384
385
31997
				states[length++] = stateno;
386
			}
387
388
13732
			add_lookback_edge(stateno, *rulep, i);
389
390
13732
			length--;
391
			done = 0;
392
41685
			while (!done) {
393
				done = 1;
394
14221
				rp--;
395
14221
				if (ISVAR(*rp)) {
396
7319
					stateno = states[--length];
397
7319
					edge[nedges++] = map_goto(stateno, *rp);
398
7319
					if (nullable[*rp] && length > 0)
399
489
						done = 0;
400
				}
401
			}
402
		}
403
404
2606
		if (nedges) {
405
1409
			includes[i] = shortp = NEW2(nedges + 1, short);
406
17456
			for (j = 0; j < nedges; j++)
407
7319
				shortp[j] = edge[j];
408
1409
			shortp[nedges] = -1;
409
1409
		}
410
	}
411
412
15
	new_includes = transpose(includes, ngotos);
413
414
5242
	for (i = 0; i < ngotos; i++)
415
2606
		free(includes[i]);
416
417
15
	free(includes);
418
419
15
	includes = new_includes;
420
421
15
	free(edge);
422
15
	free(states);
423
15
}
424
425
void
426
add_lookback_edge(int stateno, int ruleno, int gotono)
427
{
428
	int i, k, found;
429
	shorts *sp;
430
431
27464
	i = lookaheads[stateno];
432
13732
	k = lookaheads[stateno + 1];
433
	found = 0;
434

55190
	while (!found && i < k) {
435
13863
		if (LAruleno[i] == ruleno)
436
13732
			found = 1;
437
		else
438
131
			++i;
439
	}
440
13732
	assert(found);
441
442
13732
	sp = NEW(shorts);
443
13732
	sp->next = lookback[i];
444
13732
	sp->value = gotono;
445
13732
	lookback[i] = sp;
446
13732
}
447
448
449
450
short **
451
transpose(short **old_R, int n)
452
{
453
	short **new_R, **temp_R, *nedges, *sp;
454
	int i, k;
455
456
30
	nedges = NEW2(n, short);
457
458
5242
	for (i = 0; i < n; i++) {
459
2606
		sp = old_R[i];
460
2606
		if (sp) {
461
16047
			while (*sp >= 0)
462
7319
				nedges[*sp++]++;
463
		}
464
	}
465
466
15
	new_R = NEW2(n, short *);
467
15
	temp_R = NEW2(n, short *);
468
469
5242
	for (i = 0; i < n; i++) {
470
2606
		k = nedges[i];
471
2606
		if (k > 0) {
472
1757
			sp = NEW2(k + 1, short);
473
1757
			new_R[i] = sp;
474
1757
			temp_R[i] = sp;
475
1757
			sp[k] = -1;
476
1757
		}
477
	}
478
479
15
	free(nedges);
480
481
5242
	for (i = 0; i < n; i++) {
482
2606
		sp = old_R[i];
483
2606
		if (sp) {
484
16047
			while (*sp >= 0)
485
7319
				*temp_R[*sp++]++ = i;
486
		}
487
	}
488
489
15
	free(temp_R);
490
491
15
	return (new_R);
492
}
493
494
495
void
496
compute_FOLLOWS(void)
497
{
498
30
	digraph(includes);
499
15
}
500
501
void
502
compute_lookaheads(void)
503
{
504
	int i, n;
505
	unsigned int *fp1, *fp2, *fp3;
506
	shorts *sp, *next;
507
	unsigned int *rowp;
508
509
30
	rowp = LA;
510
15
	n = lookaheads[nstates];
511
4258
	for (i = 0; i < n; i++) {
512
2114
		fp3 = rowp + tokensetsize;
513
31692
		for (sp = lookback[i]; sp; sp = sp->next) {
514
			fp1 = rowp;
515
13732
			fp2 = F + tokensetsize * sp->value;
516
97114
			while (fp1 < fp3)
517
34825
				*fp1++ |= *fp2++;
518
		}
519
		rowp = fp3;
520
	}
521
522
4258
	for (i = 0; i < n; i++)
523
31692
		for (sp = lookback[i]; sp; sp = next) {
524
13732
			next = sp->next;
525
13732
			free(sp);
526
		}
527
528
15
	free(lookback);
529
15
	free(F);
530
15
}
531
532
void
533
digraph(short **relation)
534
{
535
	int i;
536
537
60
	infinity = ngotos + 2;
538
30
	INDEX = NEW2(ngotos + 1, short);
539
30
	VERTICES = NEW2(ngotos + 1, short);
540
30
	top = 0;
541
30
	R = relation;
542
543
30
	memset(INDEX, 0, ngotos * sizeof(short));
544
10484
	for (i = 0; i < ngotos; i++)
545
5212
		if (R[i])
546
1963
			traverse(i);
547
548
30
	free(INDEX);
549
30
	free(VERTICES);
550
30
}
551
552
553
void
554
traverse(int i)
555
{
556
	unsigned int *base, *fp1, *fp2, *fp3;
557
	int j, height;
558
	short *rp;
559
560
6354
	VERTICES[++top] = i;
561
3177
	INDEX[i] = height = top;
562
563
3177
	base = F + i * tokensetsize;
564
3177
	fp3 = base + tokensetsize;
565
566
3177
	rp = R[i];
567
3177
	if (rp) {
568
15195
		while ((j = *rp++) >= 0) {
569
12489
			if (INDEX[j] == 0)
570
1214
				traverse(j);
571
572
12489
			if (INDEX[i] > INDEX[j])
573
166
				INDEX[i] = INDEX[j];
574
575
			fp1 = base;
576
12489
			fp2 = F + j * tokensetsize;
577
578
83732
			while (fp1 < fp3)
579
29377
				*fp1++ |= *fp2++;
580
		}
581
	}
582
583
3177
	if (INDEX[i] == height) {
584
		for (;;) {
585
3177
			j = VERTICES[top--];
586
3177
			INDEX[j] = infinity;
587
588
3177
			if (i == j)
589
				break;
590
591
			fp1 = base;
592
166
			fp2 = F + j * tokensetsize;
593
594
1076
			while (fp1 < fp3)
595
372
				*fp2++ = *fp1++;
596
		}
597
	}
598
3177
}