PageRenderTime 46ms CodeModel.GetById 14ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 0ms

/usr.bin/yacc/lalr.c

https://bitbucket.org/freebsd/freebsd-head/
C | 701 lines | 534 code | 135 blank | 32 comment | 85 complexity | cce4d6b66ea1af43c6c2ff55659d31a4 MD5 | raw file
  1/*
  2 * Copyright (c) 1989 The Regents of the University of California.
  3 * All rights reserved.
  4 *
  5 * This code is derived from software contributed to Berkeley by
  6 * Robert Paul Corbett.
  7 *
  8 * Redistribution and use in source and binary forms, with or without
  9 * modification, are permitted provided that the following conditions
 10 * are met:
 11 * 1. Redistributions of source code must retain the above copyright
 12 *    notice, this list of conditions and the following disclaimer.
 13 * 2. Redistributions in binary form must reproduce the above copyright
 14 *    notice, this list of conditions and the following disclaimer in the
 15 *    documentation and/or other materials provided with the distribution.
 16 * 4. Neither the name of the University nor the names of its contributors
 17 *    may be used to endorse or promote products derived from this software
 18 *    without specific prior written permission.
 19 *
 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 30 * SUCH DAMAGE.
 31 */
 32
 33#if 0
 34#ifndef lint
 35static char sccsid[] = "@(#)lalr.c	5.3 (Berkeley) 6/1/90";
 36#endif
 37#endif
 38
 39#include <sys/cdefs.h>
 40__FBSDID("$FreeBSD$");
 41
 42#include <limits.h>
 43#include <stdlib.h>
 44#include "defs.h"
 45
 46typedef
 47  struct shorts
 48    {
 49      struct shorts *next;
 50      short value;
 51    }
 52  shorts;
 53
 54int tokensetsize;
 55short *lookaheads;
 56short *LAruleno;
 57unsigned *LA;
 58short *accessing_symbol;
 59core **state_table;
 60shifts **shift_table;
 61reductions **reduction_table;
 62short *goto_map;
 63short *from_state;
 64short *to_state;
 65
 66static void add_lookback_edge(int, int, int);
 67static void build_relations(void);
 68static void compute_FOLLOWS(void);
 69static void compute_lookaheads(void);
 70static void digraph(short **);
 71static void initialize_F(void);
 72static void initialize_LA(void);
 73static int map_goto(int, int);
 74static void set_accessing_symbol(void);
 75static void set_goto_map(void);
 76static void set_maxrhs(void);
 77static void set_reduction_table(void);
 78static void set_shift_table(void);
 79static void set_state_table(void);
 80static short **transpose(short **, int);
 81static void traverse(int, short **);
 82
 83static int infinity;
 84static int maxrhs;
 85static int ngotos;
 86static unsigned *F;
 87static short **includes;
 88static shorts **lookback;
 89static short *INDEX;
 90static short *VERTICES;
 91static int top;
 92
 93
 94void
 95lalr(void)
 96{
 97    tokensetsize = WORDSIZE(ntokens);
 98
 99    set_state_table();
100    set_accessing_symbol();
101    set_shift_table();
102    set_reduction_table();
103    set_maxrhs();
104    initialize_LA();
105    set_goto_map();
106    initialize_F();
107    build_relations();
108    compute_FOLLOWS();
109    compute_lookaheads();
110}
111
112
113
114static void
115set_state_table(void)
116{
117    core *sp;
118
119    state_table = NEW2(nstates, core *);
120    for (sp = first_state; sp; sp = sp->next)
121	state_table[sp->number] = sp;
122}
123
124
125
126static void
127set_accessing_symbol(void)
128{
129    core *sp;
130
131    accessing_symbol = NEW2(nstates, short);
132    for (sp = first_state; sp; sp = sp->next)
133	accessing_symbol[sp->number] = sp->accessing_symbol;
134}
135
136
137
138static void
139set_shift_table(void)
140{
141    shifts *sp;
142
143    shift_table = NEW2(nstates, shifts *);
144    for (sp = first_shift; sp; sp = sp->next)
145	shift_table[sp->number] = sp;
146}
147
148
149
150static void
151set_reduction_table(void)
152{
153    reductions *rp;
154
155    reduction_table = NEW2(nstates, reductions *);
156    for (rp = first_reduction; rp; rp = rp->next)
157	reduction_table[rp->number] = rp;
158}
159
160
161
162static void
163set_maxrhs(void)
164{
165  short *itemp;
166  short *item_end;
167  int length;
168  int max;
169
170  length = 0;
171  max = 0;
172  item_end = ritem + nitems;
173  for (itemp = ritem; itemp < item_end; itemp++)
174    {
175      if (*itemp >= 0)
176	{
177	  length++;
178	}
179      else
180	{
181	  if (length > max) max = length;
182	  length = 0;
183	}
184    }
185
186  maxrhs = max;
187}
188
189
190
191static void
192initialize_LA(void)
193{
194  int i, j, k;
195  reductions *rp;
196
197  lookaheads = NEW2(nstates + 1, short);
198
199  k = 0;
200  for (i = 0; i < nstates; i++)
201    {
202      lookaheads[i] = k;
203      rp = reduction_table[i];
204      if (rp)
205	k += rp->nreds;
206    }
207  lookaheads[nstates] = k;
208
209  LA = NEW2(k * tokensetsize, unsigned);
210  LAruleno = NEW2(k, short);
211  lookback = NEW2(k, shorts *);
212
213  k = 0;
214  for (i = 0; i < nstates; i++)
215    {
216      rp = reduction_table[i];
217      if (rp)
218	{
219	  for (j = 0; j < rp->nreds; j++)
220	    {
221	      LAruleno[k] = rp->rules[j];
222	      k++;
223	    }
224	}
225    }
226}
227
228
229static void
230set_goto_map(void)
231{
232  shifts *sp;
233  int i;
234  int symbol;
235  int k;
236  short *temp_map;
237  int state2;
238  int state1;
239
240  goto_map = NEW2(nvars + 1, short) - ntokens;
241  temp_map = NEW2(nvars + 1, short) - ntokens;
242
243  ngotos = 0;
244  for (sp = first_shift; sp; sp = sp->next)
245    {
246      for (i = sp->nshifts - 1; i >= 0; i--)
247	{
248	  symbol = accessing_symbol[sp->shift[i]];
249
250	  if (ISTOKEN(symbol)) break;
251
252	  if (ngotos == SHRT_MAX)
253	    fatal("too many gotos");
254
255	  ngotos++;
256	  goto_map[symbol]++;
257        }
258    }
259
260  k = 0;
261  for (i = ntokens; i < nsyms; i++)
262    {
263      temp_map[i] = k;
264      k += goto_map[i];
265    }
266
267  for (i = ntokens; i < nsyms; i++)
268    goto_map[i] = temp_map[i];
269
270  goto_map[nsyms] = ngotos;
271  temp_map[nsyms] = ngotos;
272
273  from_state = NEW2(ngotos, short);
274  to_state = NEW2(ngotos, short);
275
276  for (sp = first_shift; sp; sp = sp->next)
277    {
278      state1 = sp->number;
279      for (i = sp->nshifts - 1; i >= 0; i--)
280	{
281	  state2 = sp->shift[i];
282	  symbol = accessing_symbol[state2];
283
284	  if (ISTOKEN(symbol)) break;
285
286	  k = temp_map[symbol]++;
287	  from_state[k] = state1;
288	  to_state[k] = state2;
289	}
290    }
291
292  free(temp_map + ntokens);
293}
294
295
296
297/*  Map_goto maps a state/symbol pair into its numeric representation.	*/
298
299static int
300map_goto(int state, int symbol)
301{
302    int high;
303    int low;
304    int middle;
305    int s;
306
307    low = goto_map[symbol];
308    high = goto_map[symbol + 1];
309
310    for (;;)
311    {
312	assert(low <= high);
313	middle = (low + high) >> 1;
314	s = from_state[middle];
315	if (s == state)
316	    return (middle);
317	else if (s < state)
318	    low = middle + 1;
319	else
320	    high = middle - 1;
321    }
322}
323
324
325
326static void
327initialize_F(void)
328{
329  int i;
330  int j;
331  int k;
332  shifts *sp;
333  short *edge;
334  unsigned *rowp;
335  short *rp;
336  short **reads;
337  int nedges;
338  int stateno;
339  int symbol;
340  int nwords;
341
342  nwords = ngotos * tokensetsize;
343  F = NEW2(nwords, unsigned);
344
345  reads = NEW2(ngotos, short *);
346  edge = NEW2(ngotos + 1, short);
347  nedges = 0;
348
349  rowp = F;
350  for (i = 0; i < ngotos; i++)
351    {
352      stateno = to_state[i];
353      sp = shift_table[stateno];
354
355      if (sp)
356	{
357	  k = sp->nshifts;
358
359	  for (j = 0; j < k; j++)
360	    {
361	      symbol = accessing_symbol[sp->shift[j]];
362	      if (ISVAR(symbol))
363		break;
364	      SETBIT(rowp, symbol);
365	    }
366
367	  for (; j < k; j++)
368	    {
369	      symbol = accessing_symbol[sp->shift[j]];
370	      if (nullable[symbol])
371		edge[nedges++] = map_goto(stateno, symbol);
372	    }
373
374	  if (nedges)
375	    {
376	      reads[i] = rp = NEW2(nedges + 1, short);
377
378	      for (j = 0; j < nedges; j++)
379		rp[j] = edge[j];
380
381	      rp[nedges] = -1;
382	      nedges = 0;
383	    }
384	}
385
386      rowp += tokensetsize;
387    }
388
389  SETBIT(F, 0);
390  digraph(reads);
391
392  for (i = 0; i < ngotos; i++)
393    {
394      if (reads[i])
395	free(reads[i]);
396    }
397
398  free(reads);
399  free(edge);
400}
401
402
403
404static void
405build_relations(void)
406{
407  int i;
408  int j;
409  int k;
410  short *rulep;
411  short *rp;
412  shifts *sp;
413  int length;
414  int nedges;
415  int done1;
416  int state1;
417  int stateno;
418  int symbol1;
419  int symbol2;
420  short *shortp;
421  short *edge;
422  short *states;
423  short **new_includes;
424
425  includes = NEW2(ngotos, short *);
426  edge = NEW2(ngotos + 1, short);
427  states = NEW2(maxrhs + 1, short);
428
429  for (i = 0; i < ngotos; i++)
430    {
431      nedges = 0;
432      state1 = from_state[i];
433      symbol1 = accessing_symbol[to_state[i]];
434
435      for (rulep = derives[symbol1]; *rulep >= 0; rulep++)
436	{
437	  length = 1;
438	  states[0] = state1;
439	  stateno = state1;
440
441	  for (rp = ritem + rrhs[*rulep]; *rp >= 0; rp++)
442	    {
443	      symbol2 = *rp;
444	      sp = shift_table[stateno];
445	      k = sp->nshifts;
446
447	      for (j = 0; j < k; j++)
448		{
449		  stateno = sp->shift[j];
450		  if (accessing_symbol[stateno] == symbol2) break;
451		}
452
453	      states[length++] = stateno;
454	    }
455
456	  add_lookback_edge(stateno, *rulep, i);
457
458	  length--;
459	  done1 = 0;
460	  while (!done1)
461	    {
462	      done1 = 1;
463	      rp--;
464	      if (ISVAR(*rp))
465		{
466		  stateno = states[--length];
467		  edge[nedges++] = map_goto(stateno, *rp);
468		  if (nullable[*rp] && length > 0) done1 = 0;
469		}
470	    }
471	}
472
473      if (nedges)
474	{
475	  includes[i] = shortp = NEW2(nedges + 1, short);
476	  for (j = 0; j < nedges; j++)
477	    shortp[j] = edge[j];
478	  shortp[nedges] = -1;
479	}
480    }
481
482  new_includes = transpose(includes, ngotos);
483
484  for (i = 0; i < ngotos; i++)
485    if (includes[i])
486      free(includes[i]);
487
488  free(includes);
489
490  includes = new_includes;
491
492  free(edge);
493  free(states);
494}
495
496
497static void
498add_lookback_edge(int stateno, int ruleno, int gotono)
499{
500    int i, k;
501    int found;
502    shorts *sp;
503
504    i = lookaheads[stateno];
505    k = lookaheads[stateno + 1];
506    found = 0;
507    while (!found && i < k)
508    {
509	if (LAruleno[i] == ruleno)
510	    found = 1;
511	else
512	    ++i;
513    }
514    assert(found);
515
516    sp = NEW(shorts);
517    sp->next = lookback[i];
518    sp->value = gotono;
519    lookback[i] = sp;
520}
521
522
523
524static short **
525transpose(short **R, int n)
526{
527  short **new_R;
528  short **temp_R;
529  short *nedges;
530  short *sp;
531  int i;
532  int k;
533
534  nedges = NEW2(n, short);
535
536  for (i = 0; i < n; i++)
537    {
538      sp = R[i];
539      if (sp)
540	{
541	  while (*sp >= 0)
542	    nedges[*sp++]++;
543	}
544    }
545
546  new_R = NEW2(n, short *);
547  temp_R = NEW2(n, short *);
548
549  for (i = 0; i < n; i++)
550    {
551      k = nedges[i];
552      if (k > 0)
553	{
554	  sp = NEW2(k + 1, short);
555	  new_R[i] = sp;
556	  temp_R[i] = sp;
557	  sp[k] = -1;
558	}
559    }
560
561  free(nedges);
562
563  for (i = 0; i < n; i++)
564    {
565      sp = R[i];
566      if (sp)
567	{
568	  while (*sp >= 0)
569	    *temp_R[*sp++]++ = i;
570	}
571    }
572
573  free(temp_R);
574
575  return (new_R);
576}
577
578
579
580static void
581compute_FOLLOWS(void)
582{
583  digraph(includes);
584}
585
586
587static void
588compute_lookaheads(void)
589{
590  int i, n;
591  unsigned *fp1, *fp2, *fp3;
592  shorts *sp, *next;
593  unsigned *rowp;
594
595  rowp = LA;
596  n = lookaheads[nstates];
597  for (i = 0; i < n; i++)
598    {
599      fp3 = rowp + tokensetsize;
600      for (sp = lookback[i]; sp; sp = sp->next)
601	{
602	  fp1 = rowp;
603	  fp2 = F + tokensetsize * sp->value;
604	  while (fp1 < fp3)
605	    *fp1++ |= *fp2++;
606	}
607      rowp = fp3;
608    }
609
610  for (i = 0; i < n; i++)
611    for (sp = lookback[i]; sp; sp = next)
612      {
613        next = sp->next;
614        free(sp);
615      }
616
617  free(lookback);
618  free(F);
619}
620
621
622static void
623digraph(short **relation)
624{
625  int i;
626
627  infinity = ngotos + 2;
628  INDEX = NEW2(ngotos + 1, short);
629  VERTICES = NEW2(ngotos + 1, short);
630  top = 0;
631
632  for (i = 0; i < ngotos; i++)
633    INDEX[i] = 0;
634
635  for (i = 0; i < ngotos; i++)
636    {
637      if (INDEX[i] == 0 && relation[i])
638	traverse(i, relation);
639    }
640
641  free(INDEX);
642  free(VERTICES);
643}
644
645
646
647static void
648traverse(int i, short **R)
649{
650  unsigned *fp1;
651  unsigned *fp2;
652  unsigned *fp3;
653  int j;
654  short *rp;
655
656  int height;
657  unsigned *base;
658
659  VERTICES[++top] = i;
660  INDEX[i] = height = top;
661
662  base = F + i * tokensetsize;
663  fp3 = base + tokensetsize;
664
665  rp = R[i];
666  if (rp)
667    {
668      while ((j = *rp++) >= 0)
669	{
670	  if (INDEX[j] == 0)
671	    traverse(j, R);
672
673	  if (INDEX[i] > INDEX[j])
674	    INDEX[i] = INDEX[j];
675
676	  fp1 = base;
677	  fp2 = F + j * tokensetsize;
678
679	  while (fp1 < fp3)
680	    *fp1++ |= *fp2++;
681	}
682    }
683
684  if (INDEX[i] == height)
685    {
686      for (;;)
687	{
688	  j = VERTICES[top--];
689	  INDEX[j] = infinity;
690
691	  if (i == j)
692	    break;
693
694	  fp1 = base;
695	  fp2 = F + j * tokensetsize;
696
697	  while (fp1 < fp3)
698	    *fp2++ = *fp1++;
699	}
700    }
701}