5 compile with -DNOFIRST to disable firstset optimization
6 -DFOLLOW_OPT to enable followset optimization
7 NOTE: Followset optimization is not
8 supported when using -s option of LLgen
9 -DDEBUG to print debug information
13 extern int LLstartsymb;
22 /* Acces to the stacks is through a 'dynamic array' of pointers
23 * to the heads. We implemented it this way to save on the number
24 * of Malloc() calls. nr_heads is the number of heads; heads_buf_size
25 * is the current size of heads_buf.
29 struct stack_elt **heads_buf;
32 /* r_rec contains nonterminals already tried to build a new
33 * stack with, to prevent right-recursive rules making the
34 * process loop forever
37 char r_rec[(LLNNONTERMINALS + 7)/8];
39 /* join_array contains pointers to already substituted stack
40 * elements, so that if the same nonterminal turns up again
44 struct stack_elt *join_array[LLNNONTERMINALS];
46 /* cleanup_buf contains pointerts to elements that can possibly
47 * be deleted. Again this is implemented as a `growing array'.
48 * Although it's not so clean to do it this way, it DOES save
49 * a lot of time, mainly because much less pointer manipulation
50 * is required, and because it's not necessary to deallocate
51 * the buffer after each turn. Just set nr_cleanups to 0...
56 struct stack_elt **cleanup_buf;
58 /* visited_buf contains pointers to elements whose flags
64 struct stack_elt **visited_buf;
67 /* start_seen indicates if the last prediction phase
68 * has matched the start symbol
73 /* exp_terminals will contain the terminals that are `on top'
74 * of the prediction graph after a prediction phase
77 char exp_terminals[LLSETSIZE];
79 /* check_run_ok indicates whether a stack element can be deleted
88 static int allocates = 0;
89 static int deallocates = 0;
90 static int max_in_use = 0;
91 static int edge_allocates = 0;
92 static int edge_deallocates = 0;
93 static int edge_max_in_use = 0;
96 static int grammar_index = 0;
98 /* The grammar should only be build the first time we enter the
99 * recovery routine. grammar_read == 0 indicates this has not
103 static int grammar_read = 0;
105 /* 'terminals' is an array indexed by the number of a terminal and links
106 * all rules containing this terminal in the RHS
109 static struct terminal *terminals;
111 /* 'nonterminals' is an array indexed by the number of a nonterminal
112 * and contains all rules with this nonterminal in the LHS and links all
113 * rules containing this nonterminal in the RHS
116 static struct nonterminal *nonterminals;
119 /* These functions must be called instead of the original functions in
120 * 'malloc.h'. They offer a checking allocation mechanism.
123 static char *Malloc(unsigned);
124 static char *Realloc(char*, unsigned);
128 static char *Malloc();
129 static char *Realloc();
133 /* These functions build the grammar */
135 static void init_grammar(void);
136 static void build_grammar(void);
137 static struct lhs *build_rule(void);
138 static struct symbol *build_rhs(struct lhs*);
139 static struct symbol *make_link(struct symbol*);
143 static init_grammar();
144 static build_grammar();
145 static struct lhs *build_rule();
146 static struct symbol *build_rhs();
147 static struct symbol *make_link();
151 /* These functions operate on the stacks */
153 static int optimize(struct stacks*, struct symbol*, int);
154 static void read_token(void);
155 static void start_stack(struct stacks*, int, int);
156 static void continuation(struct stacks*, int, int);
157 static struct stack_elt *push_rule(struct stack_elt*, struct symbol*);
158 static void new_head(struct stacks*, struct stack_elt*);
159 static void to_delete(struct stacks*, struct stack_elt*);
160 static void substitute(struct stacks*, struct stack_elt*, int);
161 static int join(struct stacks*, struct stack_elt*, int);
162 static int path(struct stack_elt*, struct stack_elt*);
163 static int part_of_loop(struct stack_elt*);
164 static void generate_heads(struct stacks*, struct stack_elt*, int);
165 static void delete(struct stacks*, struct stack_elt*);
166 static void hyp_run(struct stack_elt*);
167 static void check_run(struct stacks*, struct stack_elt*);
168 static struct stack_elt *split(struct stack_elt*);
170 static void test(struct stacks*);
171 static void dump_stack(struct stack_elt*, int);
173 static void clear_flags(struct stack_elt*, char);
174 static void clear_gen_flags(struct stacks*);
175 static void match_heads(struct stacks*, int);
176 static void cleanup(struct stacks*);
177 static void initialize(struct stacks*);
178 static void calculate(struct stacks*, int);
179 static void kill_stack(struct stacks *stack);
180 void LLnc_recover(void);
184 static int optimize();
186 static start_stack();
187 static continuation();
188 static struct stack_elt *push_rule();
194 static int part_of_loop();
195 static generate_heads();
199 static struct stack_elt *split();
202 static clear_flags();
203 static clear_gen_flags();
204 static match_heads();
214 static char *Malloc(unsigned size)
216 static char *Malloc(size)
222 if ((p = malloc(size)) == (char *)0) {
223 fprintf(stderr, "fatal error: out of memory\n");
231 static char *Realloc(char *ptr, unsigned size)
233 static char *Realloc(ptr, size)
240 if ((p = realloc(ptr, size)) == (char *)0) {
241 fprintf(stderr, "fatal error: out of memory\n");
249 static void init_grammar(void)
251 static init_grammar()
254 /* Allocate and initialize an array for terminals and nonterminals */
258 terminals = (struct terminal *)
259 Malloc((unsigned) LLFIRST_NT * sizeof(struct terminal));
260 for (i = 0; i < LLFIRST_NT; i++) {
261 (terminals + i)->link = (struct symbol *)0;
264 nonterminals = (struct nonterminal *)
265 Malloc((unsigned)LLNNONTERMINALS * sizeof(struct nonterminal));
266 for (i = 0; i < LLNNONTERMINALS; i++) {
267 (nonterminals + i)->rule = (struct lhs *)0;
268 (nonterminals + i)->link = (struct symbol *)0;
274 static void build_grammar(void)
276 static build_grammar()
279 /* Build a rule for every nonterminal. The LHS must be saved first because
280 * of the fact that the right side of an assignment statement (in C) will
281 * be evaluated before the left side
286 for (j = 0; j < LLNNONTERMINALS; j++) {
287 nt = LLgrammar[grammar_index];
288 (nonterminals + nt - LLFIRST_NT)->rule = build_rule();
294 static struct lhs *build_rule(void)
296 static struct lhs *build_rule()
299 /* Build LHS and call a funcion to create RHS */
304 l = (struct lhs *)Malloc(sizeof(struct lhs));
305 l->nr = LLgrammar[grammar_index++];
307 /* Build first set */
308 for (j = 0; j < LLSETSIZE; j++) {
309 l->first[j] = LLgrammar[grammar_index++];
312 /* Build follow set */
313 for (j = 0; j < LLSETSIZE; j++) {
314 l->follow[j] = LLgrammar[grammar_index++];
317 l->empty = LLgrammar[grammar_index++]; /* Can NT produce empty? */
319 l->rhs = build_rhs(l);
326 static struct symbol *build_rhs(struct lhs *l)
328 static struct symbol *build_rhs(l)
332 /* Build RHS by creating structs for all symbols including ALT and
333 * EORULE. Also call a function for linking same terminals and
339 r = (struct symbol *)Malloc(sizeof(struct symbol));
340 if (LLgrammar[grammar_index] == LLALT) {
343 r->nr = -1; /* Not applicable */
344 r->link = (struct symbol *)0; /* Not applicable */
345 r->next = build_rhs(l);
348 else if (LLgrammar[grammar_index] == LLEORULE) {
351 r->nr = -1; /* Not applicable */
352 r->link = (struct symbol *)0; /* Not applicable */
353 r->next = (struct symbol *)0; /* Not applicable */
356 else if (LLgrammar[grammar_index] < LLFIRST_NT) {
358 r->nr = LLgrammar[grammar_index++];
359 r->link = make_link(r);
360 r->next = build_rhs(l);
364 r->x = LLNONTERMINAL;
365 r->nr = LLgrammar[grammar_index++];
366 r->link = make_link(r);
367 r->next = build_rhs(l);
375 static struct symbol *make_link(struct symbol *r)
377 static struct symbol *make_link(r)
381 /* Link same terminals and nonterminals. Every new symbol is appended
382 * in front of the corresponding list for efficiency.
387 if (r->nr < LLFIRST_NT) {
389 tmp = (terminals + r->nr)->link;
390 (terminals + r->nr)->link = r;
392 else { /* Nonterminal array */
393 tmp = (nonterminals + (r->nr - LLFIRST_NT))->link;
394 (nonterminals + (r->nr - LLFIRST_NT))->link = r;
400 /*****************************************************************************/
404 static int optimize(struct stacks* stack, struct symbol *symb_ptr, int l_ahead)
406 static int optimize(stack, symb_ptr, l_ahead)
407 struct stacks *stack;
408 struct symbol *symb_ptr;
412 /* Return 1 if rule symb_ptr can start with terminal l_ahead, else return 0.
413 * The array with expected terminals will also be filled in.
423 if ((l_ahead <= 0) || (l_ahead == EOFILE)) return 1;
425 switch(symb_ptr->x) {
427 LLPUTIN(stack->exp_terminals, LLindex[symb_ptr->nr]);
428 if (symb_ptr->nr != l_ahead) return 0;
429 else return 1;/*???*/
432 l = (nonterminals + symb_ptr->nr - LLFIRST_NT)->rule;
433 if (LLIN(l->first, LLindex[l_ahead])) return 1;
435 /* Try next symbol */
436 return optimize(stack, symb_ptr->next, l_ahead);
439 for (i = 0; i < LLSETSIZE; i++) {
440 stack->exp_terminals[i] |= (l->first)[i];
451 l = (nonterminals + symb_ptr->lhs->nr - LLFIRST_NT)->rule;
453 if (LLIN(l->follow, LLindex[l_ahead])) return 1;
455 for (i = 0; i < LLSETSIZE; i++) {
456 stack->exp_terminals[i] |= (l->follow)[i];
460 #endif /*FOLLOW_OPT */
467 static void read_token(void)
472 /* Read token and put it in global variable LLsymb, skipping
477 while (LLindex[LLsymb] < 0) {
478 /* Skip garbage tokens */
486 static void start_stack(struct stacks *stack, int base, int l_ahead)
488 static start_stack(stack, base, l_ahead)
489 struct stacks *stack;
493 /* Start stack on base symbol base with lookahead l_ahead */
496 struct stack_elt *bottom, *top;
497 struct symbol *symb_ptr;
500 /* Find first applicable rule */
501 symb_ptr = (terminals + base)->link;
503 /* Now try all applicable rules */
504 while (symb_ptr != (struct symbol *)0) {
506 /* If the current rule cannot start with l_ahead,
509 if (!optimize(stack, symb_ptr->next, l_ahead)) {
510 symb_ptr = symb_ptr->link;
514 if ( (symb_ptr->next->x == LLTERMINAL)
515 || (symb_ptr->next->x == LLNONTERMINAL)
517 /* Allocate an end-of-stack */
520 if (allocates - deallocates > max_in_use) {
521 max_in_use = allocates - deallocates;
524 bottom = (struct stack_elt *)
525 Malloc(sizeof(struct stack_elt));
526 bottom->edges = (struct edge *)0;
527 bottom->nr = LLEOSTACK;
529 bottom->nr_nexts = 0;
530 bottom->ref_count = 0;
531 bottom->hyp_ref_count = -1;
533 /* And use the rule to build a stack on it */
534 top = push_rule(bottom, symb_ptr->next);
536 /* Remember that we're now trying to match the LHS
539 bottom->matched = symb_ptr->lhs->nr;
541 if (top->nr >= LLFIRST_NT) {
542 substitute(stack, top, l_ahead);
545 new_head(stack, top);
548 /* Perhaps this only has produced an empty stack, in
549 * that case bottom can be deallocated.
551 if (bottom->ref_count == 0) {
552 to_delete(stack, bottom);
556 /* base was the last element of the rule, so we
557 * figure we have matched the LHS of this rule.
559 if (symb_ptr->lhs->nr == LLstartsymb) {
560 stack->start_seen = 1;
563 continuation(stack, symb_ptr->lhs->nr, l_ahead);
565 symb_ptr = symb_ptr->link;
569 /* Reinitialize some arrays */
570 for (i = 0; i < (LLNNONTERMINALS + 7)/8; i++) {
571 stack->r_rec[i] = (char) 0;
574 for (i = 0; i < LLNNONTERMINALS; i++) {
575 stack->join_array[i] = (struct stack_elt *)0;
578 /* Delete all HEAD flags */
579 for (i = 0; i < stack->nr_heads; i++) {
580 (*(stack->heads_buf + i))->flags &= ~LLHEAD;
583 /* Delete flags turned on by 'generate_heads()' */
584 clear_gen_flags(stack);
585 /* Try to delete elements on cleanup_buf */
591 static void continuation(struct stacks *stack, int nt, int l_ahead)
593 static continuation(stack, nt, l_ahead)
594 struct stacks *stack;
598 /* We have 'eaten' a whole stack, and think we recognized nt. Now
599 look for rules that we can proceed with, ie containing nt in the RHS.
600 Each rule found will be developed untill a terminal is at the top
604 struct symbol *symb_ptr;
605 struct stack_elt *bottom, *top;
607 /* If we've already tried this nt, don't do it again.
608 * Otherwise we may loop forever on right-recursive rules
610 if (LLIN(stack->r_rec, nt - LLFIRST_NT)) return;
612 /* Mark that we have looked for a continuation for nt */
613 LLPUTIN(stack->r_rec, nt - LLFIRST_NT);
615 /* Find first applicable rule */
616 symb_ptr = (nonterminals + nt - LLFIRST_NT)->link;
618 /* Try all applicable rules */
619 while (symb_ptr != (struct symbol *)0) {
621 /* If the current rule cannot start with l_ahead,
624 if (!optimize(stack, symb_ptr->next, l_ahead)) {
625 symb_ptr = symb_ptr->link;
629 if ( (symb_ptr->next->x == LLTERMINAL)
630 || (symb_ptr->next->x == LLNONTERMINAL)
634 if (allocates - deallocates > max_in_use) {
635 max_in_use = allocates - deallocates;
638 bottom = (struct stack_elt *)
639 Malloc(sizeof(struct stack_elt));
640 bottom->edges = (struct edge *)0;
641 bottom->nr = LLEOSTACK;
643 bottom->nr_nexts = 0;
644 bottom->ref_count = 0;
645 bottom->hyp_ref_count = -1;
647 /* Use the rule to build a stack on bottom */
648 top = push_rule(bottom, symb_ptr->next);
650 /* Remember that we're now trying to match the LHS
653 bottom->matched = symb_ptr->lhs->nr;
655 if (top->nr >= LLFIRST_NT) {
656 substitute(stack, top, l_ahead);
659 new_head(stack, top);
662 /* Perhaps this only has produced an empty stack, in
663 * that case bottom can be deallocated.
665 if (bottom->ref_count == 0) {
666 delete(stack, bottom);
670 /* Stack is still empty */
671 if (symb_ptr->lhs->nr == LLstartsymb) {
672 stack->start_seen = 1;
675 continuation(stack, symb_ptr->lhs->nr, l_ahead);
678 symb_ptr = symb_ptr->link;
684 static struct stack_elt *push_rule(struct stack_elt *element,
685 struct symbol *symb_ptr)
687 static struct stack_elt *push_rule(element, symb_ptr)
688 struct stack_elt *element;
689 struct symbol *symb_ptr;
692 /* Append the rule symb_ptr to stack element 'element'. Return a
693 * pointer to the new top of the stack
696 struct stack_elt *se, *top;
698 if ( (symb_ptr->next->x == LLTERMINAL)
699 || (symb_ptr->next->x == LLNONTERMINAL)
701 top = push_rule(element, symb_ptr->next);
709 if (allocates - deallocates > max_in_use) {
710 max_in_use = allocates - deallocates;
714 se = (struct stack_elt *)Malloc(sizeof(struct stack_elt));
716 se->nr = symb_ptr->nr;
718 se->hyp_ref_count = -1;
724 if (edge_allocates - edge_deallocates > edge_max_in_use) {
725 edge_max_in_use = edge_allocates - edge_deallocates;
729 se->edges = (struct edge *)Malloc(sizeof(struct edge));
730 se->edges->ptr = top;
731 se->edges->flags = 0;
739 static void new_head(struct stacks *stack, struct stack_elt *ptr)
741 static new_head(stack, ptr)
742 struct stacks *stack;
743 struct stack_elt *ptr;
746 /* Make ptr a head of stack */
749 /* Is this already a head?*/
750 if (ptr->flags & LLHEAD) return;
752 if (stack->heads_buf_size == 0) {
753 stack->heads_buf_size = LLHEADS_BUF_INCR;
754 stack->heads_buf = (struct stack_elt **)
755 Malloc(LLHEADS_BUF_INCR * sizeof(struct stack_elt *));
757 else if (stack->nr_heads == stack->heads_buf_size) {
759 stack->heads_buf_size += LLHEADS_BUF_INCR;
760 stack->heads_buf = (struct stack_elt **)
762 stack->heads_buf, (unsigned)
763 stack->heads_buf_size *
764 sizeof(struct stack_elt *)
768 *(stack->heads_buf + stack->nr_heads) = ptr; /* Add at the tail */
769 stack->nr_heads++; /* Increase number of heads */
770 ptr->flags |= LLHEAD; /* Mark it as a head */
771 ptr->ref_count++; /* Increase reference count */
772 LLPUTIN(stack->exp_terminals, LLindex[ptr->nr]);
777 static void to_delete(struct stacks *stack, struct stack_elt *ptr)
779 static to_delete(stack, ptr)
780 struct stacks *stack;
781 struct stack_elt *ptr;
784 /* Remember that ptr has to be deleted */
795 for (i = 0; i < stack->nr_cleanups; i++) {
796 /* Check if already in buffer */
797 if (*(stack->cleanup_buf + i) == ptr) return;
800 if (stack->cleanup_buf_size == 0) {
801 stack->cleanup_buf_size = LLCLEANUP_BUF_INCR;
802 stack->cleanup_buf = (struct stack_elt **)
803 Malloc(LLCLEANUP_BUF_INCR * sizeof(struct stack_elt *));
805 else if (stack->nr_cleanups == stack->cleanup_buf_size) {
806 stack->cleanup_buf_size += LLCLEANUP_BUF_INCR;
807 stack->cleanup_buf = (struct stack_elt **)
808 Realloc((char *) stack->cleanup_buf,
809 (unsigned) stack->cleanup_buf_size *
810 sizeof(struct stack_elt *));
812 *(stack->cleanup_buf + stack->nr_cleanups) = ptr;
813 stack->nr_cleanups++;
818 static void substitute(struct stacks *stack, struct stack_elt *top, int l_ahead)
820 static substitute(stack, top, l_ahead)
821 struct stacks *stack;
822 struct stack_elt *top;
826 /* This function substitutes the NT pointed to by 'top'. 'top' should be a top
830 struct symbol *symb_ptr;
831 struct stack_elt *new_top;
833 /* Try to join top NT */
834 if (join(stack, top, l_ahead)) return;
836 /* Find RHS of the rule of nonterminal 'top->nr' */
837 symb_ptr = (nonterminals + top->nr - LLFIRST_NT)->rule->rhs;
839 /* Mark top as dummy */
840 top->flags |= LLDUMMY;
843 /* If this an empty production, search down the stack for
846 if ((symb_ptr->x == LLALT) || (symb_ptr->x == LLEORULE)) {
847 generate_heads(stack, top, l_ahead);
850 /* Skip other empty productions, they have no effect. */
851 while (symb_ptr->x == LLALT) {
852 symb_ptr = symb_ptr->next;
855 if (symb_ptr->x == LLEORULE) {
856 /* If there are only empty productions, the NT on top
859 if (top->ref_count == 0) {
860 to_delete(stack, top);
865 /* If this rule can produce 'l_ahead' on the top of the stack
866 * substitute the nonterminal
868 if (optimize(stack, symb_ptr, l_ahead)) {
869 new_top = push_rule(top, symb_ptr);
871 /* If the new element on top is a nonterminal
872 * substitute it, else make it a head
874 if (new_top->nr >= LLFIRST_NT) {
875 substitute(stack, new_top, l_ahead);
878 new_head(stack, new_top);
882 /* Search to next alternative */
883 while ( (symb_ptr->x == LLTERMINAL)
884 || (symb_ptr->x == LLNONTERMINAL)
886 symb_ptr = symb_ptr->next;
889 if (symb_ptr->x == LLEORULE) {
890 if (top->ref_count == 0) {
891 to_delete(stack, top);
896 symb_ptr = symb_ptr->next;
904 static int join(struct stacks *stack, struct stack_elt *top, int l_ahead)
906 static int join(stack, top, l_ahead)
907 struct stacks *stack;
908 struct stack_elt *top;
912 /* This function tries to connect a NT on top of a stack with another stack,
913 * which has already substituted this NT
916 struct stack_elt *se;
919 if ( (se = stack->join_array[top->nr - LLFIRST_NT]) ==
920 (struct stack_elt *)0
922 stack->join_array[top->nr - LLFIRST_NT] = top;
923 return 0; /* Join not possible */
926 se->nr_nexts++; /* Increase number of descendants */
930 if (edge_allocates - edge_deallocates > edge_max_in_use) {
931 edge_max_in_use = edge_allocates - edge_deallocates;
935 /* Allocate one more pointer to descendants */
936 size = se->nr_nexts * sizeof(struct edge);
937 se->edges = (struct edge *)Realloc((char *) se->edges,
941 (se->edges + se->nr_nexts - 1)->ptr = top->edges->ptr;
942 (se->edges + se->nr_nexts - 1)->flags = 0;
944 /* The successor of 'top' gets an extra predecessor.
945 * 'top' has always only one successor because the stacks are
946 * constructed in 'depth first' order
948 top->edges->ptr->ref_count++;
952 /* If we have made a new loop find all stack elements of this
955 if (path(top->edges->ptr, se)) {
956 (se->edges + se->nr_nexts - 1)->flags |= LLLOOP;
957 (se->edges + se->nr_nexts - 1)->flags |= LLYES;
959 clear_flags(top->edges->ptr, (LLNO | LLYES));
963 /* Check if joined NT produces empty */
964 if ((nonterminals + se->nr - LLFIRST_NT)->rule->empty) {
965 generate_heads(stack, top, l_ahead);
968 /* Deallocate top symbol */
969 if (top->ref_count == 0) {
970 to_delete(stack, top);
981 static int path(struct stack_elt *se1, struct stack_elt *se2)
983 static int path(se1, se2)
984 struct stack_elt *se1, *se2;
985 #endif /* LL_ANSI_C */
987 /* If there is a path from se1 to se2 it returns 1 and marks all the paths
988 * betweeen these two points, otherwise it returns 0. The flags LLYES and
989 * LLNO are used for optimization. */
993 if (se1 == se2) return 1;
995 for (i = 0; i < se1->nr_nexts; i++) {
996 if ( (!((se1->edges + i)->flags & LLNO))
997 && (!((se1->edges + i)->flags & LLLOOP_SEARCH))
999 (se1->edges + i)->flags |= LLLOOP_SEARCH;
1001 if (path((se1->edges + i)->ptr, se2)) {
1002 (se1->edges + i)->flags |= LLLOOP;
1006 (se1->edges + i)->flags |= LLNO;
1009 (se1->edges + i)->flags &= ~LLLOOP_SEARCH;
1011 (se1->edges + i)->flags |= LLYES;
1018 static int part_of_loop(struct stack_elt *se)
1020 static int part_of_loop(se)
1021 struct stack_elt *se;
1022 #endif /* LL_ANSI_C */
1024 /* Checks if 'se' belongs to a loop */
1028 for (i = 0; i < se->nr_nexts; i++) {
1029 if ((se->edges + i)->flags & LLLOOP) return 1;
1034 #endif /* NOLOOPS */
1038 static void generate_heads(struct stacks *stack, struct stack_elt *se,
1041 static generate_heads(stack, se, l_ahead)
1042 struct stacks *stack;
1043 struct stack_elt *se;
1047 /* This funcion finds all heads starting at 'se'. */
1050 struct stack_elt *next_se;
1053 for (i = 0; i < se->nr_nexts; i++) {
1055 if (!((se->edges + i)->ptr->flags & LLGEN_SEARCH)) {
1057 (se->edges + i)->ptr->flags |= LLGEN_SEARCH;
1059 next_se = (se->edges + i)->ptr;
1061 /* Remember a flag has to be cleared later */
1063 if (stack->visited_buf_size == 0) {
1064 stack->visited_buf_size = LL_VIS_INCR;
1065 stack->visited_buf = (struct stack_elt **)
1066 Malloc(LL_VIS_INCR * sizeof(struct stack_elt *));
1068 else if (stack->nr_visited == stack->visited_buf_size) {
1069 stack->visited_buf_size += LL_VIS_INCR;
1070 stack->visited_buf = (struct stack_elt **)
1071 Realloc((char *) stack->visited_buf,
1072 (unsigned) stack->visited_buf_size *
1073 sizeof(struct stack_elt *));
1075 *(stack->visited_buf + stack->nr_visited) = next_se;
1076 stack->nr_visited++;
1078 if (next_se->flags & LLDUMMY) {
1079 generate_heads(stack, next_se, l_ahead);
1081 else if (next_se->nr == LLEOSTACK) {
1082 /* We have matched a nt */
1083 if (next_se->matched == LLstartsymb) {
1084 stack->start_seen = 1;
1087 continuation(stack, next_se->matched, l_ahead);
1088 if (next_se->ref_count == 0) {
1089 to_delete(stack, next_se);
1092 else if (next_se->nr < LLFIRST_NT) {
1094 new_head(stack, next_se);
1097 if (next_se->ref_count > 0) {
1098 next_se = split(next_se);
1100 substitute(stack, next_se, l_ahead);
1108 static void delete(struct stacks *stack, struct stack_elt *se)
1110 static delete(stack, se)
1111 struct stacks *stack;
1112 struct stack_elt *se;
1115 /* This function runs down the stack(s) deleting every element which cannot be
1116 * reached anymore. */
1124 if (se->ref_count == 0) {
1126 /* Decrease reference counts of all successors */
1127 for (i = 0; i < se->nr_nexts; i++) {
1128 if ((se->edges + i)->ptr->ref_count != 0) {
1129 (se->edges + i)->ptr->ref_count--;
1131 /* Try to delete next element */
1132 delete(stack, (se->edges + i)->ptr);
1136 /* If this element is saved in the join_array clear it */
1137 if (se->nr >= LLFIRST_NT) {
1138 if (stack->join_array[se->nr - LLFIRST_NT] == se) {
1139 stack->join_array[se->nr - LLFIRST_NT] =
1140 (struct stack_elt *)0;
1145 edge_deallocates += se->nr_nexts;
1147 free((char *) se->edges);
1152 /* If this element belongs to a loop try to delete it */
1153 else if (part_of_loop(se)) {
1155 /* Do a temporary delete */
1159 stack->check_run_ok = 1;
1160 check_run(stack, se);
1162 /* If it can be deleted delete it */
1163 if (stack->check_run_ok) {
1176 static void hyp_run(struct stack_elt *se)
1179 struct stack_elt *se;
1180 #endif /* LL_ANSI_C */
1182 /* This function sets the 'hyp_ref_counts' of all elements of the loop that
1183 * 'se' belongs to to the value that 'ref_count' will get when 'se' is
1188 struct stack_elt *next_se;
1190 for (i = 0; i < se->nr_nexts; i++) {
1191 next_se = (se->edges + i)->ptr;
1193 if ( (!((se->edges + i)->flags & LLHYP_SEARCH))
1194 && ((se->edges + i)->flags & LLLOOP)
1196 (se->edges + i)->flags |= LLHYP_SEARCH;
1198 /* If this element is not yet visited initialize
1199 * 'hyp_ref_count' else decrease it by one
1201 if (next_se->hyp_ref_count == -1) {
1202 next_se->hyp_ref_count = next_se->ref_count - 1;
1205 next_se->hyp_ref_count--;
1208 /* Continue searching */
1216 static void check_run(struct stacks *stack, struct stack_elt *se)
1218 static check_run(stack, se)
1219 struct stacks *stack;
1220 struct stack_elt *se;
1221 #endif /* LL_ANSI_C */
1223 /* This function checks all 'hyp_ref_counts' that 'hyp_run()' has set.
1224 * If one of them is not 0, 'check_run_ok' will be set to 0 indicating
1225 * that 'se' cannot be deleted. 'check_run()' also resets all 'hyp_ref_counts'
1230 if (se->hyp_ref_count > 0) {
1231 stack->check_run_ok = 0;
1234 /* Reset 'hyp_ref_count' */
1235 se->hyp_ref_count = -1;
1236 for (i = 0; i < se->nr_nexts; i++) {
1237 if ((se->edges + i)->flags & LLHYP_SEARCH) {
1238 (se->edges + i)->flags &= ~LLHYP_SEARCH;
1239 check_run(stack, (se->edges + i)->ptr);
1244 #endif /* NOLOOPS */
1248 static struct stack_elt *split(struct stack_elt *se)
1250 static struct stack_elt *split(se)
1251 struct stack_elt *se;
1254 /* This function splits of a NT in de stack, and returns a pointer to it */
1256 struct stack_elt *new_stack;
1261 if (allocates - deallocates > max_in_use) {
1262 max_in_use = allocates - deallocates;
1266 new_stack = (struct stack_elt *)Malloc(sizeof(struct stack_elt));
1267 new_stack->flags = 0; /* Used by 'clear_gen_flags()' */
1268 new_stack->nr = se->nr;
1269 new_stack->ref_count = 0; /* Copy is new top */
1270 new_stack->hyp_ref_count = -1;
1271 new_stack->matched = -1;
1272 new_stack->nr_nexts = se->nr_nexts;
1276 if (edge_allocates - edge_deallocates > edge_max_in_use) {
1277 edge_max_in_use = edge_allocates - edge_deallocates;
1281 new_stack->edges = (struct edge *)
1282 Malloc((unsigned)se->nr_nexts * sizeof(struct edge));
1284 /* Copy gets the same successors as the original */
1285 memcpy((char *) new_stack->edges, (char *) se->edges,
1286 se->nr_nexts * sizeof(struct edge));
1288 /* Each successor gets a new predecessor */
1289 for (i = 0; i < new_stack->nr_nexts; i++) {
1290 (new_stack->edges + i)->ptr->ref_count++;
1291 (new_stack->edges + i)->flags = 0;
1300 static void test(struct stacks *stack)
1303 struct stacks *stack;
1306 struct stack_elt *se;
1309 printf("STACKS:\n");
1310 for (i = 0; i < stack->nr_heads; i++) {
1311 printf("%2d: ", i + 1);
1312 if (*(stack->heads_buf + i) == (struct stack_elt *)0) {
1316 se = *(stack->heads_buf + i);
1318 clear_flags(se, PRINT_SEARCH);
1324 static void dump_stack(struct stack_elt *se, int level)
1326 static dump_stack(se, level)
1327 struct stack_elt *se;
1333 while (se->nr != LLEOSTACK) {
1334 if ((se->flags & LLDUMMY) && (se->nr_nexts > 1)) {
1335 printf("[%d] <%d,%d,%d>\n",
1336 se->nr, se->ref_count,
1340 for (j = 0; j < se->nr_nexts; j++) {
1341 for (i = 1; i <= level; i++) {
1344 printf("%d: ", j + 1);
1345 if (!((se->edges + j)->flags & PRINT_SEARCH)) {
1346 printf(" (%d) ", (se->edges + j)->flags);
1347 (se->edges + j)->flags |= PRINT_SEARCH;
1348 dump_stack((se->edges+j)->ptr,level+1);
1349 /*clear_flags((se->edges+j)->ptr,PRINT_SEARCH);*/
1358 if (se->flags & LLDUMMY) {
1359 printf("[%d] <%d,%d,%d> ",
1360 se->nr,se->ref_count,
1366 printf("%d <%d,%d,%d> ",
1367 se->nr, se->ref_count,
1372 if (!(se->edges->flags & PRINT_SEARCH)) {
1373 printf(" (%d) ", se->edges->flags);
1374 se->edges->flags |= PRINT_SEARCH;
1375 se = se->edges->ptr;
1389 static void clear_flags(struct stack_elt *se, char flag)
1391 static clear_flags(se, flag)
1392 struct stack_elt *se;
1396 /* Clears edge flag 'flag' */
1400 for (i = 0; i < se->nr_nexts; i++) {
1401 if ((se->edges + i)->flags & flag) {
1402 (se->edges + i)->flags &= ~flag; /* clear flag */
1403 clear_flags((se->edges + i)->ptr, flag);
1409 static void clear_gen_flags(struct stacks *stack)
1411 static clear_gen_flags(stack)
1412 struct stacks *stack;
1418 for (i = 0; i < stack->nr_visited; i++) {
1419 (*(stack->visited_buf + i))->flags &= ~(LLGEN_SEARCH);
1422 stack->nr_visited = 0;
1427 static void match_heads(struct stacks *stack, int symb)
1429 static match_heads(stack, symb)
1430 struct stacks *stack;
1434 /* Match heads_buf against symb, leaving only matching heads,
1435 * whilst deallocating the non-matching stacks
1441 struct stack_elt **old_heads_buf;
1444 /* Copy the 'old' heads */
1445 old_nr_heads = stack->nr_heads;
1446 old_heads_buf = stack->heads_buf;
1449 /* Set heads in stack to 0 */
1450 stack->nr_heads = 0;
1451 stack->heads_buf_size = 0;
1452 stack->heads_buf = (struct stack_elt **) 0;
1455 for (i = 0; i < old_nr_heads; i++) {
1456 if ((*(old_heads_buf + i))->nr != symb) {
1457 /* Does not match? */
1458 (*(old_heads_buf + i))->ref_count--;
1459 (*(old_heads_buf + i))->flags &= ~LLHEAD;
1460 delete(stack, *(old_heads_buf + i));
1462 else { /* Matches */
1463 if (stack->heads_buf_size == 0) {
1464 stack->heads_buf_size = LLHEADS_BUF_INCR;
1465 stack->heads_buf = (struct stack_elt **)
1466 Malloc((unsigned)stack->heads_buf_size *
1467 sizeof(struct stack_elt *));
1469 else if (stack->nr_heads == stack->heads_buf_size) {
1470 stack->heads_buf_size += LLHEADS_BUF_INCR;
1471 stack->heads_buf = (struct stack_elt **)
1472 Realloc((char *) stack->heads_buf,
1473 (unsigned) stack->heads_buf_size *
1474 sizeof(struct stack_elt *));
1476 *(stack->heads_buf + stack->nr_heads) =
1477 *(old_heads_buf + i);
1481 free((char *) old_heads_buf);
1486 static void cleanup(struct stacks *stack)
1488 static cleanup(stack)
1489 struct stacks *stack;
1492 /* Deletes all elements in 'cleanup_buf()' */
1496 for (i = 0; i < stack->nr_cleanups; i++) {
1497 delete(stack, *(stack->cleanup_buf + i));
1500 stack->nr_cleanups = 0;
1506 static void initialize(struct stacks *stack)
1508 static initialize(stack)
1509 struct stacks *stack;
1512 /* Initializes some variables and arrays */
1516 stack->nr_heads = 0;
1517 stack->heads_buf_size = 0;
1518 stack->heads_buf = (struct stack_elt **)0;
1520 stack->nr_cleanups = 0;
1521 stack->cleanup_buf_size = 0;
1522 stack->cleanup_buf = (struct stack_elt **)0;
1524 stack->nr_visited = 0;
1525 stack->visited_buf_size = 0;
1526 stack->visited_buf = (struct stack_elt **)0;
1528 for (j = 0; j < (LLNNONTERMINALS + 7)/8; j++) {
1529 stack->r_rec[j] = (char) 0;
1532 for (j = 0; j < LLNNONTERMINALS; j++) {
1533 stack->join_array[j] = (struct stack_elt *)0;
1536 for (j = 0; j < LLSETSIZE; j++) {
1537 stack->exp_terminals[j] = 0;
1540 stack->start_seen = 0;
1545 static void calculate(struct stacks *stack, int l_ahead)
1547 static calculate(stack, l_ahead)
1548 struct stacks *stack;
1552 /* This function finds all new heads and deletes the old heads */
1556 struct stack_elt **old_heads_buf;
1558 /* Make a copy of the heads */
1559 old_nr_heads = stack->nr_heads;
1560 old_heads_buf = stack->heads_buf;
1562 stack->nr_heads = 0;
1563 stack->heads_buf = (struct stack_elt **) 0;
1564 stack->heads_buf_size = 0;
1566 for (i = 0; i < old_nr_heads; i++) {
1567 /* Find all new heads */
1568 generate_heads(stack, *(old_heads_buf + i), l_ahead);
1569 clear_gen_flags(stack);
1571 /* Old head can be deleted now */
1572 (*(old_heads_buf + i))->ref_count--;
1573 delete(stack, *(old_heads_buf + i));
1578 free((char *) old_heads_buf);
1580 /* Reinitialize some things */
1581 for (i = 0; i < (LLNNONTERMINALS + 7)/8; i++) {
1582 stack->r_rec[i] = (char) 0;
1585 for (i = 0; i < LLNNONTERMINALS; i++) {
1586 stack->join_array[i] = (struct stack_elt *)0;
1589 /* Delete all HEAD flags */
1590 for (i = 0; i < stack->nr_heads; i++) {
1591 (*(stack->heads_buf + i))->flags &= ~LLHEAD;
1596 static void kill_stack(struct stacks *stack)
1598 static kill_stack(stack)
1599 struct stacks *stack;
1604 for (i = 0; i < stack->nr_heads; i++) {
1605 (*(stack->heads_buf + i))->ref_count--;
1606 delete(stack, *(stack->heads_buf + i));
1613 void LLnc_recover(void)
1618 /* This function contains the main loop for non correcting syntax error
1624 struct stacks stack;
1626 int max_nr_good_heads;
1630 max_nr_good_heads = 0;
1632 /* Grammar has to be read only once */
1633 if (!grammar_read) {
1638 /* Read first token */
1642 /* Check on end of file */
1643 if ((base_symb <= 0) || (base_symb == EOFILE)) {
1645 if ((nonterminals + LLstartsymb - LLFIRST_NT)->rule->empty != 1
1655 /* Read look ahead token */
1658 /* Now search applicable rules and starts the ball rolling */
1659 start_stack(&stack, base_symb, LLsymb);
1661 if (stack.nr_heads > max_nr_heads) {
1662 max_nr_heads = stack.nr_heads;
1666 /* Only matching heads are needed */
1667 match_heads(&stack, LLsymb);
1669 if (stack.nr_heads > max_nr_good_heads) {
1670 max_nr_good_heads = stack.nr_heads;
1678 /* Loop untill end of inputfile */
1679 while ((LLsymb > 0) && (LLsymb != EOFILE)) {
1680 /* When entering the loop LLsymb always contains the
1681 * symbol that was used as look_ahead to construct the stacks,
1682 * or, if optimization is OFF, it contains the symbol with
1683 * which the current heads have been matched
1686 if (stack.nr_heads == 0) {
1687 /* No more heads left */
1690 /* Restart the whole thing */
1693 /* The look-ahead caused the empty stack, don't
1694 * use it to start a new one !
1700 /* Check on end of file */
1701 if ((base_symb <= 0) || (base_symb == EOFILE)) {
1702 if ((nonterminals + LLstartsymb - LLFIRST_NT)->rule->empty != 1) {
1712 start_stack(&stack, base_symb, LLsymb);
1714 if (stack.nr_heads > max_nr_heads) {
1715 max_nr_heads = stack.nr_heads;
1719 match_heads(&stack, LLsymb);
1721 if (stack.nr_heads > max_nr_good_heads) {
1722 max_nr_good_heads = stack.nr_heads;
1729 /* Normal case starts here */
1730 stack.start_seen = 0;
1732 for (j = 0; j < LLSETSIZE; j++) {
1733 stack.exp_terminals[j] = 0;
1736 /* Read next symbol */
1739 /* Generate all new heads and delete old ones */
1740 calculate(&stack, LLsymb);
1742 /* Leave out not wanted heads */
1744 if (stack.nr_heads > max_nr_heads) {
1745 max_nr_heads = stack.nr_heads;
1748 match_heads(&stack, LLsymb);
1750 if (stack.nr_heads > max_nr_good_heads) {
1751 max_nr_good_heads = stack.nr_heads;
1762 /* End of file reached, check if we have seen a start symbol */
1763 if (stack.start_seen == 1) return;
1772 printf("Maximum number of heads: %d\n", max_nr_heads);
1773 printf("Maximum number of good heads: %d\n", max_nr_good_heads);
1774 printf("Number of node allocates: %d\n", allocates);
1775 printf("Number of node deallocates: %d\n", deallocates);
1776 printf("Maximum number of nodes in use: %8d\n", max_in_use);
1777 printf("Sizeof(struct stack_elt) = %8d\n", sizeof(struct stack_elt));
1778 printf(" --------x\n");
1779 printf(" %8d\n", max_in_use * sizeof(
1781 printf("Number of edge allocates: %d\n", edge_allocates);
1782 printf("Number of edge deallocates: %d\n", edge_deallocates);
1783 printf("Maximum number of edges in use: %8d\n", edge_max_in_use);
1784 printf("Sizeof(struct edge) = %8d\n", sizeof(struct edge));
1785 printf(" --------x\n");
1786 printf(" %8d\n", edge_max_in_use * sizeof(struct edge));