diff options
author | thegeorg <thegeorg@yandex-team.com> | 2024-05-17 12:00:42 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2024-05-17 12:10:14 +0300 |
commit | 2bd98b5c8ddd404f62db9f74144a763de01341cc (patch) | |
tree | 93040aaeb1b7076ec9e3de486128f99b44316e7f /contrib/tools/bison/src | |
parent | 3d339ed1c60a04d959a40aaa931e1792a1a9cabb (diff) | |
download | ydb-2bd98b5c8ddd404f62db9f74144a763de01341cc.tar.gz |
Sync contrib/tools/bison layout with upstream
59379f119eb5f2fd036edea64923ff53b96c9028
Diffstat (limited to 'contrib/tools/bison/src')
76 files changed, 30483 insertions, 0 deletions
diff --git a/contrib/tools/bison/src/AnnotationList.c b/contrib/tools/bison/src/AnnotationList.c new file mode 100644 index 0000000000..b5781766a4 --- /dev/null +++ b/contrib/tools/bison/src/AnnotationList.c @@ -0,0 +1,808 @@ +/* IELR's inadequacy annotation list. + + Copyright (C) 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include "AnnotationList.h" +#include "lalr.h" +#include "ielr.h" + +/** + * \pre + * - <tt>annotations_obstackp != NULL</tt>. + * \post + * - \c result is a new \c AnnotationList with one node whose: + * - \c inadequacyNode member is \c NULL. + * - \c contributions member is allocated with \c contribution_count + * uninitialized elements. + * - All memory was allocated on \c annotations_obstackp. + */ +static AnnotationList* +AnnotationList__alloc_on_obstack (ContributionIndex contribution_count, + struct obstack *annotations_obstackp) +{ + AnnotationList *result; + size_t contributions_size = + contribution_count * sizeof result->contributions[0]; + result = obstack_alloc (annotations_obstackp, + offsetof (AnnotationList, contributions) + + contributions_size); + result->next = NULL; + result->inadequacyNode = NULL; + return result; +} + +/** + * \pre + * - <tt>self != NULL</tt>. + * - <tt>0 <= ci < self->inadequacyNode->contributionCount</tt>. + * \post + * - \c result = true iff contribution \c ci in \c self represents an + * "always" contribution. + */ +static bool +AnnotationList__isContributionAlways (AnnotationList const *self, + ContributionIndex ci) +{ + aver (0 <= ci && ci < self->inadequacyNode->contributionCount); + return self->contributions[ci] == NULL; +} + +/** + * \pre + * - \c self is a single node. + * - \c self annotates the same state as every other node in \c list, and + * that state has \c nitems kernel items. + * \post + * - If the list \c list already contains an identical annotation to \c self, + * \c self was discarded, \c result is false, and the caller is responsible + * for the memory of \c self. + * - Otherwise, \c list now contains the node \c self, \c result is true, and + * \c list assumes responsibility for the memory of \c self. + * - The sort in \c list is: + * - Sort in reverse order on the unique ID of the associated + * inadequacy node. Because these IDs are assigned in ascending + * order, this should mean that the insertion position within an + * annotation list is usually near the beginning with other + * annotations associated with the same inadequacy. + * - Next, sort on the first contribution that is different as follows: + * - Sort an always-contribution before a never-contribution before a + * potential-contribution. + * - Two always-contributions are identical. + * - Two never-contributions are identical. + * - For two potential-contributions, sort on the contributions' kernel + * item bitsets interpreted as binary numbers. + * - The sorting has a few effects: + * - It accelerates elimination of identical annotations during insertion. + * - It determines how the output of \c AnnotationList__debug is sorted. + * - Other than that, it's probably not important. + */ +static bool +AnnotationList__insertInto (AnnotationList *self, AnnotationList **list, + size_t nitems) +{ + AnnotationList **node; + for (node = list; *node; node = &(*node)->next) + { + int cmp = 0; + ContributionIndex ci; + if (self->inadequacyNode->id < (*node)->inadequacyNode->id) + cmp = 1; + else if ((*node)->inadequacyNode->id < self->inadequacyNode->id) + cmp = -1; + else + for (ci = 0; + cmp == 0 && ci < self->inadequacyNode->contributionCount; + ++ci) + { + if (AnnotationList__isContributionAlways (self, ci)) + { + if (!AnnotationList__isContributionAlways (*node, ci)) + cmp = -1; + } + else if (AnnotationList__isContributionAlways (*node, ci)) + cmp = 1; + else + { + size_t item; + for (item = 0; cmp == 0 && item < nitems; ++item) + { + if (!Sbitset__test (self->contributions[ci], item)) + { + if (Sbitset__test ((*node)->contributions[ci], item)) + cmp = -1; + } + else if (!Sbitset__test ((*node)->contributions[ci], item)) + cmp = 1; + } + } + } + if (cmp < 0) + { + self->next = *node; + *node = self; + break; + } + else if (cmp == 0) + { + self = NULL; + break; + } + } + if (!*node) + *node = self; + return self != NULL; +} + +static bitset +AnnotationList__compute_shift_tokens (transitions *trans) +{ + bitset shift_tokens = bitset_create (ntokens, BITSET_FIXED); + int i; + FOR_EACH_SHIFT (trans, i) + bitset_set (shift_tokens, TRANSITION_SYMBOL (trans, i)); + return shift_tokens; +} + +static bitset +AnnotationList__compute_conflicted_tokens (bitset shift_tokens, + reductions *reds) +{ + bitset conflicted_tokens = bitset_create (ntokens, BITSET_FIXED); + bitset conflicted_tokens_rule = bitset_create (ntokens, BITSET_FIXED); + bitset tokens = bitset_create (ntokens, BITSET_FIXED); + int i; + + bitset_copy (tokens, shift_tokens); + for (i = 0; i < reds->num; ++i) + { + bitset_and (conflicted_tokens_rule, tokens, reds->lookahead_tokens[i]); + bitset_or (conflicted_tokens, + conflicted_tokens, conflicted_tokens_rule); + bitset_or (tokens, tokens, reds->lookahead_tokens[i]); + /* Check that rules are sorted on rule number or the next step in + AnnotationList__compute_from_inadequacies will misbehave. */ + aver (i == 0 || reds->rules[i-1] < reds->rules[i]); + } + + bitset_free (tokens); + bitset_free (conflicted_tokens_rule); + + return conflicted_tokens; +} + +static bool +AnnotationList__compute_lhs_contributions (state *s, rule *the_rule, + symbol_number conflicted_token, + bitsetv follow_kernel_items, + bitsetv always_follows, + state ***predecessors, + bitset **item_lookahead_sets, + Sbitset *items, + struct obstack + *annotations_obstackp) +{ + goto_number lhs_goto = map_goto (s->number, the_rule->lhs->number); + if (bitset_test (always_follows[lhs_goto], conflicted_token)) + return true; + *items = Sbitset__new_on_obstack (s->nitems, annotations_obstackp); + { + bitset_iterator biter_item; + bitset_bindex item; + BITSET_FOR_EACH (biter_item, follow_kernel_items[lhs_goto], item, 0) + if (ielr_item_has_lookahead (s, 0, item, conflicted_token, + predecessors, item_lookahead_sets)) + Sbitset__set (*items, item); + } + return false; +} + +static void +AnnotationList__computePredecessorAnnotations (AnnotationList *self, state *s, + bitsetv follow_kernel_items, + bitsetv always_follows, + state ***predecessors, + bitset **item_lookahead_sets, + AnnotationList + **annotation_lists, + AnnotationIndex + *annotation_counts, + struct obstack + *annotations_obstackp) +{ + state **predecessor; + bitset *lookaheads; + for (predecessor = predecessors[s->number]; *predecessor; ++predecessor) + { + AnnotationList *annotation_node = + AnnotationList__alloc_on_obstack ( + self->inadequacyNode->contributionCount, annotations_obstackp); + bool potential_contribution = false; + annotation_node->inadequacyNode = self->inadequacyNode; + lookaheads = NULL; + { + ContributionIndex ci; + for (ci = 0; ci < self->inadequacyNode->contributionCount; ++ci) + { + symbol_number contribution_token = + InadequacyList__getContributionToken (self->inadequacyNode, ci) + ->number; + if (AnnotationList__isContributionAlways (self, ci)) + { + annotation_node->contributions[ci] = NULL; + continue; + } + annotation_node->contributions[ci] = + Sbitset__new_on_obstack ((*predecessor)->nitems, + annotations_obstackp); + { + size_t predecessor_item = 0; + Sbitset sbiter_item; + Sbitset__Index self_item; + SBITSET__FOR_EACH (self->contributions[ci], s->nitems, + sbiter_item, self_item) + { + /* If this kernel item is the beginning of a RHS, it must be + the kernel item in the start state, and so it has an empty + lookahead set. Thus, it can't contribute to inadequacies, + and so it should never have been identified as a + contribution. If, instead, this kernel item is the + successor of the start state's kernel item, the lookahead + set is still empty, and so it also should never have been + identified as a contribution. This situation is fortunate + because we want to avoid the - 2 below in both cases. */ + aver (s->items[self_item] > 1); + /* If this kernel item is next to the beginning of the RHS, + then check all of the predecessor's goto follows for the + LHS. */ + if (item_number_is_rule_number (ritem[s->items[self_item] + - 2])) + { + Sbitset items; + unsigned int rulei; + for (rulei = s->items[self_item]; + !item_number_is_rule_number (ritem[rulei]); + ++rulei) + ; + if (AnnotationList__compute_lhs_contributions ( + *predecessor, + &rules[item_number_as_rule_number (ritem[rulei])], + contribution_token, + follow_kernel_items, always_follows, predecessors, + item_lookahead_sets, &items, annotations_obstackp)) + { + obstack_free (annotations_obstackp, + annotation_node->contributions[ci]); + annotation_node->contributions[ci] = NULL; + break; + } + else + { + Sbitset__or (annotation_node->contributions[ci], + annotation_node->contributions[ci], + items, (*predecessor)->nitems); + obstack_free (annotations_obstackp, items); + } + } + /* If this kernel item is later in the RHS, then check the + predecessor item's lookahead set. */ + else + { + /* We don't have to start the predecessor item search at + the beginning every time because items from both + states are sorted by their indices in ritem. */ + for (; + predecessor_item < (*predecessor)->nitems; + ++predecessor_item) + if ((*predecessor)->items[predecessor_item] + == s->items[self_item] - 1) + break; + aver (predecessor_item != (*predecessor)->nitems); + if (ielr_item_has_lookahead (*predecessor, 0, + predecessor_item, + contribution_token, + predecessors, + item_lookahead_sets)) + Sbitset__set (annotation_node->contributions[ci], + predecessor_item); + } + } + } + if (annotation_node->contributions[ci]) + { + Sbitset biter; + Sbitset__Index i; + SBITSET__FOR_EACH (annotation_node->contributions[ci], + (*predecessor)->nitems, biter, i) + { + potential_contribution = true; + if (!lookaheads) + { + size_t j; + lookaheads = xnmalloc ((*predecessor)->nitems, + sizeof *lookaheads); + for (j = 0; j < (*predecessor)->nitems; ++j) + lookaheads[j] = NULL; + } + if (!lookaheads[i]) + lookaheads[i] = bitset_create (ntokens, BITSET_FIXED); + bitset_set (lookaheads[i], contribution_token); + } + } + } + } + + /* If the predecessor has any contributions besides just "always" and + "never" contributions: + - If the dominant contribution is split-stable, the annotation could + not affect merging on this predecessor state or its eventual + predecessor states. Moreover, all contributions that affect + whether the dominant contribution remains dominant must be "always" + or "never" contributions in order for the dominant contribution to + be split-stable. Thus, the dominant contribution computation result + in eventual successor states will not be affected by lookaheads + tracked for this predecessor state. (Also, as in the isocore + compatibility test, we depend on the fact that isocores with equal + dominant contributions will have the same dominant contribution when + merged. Otherwise, we might have to worry that the presence of a + potential contribution might somehow be the culprit of that behavior + and thus need to be tracked regardless of the split stability of the + dominant contribution.) Thus, go ahead and discard the annotation + to save space now plus time during state splitting. + - Otherwise, record the annotation, and compute any resulting + annotations needed on predecessor states. */ + if (potential_contribution) + { + if (ContributionIndex__none + != AnnotationList__computeDominantContribution ( + annotation_node, (*predecessor)->nitems, lookaheads, true)) + { + obstack_free (annotations_obstackp, annotation_node); + annotation_node = NULL; + } + { + size_t i; + for (i = 0; i < (*predecessor)->nitems; ++i) + if (lookaheads[i]) + bitset_free (lookaheads[i]); + free (lookaheads); + } + if (annotation_node) + { + if (AnnotationList__insertInto (annotation_node, + &annotation_lists[(*predecessor) + ->number], + (*predecessor)->nitems)) + { + ++annotation_counts[(*predecessor)->number]; + AnnotationList__computePredecessorAnnotations ( + annotation_node, *predecessor, + follow_kernel_items, always_follows, predecessors, + item_lookahead_sets, annotation_lists, annotation_counts, + annotations_obstackp); + } + else + obstack_free (annotations_obstackp, annotation_node); + } + } + else + obstack_free (annotations_obstackp, annotation_node); + } +} + +void +AnnotationList__compute_from_inadequacies ( + state *s, bitsetv follow_kernel_items, bitsetv always_follows, + state ***predecessors, bitset **item_lookahead_sets, + InadequacyList **inadequacy_lists, AnnotationList **annotation_lists, + AnnotationIndex *annotation_counts, + ContributionIndex *max_contributionsp, + struct obstack *annotations_obstackp, + InadequacyListNodeCount *inadequacy_list_node_count) +{ + bitsetv all_lookaheads; + bitset shift_tokens; + bitset conflicted_tokens; + bitset_iterator biter_conflict; + bitset_bindex conflicted_token; + + /* Return an empty list if s->lookahead_tokens = NULL. */ + if (s->consistent) + return; + + all_lookaheads = bitsetv_create (s->nitems, ntokens, BITSET_FIXED); + bitsetv_ones (all_lookaheads); + shift_tokens = AnnotationList__compute_shift_tokens (s->transitions); + conflicted_tokens = + AnnotationList__compute_conflicted_tokens (shift_tokens, s->reductions); + + /* Add an inadequacy annotation for each conflicted_token. */ + BITSET_FOR_EACH (biter_conflict, conflicted_tokens, conflicted_token, 0) + { + AnnotationList *annotation_node; + /* FIXME: Would a BITSET_FRUGAL or BITEST_SPARSE be more efficient? Now + or convert it inside InadequacyList__new_conflict? */ + bitset actions = bitset_create (s->reductions->num + 1, BITSET_FIXED); + ContributionIndex contribution_count = 0; + bool potential_contribution = false; + + /* Allocate the annotation node. */ + { + int rule_i; + for (rule_i = 0; rule_i < s->reductions->num; ++rule_i) + if (bitset_test (s->reductions->lookahead_tokens[rule_i], + conflicted_token)) + ++contribution_count; + if (bitset_test (shift_tokens, conflicted_token)) + ++contribution_count; + annotation_node = + AnnotationList__alloc_on_obstack (contribution_count, + annotations_obstackp); + } + + /* Add a contribution for each reduction that has conflicted_token as a + lookahead. */ + { + ContributionIndex ci = 0; + int item_i = 0; + int rule_i; + for (rule_i = 0; rule_i < s->reductions->num; ++rule_i) + { + rule *the_rule = s->reductions->rules[rule_i]; + if (bitset_test (s->reductions->lookahead_tokens[rule_i], + conflicted_token)) + { + bitset_set (actions, rule_i); + /* If this reduction is on a kernel item, just add it. */ + if (!item_number_is_rule_number (the_rule->rhs[0])) + { + annotation_node->contributions[ci] = + Sbitset__new_on_obstack (s->nitems, + annotations_obstackp); + /* Catch item_i up to rule_i. This works because both are + sorted on rule number. */ + while (!item_number_is_rule_number ( + ritem[s->items[item_i]]) + || item_number_as_rule_number ( + ritem[s->items[item_i]]) + != the_rule->number) + { + ++item_i; + aver (item_i < s->nitems); + } + Sbitset__set (annotation_node->contributions[ci], item_i); + } + /* Otherwise, add the kernel items whose lookahead sets + contribute the conflicted token to this reduction's + lookahead set. */ + else if (AnnotationList__compute_lhs_contributions ( + s, the_rule, conflicted_token, follow_kernel_items, + always_follows, predecessors, item_lookahead_sets, + &annotation_node->contributions[ci], + annotations_obstackp)) + { + annotation_node->contributions[ci++] = NULL; + continue; + } + /* The lookahead token has to come from somewhere. */ + aver (!Sbitset__isEmpty (annotation_node->contributions[ci], + s->nitems)); + ++ci; + potential_contribution = true; + } + } + } + + /* If there are any contributions besides just "always" contributions: + - If there's also a shift contribution, record it. + - If the dominant contribution is split-stable, then the annotation + could not affect merging, so go ahead and discard the annotation and + the inadequacy to save space now plus time during state splitting. + - Otherwise, record the annotation and the inadequacy, and compute any + resulting annotations needed on predecessor states. */ + if (potential_contribution) + { + if (bitset_test (shift_tokens, conflicted_token)) + { + bitset_set (actions, s->reductions->num); + annotation_node->contributions[contribution_count - 1] = NULL; + } + { + InadequacyList *conflict_node = + InadequacyList__new_conflict ( + s, symbols[conflicted_token], actions, + inadequacy_list_node_count); + actions = NULL; + annotation_node->inadequacyNode = conflict_node; + if (ContributionIndex__none + != AnnotationList__computeDominantContribution ( + annotation_node, s->nitems, all_lookaheads, true)) + { + obstack_free (annotations_obstackp, annotation_node); + InadequacyList__delete (conflict_node); + } + else + { + InadequacyList__prependTo (conflict_node, + &inadequacy_lists[s->number]); + aver (AnnotationList__insertInto ( + annotation_node, &annotation_lists[s->number], + s->nitems)); + /* This aver makes sure the + AnnotationList__computeDominantContribution check above + does discard annotations in the simplest case of a S/R + conflict with no token precedence. */ + aver (!bitset_test (shift_tokens, conflicted_token) + || symbols[conflicted_token]->prec); + ++annotation_counts[s->number]; + if (contribution_count > *max_contributionsp) + *max_contributionsp = contribution_count; + AnnotationList__computePredecessorAnnotations ( + annotation_node, s, + follow_kernel_items, always_follows, predecessors, + item_lookahead_sets, annotation_lists, annotation_counts, + annotations_obstackp); + } + } + } + else + { + bitset_free (actions); + obstack_free (annotations_obstackp, annotation_node); + } + } + + bitsetv_free (all_lookaheads); + bitset_free (shift_tokens); + bitset_free (conflicted_tokens); +} + +void +AnnotationList__debug (AnnotationList const *self, size_t nitems, int spaces) +{ + AnnotationList const *a; + AnnotationIndex ai; + for (a = self, ai = 0; a; a = a->next, ++ai) + { + { + int j; + for (j = 0; j < spaces; ++j) + putc (' ', stderr); + } + fprintf (stderr, "Annotation %d (manifesting state %d):\n", + ai, a->inadequacyNode->manifestingState->number); + { + ContributionIndex ci; + bitset_bindex rulei = 0; /* init suppresses compiler warning */ + rulei = bitset_first (a->inadequacyNode->inadequacy.conflict.actions); + for (ci = 0; ci < a->inadequacyNode->contributionCount; ++ci) + { + symbol_number token = + InadequacyList__getContributionToken (a->inadequacyNode, ci) + ->number; + { + int j; + for (j = 0; j < spaces+2; ++j) + putc (' ', stderr); + } + if (ci == InadequacyList__getShiftContributionIndex ( + a->inadequacyNode)) + fprintf (stderr, "Contributes shift of token %d.\n", token); + else + { + fprintf (stderr, "Contributes token %d", token); + aver (rulei != BITSET_BINDEX_MAX); + fprintf (stderr, " as lookahead, rule number %d", + a->inadequacyNode->manifestingState + ->reductions->rules[rulei]->number); + rulei = + bitset_next (a->inadequacyNode->inadequacy.conflict.actions, + rulei+1); + if (AnnotationList__isContributionAlways (a, ci)) + fprintf (stderr, " always."); + else + { + fprintf (stderr, ", items: "); + Sbitset__fprint (a->contributions[ci], nitems, stderr); + } + fprintf (stderr, "\n"); + } + } + } + } +} + +void +AnnotationList__computeLookaheadFilter (AnnotationList const *self, + size_t nitems, + bitsetv lookahead_filter) +{ + bitsetv_zero (lookahead_filter); + for (; self; self = self->next) + { + ContributionIndex ci; + for (ci = 0; ci < self->inadequacyNode->contributionCount; ++ci) + if (!AnnotationList__isContributionAlways (self, ci)) + { + Sbitset__Index item; + Sbitset biter; + symbol_number token = + InadequacyList__getContributionToken (self->inadequacyNode, ci) + ->number; + SBITSET__FOR_EACH (self->contributions[ci], nitems, biter, item) + bitset_set (lookahead_filter[item], token); + } + } +} + +/** + * \pre + * - <tt>self != NULL</tt>. + * - \c nitems is the number of kernel items in the LR(0) state that \c self + * annotates. + * - \c lookaheads describes the lookahead sets on the kernel items of some + * isocore of the LR(0) state that \c self annotates. Either: + * - <tt>lookaheads = NULL</tt> only if the lookahead set on every kernel + * item is empty. + * - For any <tt>0 <= i < nitems</tt>, <tt>lookaheads[i]</tt> is either: + * - \c NULL only if the lookahead set on kernel item \c i is empty. + * - The (possibly empty) lookahead set on kernel item \c i. + * - <tt>0 <= ci < self->inadequacyNode->contributionCount</tt>. + * \post + * - \c result = true iff contribution \c ci in \c self is made by the state + * described by \c lookaheads. + */ +static bool +AnnotationList__stateMakesContribution (AnnotationList const *self, + size_t nitems, ContributionIndex ci, + bitset *lookaheads) +{ + if (AnnotationList__isContributionAlways (self, ci)) + return true; + if (!lookaheads) + return false; + { + symbol_number token = + InadequacyList__getContributionToken (self->inadequacyNode, ci)->number; + Sbitset__Index item; + Sbitset biter; + SBITSET__FOR_EACH (self->contributions[ci], nitems, biter, item) + if (lookaheads[item] && bitset_test (lookaheads[item], token)) + return true; + } + return false; +} + +ContributionIndex +AnnotationList__computeDominantContribution (AnnotationList const *self, + size_t nitems, bitset *lookaheads, + bool require_split_stable) +{ + symbol *token; + ContributionIndex const ci_shift = + InadequacyList__getShiftContributionIndex (self->inadequacyNode); + + token = self->inadequacyNode->inadequacy.conflict.token; + + /* S/R conflict. */ + if (ci_shift != ContributionIndex__none) + { + bool find_stable_domination_over_shift = false; + bool find_stable_error_action_domination = false; + { + ContributionIndex ci; + int actioni; + ContributionIndex ci_rr_dominator = ContributionIndex__none; + int shift_precedence = token->prec; + + /* If the token has no precedence set, shift is always chosen. */ + if (!shift_precedence) + return ci_shift; + + /* Figure out which reductions contribute, which of those would + dominate in a R/R comparison, and whether any reduction dominates + the shift so that the R/R comparison is actually needed. */ + for (ci = 0, actioni = bitset_first (self->inadequacyNode->inadequacy + .conflict.actions); + ci < self->inadequacyNode->contributionCount; + ++ci, actioni = bitset_next (self->inadequacyNode->inadequacy + .conflict.actions, actioni+1)) + { + int reduce_precedence = 0; + if (ci == ci_shift) + continue; + { + rule *r = self->inadequacyNode->manifestingState + ->reductions->rules[actioni]; + if (r->prec) + reduce_precedence = r->prec->prec; + } + /* If there's no need to check whether this reduction actually + contributes because the shift eliminates it from the R/R + comparison anyway, continue to the next reduction. */ + if (reduce_precedence + && (reduce_precedence < shift_precedence + || (reduce_precedence == shift_precedence + && token->assoc == right_assoc))) + continue; + if (!AnnotationList__stateMakesContribution (self, nitems, ci, + lookaheads)) + continue; + /* This uneliminated reduction contributes, so see if it can cause + an error action. */ + if (reduce_precedence == shift_precedence + && token->assoc == non_assoc) + { + /* It's not possible to find split-stable domination over + shift after a potential %nonassoc. */ + if (find_stable_domination_over_shift) + return ContributionIndex__none; + if (!require_split_stable + || AnnotationList__isContributionAlways (self, ci)) + return ContributionIndex__error_action; + find_stable_error_action_domination = true; + } + /* Consider this uneliminated contributing reduction in the R/R + comparison. */ + if (ci_rr_dominator == ContributionIndex__none) + ci_rr_dominator = ci; + /* If precedence is set for this uneliminated contributing + reduction, it dominates the shift, so try to figure out which + reduction dominates the R/R comparison. */ + if (reduce_precedence) + { + /* It's not possible to find split-stable error action + domination after a potential reduction. */ + if (find_stable_error_action_domination) + return ContributionIndex__none; + if (!require_split_stable) + return ci_rr_dominator; + if (!AnnotationList__isContributionAlways (self, + ci_rr_dominator)) + return ContributionIndex__none; + if (AnnotationList__isContributionAlways (self, ci)) + return ci_rr_dominator; + find_stable_domination_over_shift = true; + } + } + } + if (find_stable_domination_over_shift + || find_stable_error_action_domination) + return ContributionIndex__none; + /* No reduce or error action domination found, so shift dominates. */ + return ci_shift; + } + + /* R/R conflict, so the reduction with the lowest rule number dominates. + Fortunately, contributions are sorted by rule number. */ + { + ContributionIndex ci; + for (ci = 0; ci < self->inadequacyNode->contributionCount; ++ci) + if (AnnotationList__stateMakesContribution (self, nitems, ci, + lookaheads)) + { + if (require_split_stable + && !AnnotationList__isContributionAlways (self, ci)) + return ContributionIndex__none; + return ci; + } + } + return ContributionIndex__none; +} diff --git a/contrib/tools/bison/src/AnnotationList.h b/contrib/tools/bison/src/AnnotationList.h new file mode 100644 index 0000000000..5abaa2e79b --- /dev/null +++ b/contrib/tools/bison/src/AnnotationList.h @@ -0,0 +1,182 @@ +/* IELR's inadequacy annotation list. + + Copyright (C) 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef ANNOTATION_LIST_H_ +# define ANNOTATION_LIST_H_ + +# include <bitsetv.h> +# include "Sbitset.h" +# include "InadequacyList.h" +# include "state.h" + +typedef unsigned int AnnotationIndex; + +/** + * A node in a list of annotations on a particular LR(0) state. Each + * annotation records how isocores of that LR(0) state might contribute to an + * individual inadequacy, which might manifest in a different state. Don't + * break encapsulation by modifying the fields directly. Use the provided + * interface functions. + */ +typedef struct AnnotationList +{ + /** The next node in the list or \c NULL if none. */ + struct AnnotationList *next; + /** The \c InadequacyList node describing how this inadequacy manifests. */ + InadequacyList *inadequacyNode; + /** + * List of how the "always", "never", and potential contributions of the + * inadequacy might be made by isocores of the annotated LR(0) state: + * - The number of rows is the number of contributions. That is, + * <tt>AnnotationList::inadequacyNode->contributionCount</tt>. + * - The token associated with contribution \c i is + * <tt>InadequacyList__getContributionToken (AnnotationList::inadequacyNode, i)</tt>. + * - Iff <tt>AnnotationList::contributions[i] = NULL</tt>, contribution + * \c i is an "always" contribution. That is, for every isocore of the + * annotated LR(0) state, its core or the core of one its eventual + * successors will definitely make this contribution to the inadequacy. + * It may contribute by either: + * - Creating a shift of contribution <tt>i</tt>'s token in the state + * that can manifest the inadequacy. + * - Propagating that token to the lookahead set of contribution + * <tt>i</tt>'s reduction in the state that can manifest the + * inadequacy. + * - Otherwise: + * - The number of columns in <tt>AnnotationList::contributions[i]</tt> + * is the number of kernel items in any isocore of the annotated LR(0) + * state. + * - Iff <tt>AnnotationList::contributions[i]</tt> is empty, contribution + * \c i is a "never" contribution. That is, no isocore of the + * annotated LR(0) state can make this contribution to the inadequacy. + * - Otherwise, for each bit \c j that is set in + * <tt>AnnotationList::contributions[i]</tt>, if the token associated + * with contribution \c i is present in the lookahead set of kernel + * item \c j of an isocore of the annotated LR(0) state, that isocore + * will make contribution \c i to the inadequacy by propagating the + * contribution's token to the lookahead set of the contribution's + * reduction in the state that can manifest the inadequacy. + */ + Sbitset contributions[1]; +} AnnotationList; + +/** + * \pre + * - <tt>s != NULL</tt>. + * - \c follow_kernel_items, \c always_follows, and \c predecessors were + * computed by \c ielr_compute_auxiliary_tables. + * - The size of each of \c annotation_lists and \c annotation_counts is + * \c ::nstates. + * - If no \c InadequacyList nodes are currently allocated for the + * parser tables to which \c s belongs, then it is best if + * <tt>*inadequacy_list_node_count</tt> is zero to avoid overflow. + * Otherwise, <tt>*inadequacy_list_node_count</tt> has not been + * modified by any function except + * \c AnnotationList__compute_from_inadequacies since the invocation + * of \c AnnotationList__compute_from_inadequacies that constructed + * the first of the \c InadequacyList nodes currently allocated for + * those parser tables. + * \post + * - <tt>inadequacy_lists[s->number]</tt> now describes all inadequacies that + * manifest in \c s. + * - For every state <tt>states[i]</tt>, <tt>annotation_lists[i]</tt> now + * contains all annotations associated with all inadequacies that manifest + * in \c s. + * - <tt>annotation_counts[i]</tt> was incremented by the number of new + * annotations added to <tt>states[i]</tt>. + * - <tt>*max_contributionsp</tt> is the higher of: + * - The maximum number of contributions computed per annotation. + * - <tt>*max_contributionsp \@pre</tt>. + * - All memory for all new annotations was allocated on + * \c annotations_obstackp. + */ +void +AnnotationList__compute_from_inadequacies ( + state *s, bitsetv follow_kernel_items, bitsetv always_follows, + state ***predecessors, bitset **item_lookahead_sets, + InadequacyList **inadequacy_lists, AnnotationList **annotation_lists, + AnnotationIndex *annotation_counts, + ContributionIndex *max_contributionsp, + struct obstack *annotations_obstackp, + InadequacyListNodeCount *inadequacy_list_node_count); + +/** + * \pre + * - <tt>self != NULL</tt>. + * - \c nitems is the number of kernel items in the LR(0) state that every + * node in the list \c self annotates. + * \post + * - A textual representation of all nodes in the list \c self was printed to + * stderr. \c spaces spaces were printed before each line of the text. + */ +void AnnotationList__debug (AnnotationList const *self, size_t nitems, + int spaces); + +/** + * \pre + * - <tt>self != NULL</tt>. + * - \c nitems is the number of kernel items in the LR(0) state that \c self + * annotates. + * - The number of rows in \c lookahead_filter is at least \c nitems, and the + * number of columns is \c ::ntokens. + * \post + * - <tt>lookahead_filter[i][j]</tt> is set iff some annotation in the list + * \c self lists token \c j in kernel item \c i as a contributor. + */ +void AnnotationList__computeLookaheadFilter (AnnotationList const *self, + size_t nitems, + bitsetv lookahead_filter); + +/** + * \pre + * - <tt>self != NULL</tt>. + * - \c nitems is the number of kernel items in the LR(0) state that \c self + * annotates. + * - \c lookaheads describes the lookahead sets on the kernel items of some + * isocore of the LR(0) state that \c self annotates. Either: + * - <tt>lookaheads = NULL</tt> only if the lookahead set on every kernel + * item is empty. + * - For any <tt>0 <= i < nitems</tt>, <tt>lookaheads[i]</tt> is either: + * - \c NULL only if the lookahead set on kernel item \c i is empty. + * - The (possibly empty) lookahead set on kernel item \c i. + * \post + * - If <tt>require_split_stable = false</tt>, \c result = either: + * - \c ContributionIndex__none iff the state described by \c lookaheads + * makes none of the contributions in \c self. + * - The index of the dominating contribution in \c self that is made by + * that state. + * - \c ContributionIndex__error_action to indicate that the inadequacy + * manifests as a conflict and that a syntax error action (because of a + * %nonassoc) dominates instead. + * - Otherwise, \c result is the same as if <tt>require_split_stable = + * false</tt> except that it is also \c ContributionIndex__none if there + * are contributions made by the state but the dominating contribution is + * not split-stable. By split-stable, we mean that the dominating + * contribution cannot change due to loss of one or more potential + * contributions due to loss of lookaheads due to splitting of the state. + * - After determining which contributions are actually made by the state, + * the algorithm for determining which contribution dominates in the + * conflict is intended to choose exactly the same action as conflicts.c + * would choose... no matter how crazy conflicts.c's choice is. + */ +ContributionIndex +AnnotationList__computeDominantContribution (AnnotationList const *self, + size_t nitems, bitset *lookaheads, + bool require_split_stable); + +#endif /* !ANNOTATION_LIST_H_ */ diff --git a/contrib/tools/bison/src/InadequacyList.c b/contrib/tools/bison/src/InadequacyList.c new file mode 100644 index 0000000000..9510b40d91 --- /dev/null +++ b/contrib/tools/bison/src/InadequacyList.c @@ -0,0 +1,79 @@ +/* IELR's inadequacy list. + + Copyright (C) 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include "InadequacyList.h" + +ContributionIndex const ContributionIndex__none = -1; +ContributionIndex const ContributionIndex__error_action = -2; + +InadequacyList * +InadequacyList__new_conflict (state *manifesting_state, symbol *token, + bitset actions, + InadequacyListNodeCount *node_count) +{ + InadequacyList *result = xmalloc (sizeof *result); + result->id = (*node_count)++; + aver (*node_count != 0); + result->next = NULL; + result->manifestingState = manifesting_state; + result->contributionCount = bitset_count (actions); + result->inadequacy.conflict.token = token; + result->inadequacy.conflict.actions = actions; + return result; +} + +void +InadequacyList__delete (InadequacyList *self) +{ + while (self) + { + InadequacyList *node = self; + self = self->next; + bitset_free (node->inadequacy.conflict.actions); + free (node); + } +} + +ContributionIndex +InadequacyList__getShiftContributionIndex (InadequacyList const *self) +{ + if (!bitset_test (self->inadequacy.conflict.actions, + self->manifestingState->reductions->num)) + return ContributionIndex__none; + return self->contributionCount - 1; +} + +symbol * +InadequacyList__getContributionToken (InadequacyList const *self, + ContributionIndex i) +{ + aver (0 <= i && i < self->contributionCount); + return self->inadequacy.conflict.token; +} + +void +InadequacyList__prependTo (InadequacyList *self, InadequacyList **list) +{ + InadequacyList *head_old = *list; + *list = self; + self->next = head_old; +} diff --git a/contrib/tools/bison/src/InadequacyList.h b/contrib/tools/bison/src/InadequacyList.h new file mode 100644 index 0000000000..d293b9b6c6 --- /dev/null +++ b/contrib/tools/bison/src/InadequacyList.h @@ -0,0 +1,156 @@ +/* IELR's inadequacy list. + + Copyright (C) 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef INADEQUACY_LIST_H_ +# define INADEQUACY_LIST_H_ + +# include <bitset.h> +# include "gram.h" +# include "state.h" +# include "symtab.h" + +/** + * A unique ID assigned to every \c InadequacyList node. + * + * This must remain unsigned so that the overflow check in + * \c InadequacyList__new_conflict works properly. + */ +typedef unsigned long long int InadequacyListNodeCount; + +/** + * For a conflict, each rule in the grammar can have at most one contributing + * reduction except that rule 0 cannot have any because the reduction on rule 0 + * cannot have lookaheads. For a conflict, exactly one shift can contribute. + * Thus the number of rules in the grammar is an upper bound on the number of + * possible contributions to any conflict. The maximum number of possible + * items in a state is also an upper bound, but the \c nitems member of \c + * state is currently a \c size_t and thus, if changed, risks becoming out of + * sync with this type. Whatever the type, it must support negatives for sake + * of the special values below. + */ +typedef rule_number ContributionIndex; + +/* Special \c ContributionIndex used to indicate null result when looking for a + contribution. */ +extern ContributionIndex const ContributionIndex__none; + +/* Special \c ContributionIndex used by + \c AnnotationList__computeDominantContribution to signal when the action + chosen in a conflict is a syntax error because of a %nonassoc. */ +extern ContributionIndex const ContributionIndex__error_action; + +/** + * The description of a conflict. Don't break encapsulation by modifying the + * fields directly. Use the provided interface functions for + * \c InadequacyList. + */ +typedef struct { + /** The \c token passed to \c InadequacyList__new_conflict. */ + symbol *token; + /** The \c actions passed to \c InadequacyList__new_conflict. */ + bitset actions; +} Conflict; + +/** + * A node in a list that describes all the inadequacies that manifest in a + * particular state. Don't break encapsulation by modifying the fields + * directly. Use the provided interface functions. + */ +typedef struct InadequacyList { + struct InadequacyList *next; + InadequacyListNodeCount id; + state *manifestingState; + ContributionIndex contributionCount; + union { + Conflict conflict; + } inadequacy; +} InadequacyList; + +/** + * \pre + * - <tt>manifesting_state != NULL</tt>. + * - \c token is a token. + * - The size of \c actions is + * <tt>manifesting_state->reductions->num + 1</tt>. + * - If the set of all \c InadequacyList nodes with which the new + * \c InadequacyList node might be compared is currently empty, then + * it is best if <tt>*node_count</tt> is zero so that the node count + * does not eventually overflow. However, if that set is not + * currently empty, then <tt>*node_count</tt> has not been modified + * by any function except \c InadequacyList__new_conflict since the + * invocation of \c InadequacyList__new_conflict that constructed + * the first existing member of that set. + * \post + * - \c result is a new \c InadequacyList with one node indicating that, in + * \c manifesting_state, the following actions are in conflict on \c token: + * - Shift iff + * <tt>bitset_test (actions, manifesting_state->reductions->num)</tt>. + * - For any \c i such that + * <tt>0 <= i < manifesting_state->reductions->num</tt>, the reduction + * for the rule <tt>manifesting_state->reductions->rules[i]</tt> iff + * <tt>actions[i]</tt> is set. + * - Given any node \c n from the set of all existing + * \c InadequacyList nodes with which \c result might be compared + * such that <tt>n != result</tt>, then <tt>n->id < result->id</tt>. + * - \c result assumes responsibility for the memory of \c actions. + */ +InadequacyList *InadequacyList__new_conflict ( + state *manifesting_state, symbol *token, bitset actions, + InadequacyListNodeCount *node_count); + +/** + * \post + * - All memory associated with all nodes in the list \c self was freed. + */ +void InadequacyList__delete (InadequacyList *self); + +/** + * \pre + * - <tt>self != NULL</tt>. + * \post + * - \c result = either: + * - \c ContributionIndex__none iff there is no shift contribution in + * \c self (perhaps because \c self isn't a conflict). + * - The index of the shift contribution, otherwise. + */ +ContributionIndex +InadequacyList__getShiftContributionIndex (InadequacyList const *self); + +/** + * \pre + * - <tt>self != NULL</tt>. + * - <tt>0 <= i < self->contributionCount</tt>. + * \post + * - \c result = the token associated with contribution \c i in the + * inadequacy described by the node \c self. + */ +symbol *InadequacyList__getContributionToken (InadequacyList const *self, + ContributionIndex i); + +/** + * \pre + * - \c self is a single node. + * - <tt>list != NULL</tt>. + * \post + * - \c list now contains \c self as its first node. + * - \c list assumes responsibility for the memory of \c self. + */ +void InadequacyList__prependTo (InadequacyList *self, InadequacyList **list); + +#endif /* !INADEQUACY_LIST_H_ */ diff --git a/contrib/tools/bison/src/LR0.c b/contrib/tools/bison/src/LR0.c new file mode 100644 index 0000000000..f6a9537e4c --- /dev/null +++ b/contrib/tools/bison/src/LR0.c @@ -0,0 +1,375 @@ +/* Generate the LR(0) parser states for Bison. + + Copyright (C) 1984, 1986, 1989, 2000-2002, 2004-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + + +/* See comments in state.h for the data structures that represent it. + The entry point is generate_states. */ + +#include <config.h> +#include "system.h" + +#include <bitset.h> + +#include "LR0.h" +#include "closure.h" +#include "complain.h" +#include "getargs.h" +#include "gram.h" +#include "lalr.h" +#include "reader.h" +#include "reduce.h" +#include "state.h" +#include "symtab.h" + +typedef struct state_list +{ + struct state_list *next; + state *state; +} state_list; + +static state_list *first_state = NULL; +static state_list *last_state = NULL; + + +/*------------------------------------------------------------------. +| A state was just discovered from another state. Queue it for | +| later examination, in order to find its transitions. Return it. | +`------------------------------------------------------------------*/ + +static state * +state_list_append (symbol_number sym, size_t core_size, item_number *core) +{ + state_list *node = xmalloc (sizeof *node); + state *s = state_new (sym, core_size, core); + + if (trace_flag & trace_automaton) + fprintf (stderr, "state_list_append (state = %d, symbol = %d (%s))\n", + nstates, sym, symbols[sym]->tag); + + node->next = NULL; + node->state = s; + + if (!first_state) + first_state = node; + if (last_state) + last_state->next = node; + last_state = node; + + return s; +} + +static int nshifts; +static symbol_number *shift_symbol; + +static rule **redset; +static state **shiftset; + +static item_number **kernel_base; +static int *kernel_size; +static item_number *kernel_items; + + +static void +allocate_itemsets (void) +{ + symbol_number i; + rule_number r; + item_number *rhsp; + + /* Count the number of occurrences of all the symbols in RITEMS. + Note that useless productions (hence useless nonterminals) are + browsed too, hence we need to allocate room for _all_ the + symbols. */ + size_t count = 0; + size_t *symbol_count = xcalloc (nsyms + nuseless_nonterminals, + sizeof *symbol_count); + + for (r = 0; r < nrules; ++r) + for (rhsp = rules[r].rhs; *rhsp >= 0; ++rhsp) + { + count++; + symbol_count[*rhsp]++; + } + + /* See comments before new_itemsets. All the vectors of items + live inside KERNEL_ITEMS. The number of active items after + some symbol S cannot be more than the number of times that S + appears as an item, which is SYMBOL_COUNT[S]. + We allocate that much space for each symbol. */ + + kernel_base = xnmalloc (nsyms, sizeof *kernel_base); + kernel_items = xnmalloc (count, sizeof *kernel_items); + + count = 0; + for (i = 0; i < nsyms; i++) + { + kernel_base[i] = kernel_items + count; + count += symbol_count[i]; + } + + free (symbol_count); + kernel_size = xnmalloc (nsyms, sizeof *kernel_size); +} + + +static void +allocate_storage (void) +{ + allocate_itemsets (); + + shiftset = xnmalloc (nsyms, sizeof *shiftset); + redset = xnmalloc (nrules, sizeof *redset); + state_hash_new (); + shift_symbol = xnmalloc (nsyms, sizeof *shift_symbol); +} + + +static void +free_storage (void) +{ + free (shift_symbol); + free (redset); + free (shiftset); + free (kernel_base); + free (kernel_size); + free (kernel_items); + state_hash_free (); +} + + + + +/*---------------------------------------------------------------. +| Find which symbols can be shifted in S, and for each one | +| record which items would be active after that shift. Uses the | +| contents of itemset. | +| | +| shift_symbol is set to a vector of the symbols that can be | +| shifted. For each symbol in the grammar, kernel_base[symbol] | +| points to a vector of item numbers activated if that symbol is | +| shifted, and kernel_size[symbol] is their numbers. | +| | +| itemset is sorted on item index in ritem, which is sorted on | +| rule number. Compute each kernel_base[symbol] with the same | +| sort. | +`---------------------------------------------------------------*/ + +static void +new_itemsets (state *s) +{ + size_t i; + + if (trace_flag & trace_automaton) + fprintf (stderr, "Entering new_itemsets, state = %d\n", s->number); + + memset (kernel_size, 0, nsyms * sizeof *kernel_size); + + nshifts = 0; + + for (i = 0; i < nitemset; ++i) + if (item_number_is_symbol_number (ritem[itemset[i]])) + { + symbol_number sym = item_number_as_symbol_number (ritem[itemset[i]]); + if (!kernel_size[sym]) + { + shift_symbol[nshifts] = sym; + nshifts++; + } + + kernel_base[sym][kernel_size[sym]] = itemset[i] + 1; + kernel_size[sym]++; + } +} + + + +/*--------------------------------------------------------------. +| Find the state we would get to (from the current state) by | +| shifting SYM. Create a new state if no equivalent one exists | +| already. Used by append_states. | +`--------------------------------------------------------------*/ + +static state * +get_state (symbol_number sym, size_t core_size, item_number *core) +{ + state *s; + + if (trace_flag & trace_automaton) + fprintf (stderr, "Entering get_state, symbol = %d (%s)\n", + sym, symbols[sym]->tag); + + s = state_hash_lookup (core_size, core); + if (!s) + s = state_list_append (sym, core_size, core); + + if (trace_flag & trace_automaton) + fprintf (stderr, "Exiting get_state => %d\n", s->number); + + return s; +} + +/*---------------------------------------------------------------. +| Use the information computed by new_itemsets to find the state | +| numbers reached by each shift transition from S. | +| | +| SHIFTSET is set up as a vector of those states. | +`---------------------------------------------------------------*/ + +static void +append_states (state *s) +{ + int i; + + if (trace_flag & trace_automaton) + fprintf (stderr, "Entering append_states, state = %d\n", s->number); + + /* First sort shift_symbol into increasing order. */ + + for (i = 1; i < nshifts; i++) + { + symbol_number sym = shift_symbol[i]; + int j; + for (j = i; 0 < j && sym < shift_symbol[j - 1]; j--) + shift_symbol[j] = shift_symbol[j - 1]; + shift_symbol[j] = sym; + } + + for (i = 0; i < nshifts; i++) + { + symbol_number sym = shift_symbol[i]; + shiftset[i] = get_state (sym, kernel_size[sym], kernel_base[sym]); + } +} + + +/*----------------------------------------------------------------. +| Find which rules can be used for reduction transitions from the | +| current state and make a reductions structure for the state to | +| record their rule numbers. | +`----------------------------------------------------------------*/ + +static void +save_reductions (state *s) +{ + int count = 0; + size_t i; + + /* Find and count the active items that represent ends of rules. */ + for (i = 0; i < nitemset; ++i) + { + item_number item = ritem[itemset[i]]; + if (item_number_is_rule_number (item)) + { + rule_number r = item_number_as_rule_number (item); + redset[count++] = &rules[r]; + if (r == 0) + { + /* This is "reduce 0", i.e., accept. */ + aver (!final_state); + final_state = s; + } + } + } + + /* Make a reductions structure and copy the data into it. */ + state_reductions_set (s, count, redset); +} + + +/*---------------. +| Build STATES. | +`---------------*/ + +static void +set_states (void) +{ + states = xcalloc (nstates, sizeof *states); + + while (first_state) + { + state_list *this = first_state; + + /* Pessimization, but simplification of the code: make sure all + the states have valid transitions and reductions members, + even if reduced to 0. It is too soon for errs, which are + computed later, but set_conflicts. */ + state *s = this->state; + if (!s->transitions) + state_transitions_set (s, 0, 0); + if (!s->reductions) + state_reductions_set (s, 0, 0); + + states[s->number] = s; + + first_state = this->next; + free (this); + } + first_state = NULL; + last_state = NULL; +} + + +/*-------------------------------------------------------------------. +| Compute the LR(0) parser states (see state.h for details) from the | +| grammar. | +`-------------------------------------------------------------------*/ + +void +generate_states (void) +{ + item_number initial_core = 0; + state_list *list = NULL; + allocate_storage (); + new_closure (nritems); + + /* Create the initial state. The 0 at the lhs is the index of the + item of this initial rule. */ + state_list_append (0, 1, &initial_core); + + /* States are queued when they are created; process them all. */ + for (list = first_state; list; list = list->next) + { + state *s = list->state; + if (trace_flag & trace_automaton) + fprintf (stderr, "Processing state %d (reached by %s)\n", + s->number, + symbols[s->accessing_symbol]->tag); + /* Set up itemset for the transitions out of this state. itemset gets a + vector of all the items that could be accepted next. */ + closure (s->items, s->nitems); + /* Record the reductions allowed out of this state. */ + save_reductions (s); + /* Find the itemsets of the states that shifts can reach. */ + new_itemsets (s); + /* Find or create the core structures for those states. */ + append_states (s); + + /* Create the shifts structures for the shifts to those states, + now that the state numbers transitioning to are known. */ + state_transitions_set (s, nshifts, shiftset); + } + + /* discard various storage */ + free_closure (); + free_storage (); + + /* Set up STATES. */ + set_states (); +} diff --git a/contrib/tools/bison/src/LR0.h b/contrib/tools/bison/src/LR0.h new file mode 100644 index 0000000000..976bcb26ee --- /dev/null +++ b/contrib/tools/bison/src/LR0.h @@ -0,0 +1,28 @@ +/* Generate the LR(0) parser states for Bison. + + Copyright (C) 1984, 1986, 1989, 2000-2002, 2009-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef LR0_H_ +# define LR0_H_ + +# include "state.h" + +void generate_states (void); + +#endif /* !LR0_H_ */ diff --git a/contrib/tools/bison/src/Sbitset.c b/contrib/tools/bison/src/Sbitset.c new file mode 100644 index 0000000000..bb278b55db --- /dev/null +++ b/contrib/tools/bison/src/Sbitset.c @@ -0,0 +1,80 @@ +/* A simple, memory-efficient bitset implementation. + + Copyright (C) 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include "Sbitset.h" + +Sbitset +Sbitset__new (Sbitset__Index nbits) +{ + /* Some functions, like Sbitset__last_byte_mask, will fail if nbits = 0. */ + aver (nbits); + return xcalloc (1, Sbitset__nbytes (nbits)); +} + +Sbitset +Sbitset__new_on_obstack (Sbitset__Index nbits, struct obstack *obstackp) +{ + Sbitset result; + Sbitset ptr; + Sbitset end; + aver (nbits); + result = obstack_alloc (obstackp, Sbitset__nbytes (nbits)); + for (ptr = result, end = result + Sbitset__nbytes (nbits); ptr < end; ++ptr) + *ptr = 0; + return result; +} + +void +Sbitset__delete (Sbitset self) +{ + free (self); +} + +bool +Sbitset__isEmpty (Sbitset self, Sbitset__Index nbits) +{ + Sbitset last = self + Sbitset__nbytes (nbits) - 1; + for (; self < last; ++self) + if (*self != 0) + return false; + return ((*last) & Sbitset__last_byte_mask (nbits)) == 0; +} + +void +Sbitset__fprint (Sbitset self, Sbitset__Index nbits, FILE *file) +{ + Sbitset__Index i; + Sbitset itr; + bool first = true; + fprintf (file, + "nbits = %" SBITSET__INDEX__CONVERSION_SPEC ", set = {", + nbits); + SBITSET__FOR_EACH (self, nbits, itr, i) + { + if (first) + first = false; + else + fprintf (file, ","); + fprintf (file, " %" SBITSET__INDEX__CONVERSION_SPEC, i); + } + fprintf (file, " }"); +} diff --git a/contrib/tools/bison/src/Sbitset.h b/contrib/tools/bison/src/Sbitset.h new file mode 100644 index 0000000000..bcb329ad39 --- /dev/null +++ b/contrib/tools/bison/src/Sbitset.h @@ -0,0 +1,92 @@ +/* A simple, memory-efficient bitset implementation. + + Copyright (C) 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef SBITSET_H_ +# define SBITSET_H_ + +typedef unsigned char *Sbitset; +typedef size_t Sbitset__Index; +# define SBITSET__INDEX__CONVERSION_SPEC "zu" + +# define Sbitset__nbytes(NBITS) \ + (((NBITS) + CHAR_BIT - 1) / CHAR_BIT) +# define Sbitset__byteAddress(SELF, INDEX) \ + (((SELF) + (INDEX) / CHAR_BIT)) +# define Sbitset__bit_mask(INDEX) \ + (1 << (CHAR_BIT - 1 - (INDEX) % CHAR_BIT)) +# define Sbitset__last_byte_mask(NBITS) \ + (UCHAR_MAX << (CHAR_BIT - 1 - ((NBITS) - 1) % CHAR_BIT)) + +/* nbits must not be 0. */ +Sbitset Sbitset__new (Sbitset__Index nbits); +Sbitset Sbitset__new_on_obstack (Sbitset__Index nbits, + struct obstack *obstackp); +void Sbitset__delete (Sbitset self); + +# define Sbitset__test(SELF, INDEX) \ + ((*Sbitset__byteAddress ((SELF), (INDEX)) & Sbitset__bit_mask (INDEX)) != 0) + +bool Sbitset__isEmpty (Sbitset self, Sbitset__Index nbits); + +void Sbitset__fprint (Sbitset self, Sbitset__Index nbits, FILE *file); + +# define Sbitset__set(SELF, INDEX) \ + do { \ + *Sbitset__byteAddress ((SELF), (INDEX)) = \ + *Sbitset__byteAddress ((SELF), (INDEX)) | Sbitset__bit_mask (INDEX); \ + } while (0) + +# define Sbitset__reset(SELF, INDEX) \ + do { \ + *Sbitset__byteAddress ((SELF), (INDEX)) = \ + *Sbitset__byteAddress ((SELF), (INDEX)) & ~Sbitset__bit_mask (INDEX); \ + } while (0) + +/* NBITS is the size of the bitset. More than NBITS bits might be reset. */ +# define Sbitset__zero(SELF, NBITS) \ + do { \ + memset (SELF, 0, Sbitset__nbytes (NBITS)); \ + } while (0) + +/* NBITS is the size of the bitset. More than NBITS bits might be set. */ +# define Sbitset__ones(SELF, NBITS) \ + do { \ + memset (SELF, UCHAR_MAX, Sbitset__nbytes (NBITS)); \ + } while (0) + +/* NBITS is the size of every bitset. More than NBITS bits might be set. */ +# define Sbitset__or(SELF, OTHER1, OTHER2, NBITS) \ + do { \ + Sbitset ptr_self = (SELF); \ + Sbitset ptr_other1 = (OTHER1); \ + Sbitset ptr_other2 = (OTHER2); \ + Sbitset end_self = ptr_self + Sbitset__nbytes (NBITS); \ + for (; ptr_self < end_self; ++ptr_self, ++ptr_other1, ++ptr_other2) \ + *ptr_self = *ptr_other1 | *ptr_other2; \ + } while (0) + +# define SBITSET__FOR_EACH(SELF, NBITS, ITER, INDEX) \ + for ((ITER) = (SELF); (ITER) < (SELF) + Sbitset__nbytes (NBITS); ++(ITER)) \ + if (*(ITER) != 0) \ + for ((INDEX) = ((ITER)-(SELF))*CHAR_BIT; \ + (INDEX) < (NBITS) && (SELF)+(INDEX)/CHAR_BIT < (ITER)+1; \ + ++(INDEX)) \ + if (((*ITER) & Sbitset__bit_mask (INDEX)) != 0) + +#endif /* !SBITSET_H_ */ diff --git a/contrib/tools/bison/src/assoc.c b/contrib/tools/bison/src/assoc.c new file mode 100644 index 0000000000..d2eec31574 --- /dev/null +++ b/contrib/tools/bison/src/assoc.c @@ -0,0 +1,50 @@ +/* Associativity information. + + Copyright (C) 2002, 2005-2006, 2008-2013 Free Software Foundation, + Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include "assoc.h" + + +const char * +assoc_to_string (assoc a) +{ + switch (a) + { + default: + abort (); + + case undef_assoc: + return "undefined associativity"; + + case right_assoc: + return "%right"; + + case left_assoc: + return "%left"; + + case non_assoc: + return "%nonassoc"; + + case precedence_assoc: + return "%precedence"; + } +} diff --git a/contrib/tools/bison/src/assoc.h b/contrib/tools/bison/src/assoc.h new file mode 100644 index 0000000000..b9475b5d12 --- /dev/null +++ b/contrib/tools/bison/src/assoc.h @@ -0,0 +1,35 @@ +/* Associativity information. + + Copyright (C) 2002, 2006, 2008-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef ASSOC_H_ +# define ASSOC_H_ + +/* Associativity values for tokens and rules. */ +typedef enum +{ + undef_assoc, /** Not defined. */ + right_assoc, /** %right */ + left_assoc, /** %left */ + non_assoc, /** %nonassoc */ + precedence_assoc /** %precedence */ +} assoc; + +char const *assoc_to_string (assoc a); + +#endif /* !ASSOC_H_ */ diff --git a/contrib/tools/bison/src/closure.c b/contrib/tools/bison/src/closure.c new file mode 100644 index 0000000000..45e8311022 --- /dev/null +++ b/contrib/tools/bison/src/closure.c @@ -0,0 +1,246 @@ +/* Closures for Bison + + Copyright (C) 1984, 1989, 2000-2002, 2004-2005, 2007, 2009-2013 Free + Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include <bitset.h> +#include <bitsetv-print.h> +#include <bitsetv.h> + +#include "closure.h" +#include "derives.h" +#include "getargs.h" +#include "gram.h" +#include "reader.h" +#include "symtab.h" + +/* NITEMSET is the size of the array ITEMSET. */ +item_number *itemset; +size_t nitemset; + +static bitset ruleset; + +/* internal data. See comments before set_fderives and set_firsts. */ +static bitsetv fderives = NULL; +static bitsetv firsts = NULL; + +/* Retrieve the FDERIVES/FIRSTS sets of the nonterminals numbered Var. */ +#define FDERIVES(Var) fderives[(Var) - ntokens] +#define FIRSTS(Var) firsts[(Var) - ntokens] + + +/*-----------------. +| Debugging code. | +`-----------------*/ + +static void +print_closure (char const *title, item_number const *array, size_t size) +{ + size_t i; + fprintf (stderr, "Closure: %s\n", title); + for (i = 0; i < size; ++i) + { + item_number *rp; + fprintf (stderr, " %2d: .", array[i]); + for (rp = &ritem[array[i]]; *rp >= 0; ++rp) + fprintf (stderr, " %s", symbols[*rp]->tag); + fprintf (stderr, " (rule %d)\n", -*rp - 1); + } + fputs ("\n\n", stderr); +} + + +static void +print_firsts (void) +{ + symbol_number i, j; + + fprintf (stderr, "FIRSTS\n"); + for (i = ntokens; i < nsyms; i++) + { + bitset_iterator iter; + fprintf (stderr, " %s firsts\n", symbols[i]->tag); + BITSET_FOR_EACH (iter, FIRSTS (i), j, 0) + fprintf (stderr, " %s\n", symbols[j + ntokens]->tag); + } + fprintf (stderr, "\n\n"); +} + + +static void +print_fderives (void) +{ + int i; + rule_number r; + + fprintf (stderr, "FDERIVES\n"); + for (i = ntokens; i < nsyms; i++) + { + bitset_iterator iter; + fprintf (stderr, " %s derives\n", symbols[i]->tag); + BITSET_FOR_EACH (iter, FDERIVES (i), r, 0) + { + fprintf (stderr, " %3d ", r); + rule_rhs_print (&rules[r], stderr); + fprintf (stderr, "\n"); + } + } + fprintf (stderr, "\n\n"); +} + +/*------------------------------------------------------------------. +| Set FIRSTS to be an NVARS array of NVARS bitsets indicating which | +| items can represent the beginning of the input corresponding to | +| which other items. | +| | +| For example, if some rule expands symbol 5 into the sequence of | +| symbols 8 3 20, the symbol 8 can be the beginning of the data for | +| symbol 5, so the bit [8 - ntokens] in first[5 - ntokens] (= FIRST | +| (5)) is set. | +`------------------------------------------------------------------*/ + +static void +set_firsts (void) +{ + symbol_number i, j; + + firsts = bitsetv_create (nvars, nvars, BITSET_FIXED); + + for (i = ntokens; i < nsyms; i++) + for (j = 0; derives[i - ntokens][j]; ++j) + { + item_number sym = derives[i - ntokens][j]->rhs[0]; + if (ISVAR (sym)) + bitset_set (FIRSTS (i), sym - ntokens); + } + + if (trace_flag & trace_sets) + bitsetv_matrix_dump (stderr, "RTC: Firsts Input", firsts); + bitsetv_reflexive_transitive_closure (firsts); + if (trace_flag & trace_sets) + bitsetv_matrix_dump (stderr, "RTC: Firsts Output", firsts); + + if (trace_flag & trace_sets) + print_firsts (); +} + +/*-------------------------------------------------------------------. +| Set FDERIVES to an NVARS by NRULES matrix of bits indicating which | +| rules can help derive the beginning of the data for each | +| nonterminal. | +| | +| For example, if symbol 5 can be derived as the sequence of symbols | +| 8 3 20, and one of the rules for deriving symbol 8 is rule 4, then | +| the [5 - NTOKENS, 4] bit in FDERIVES is set. | +`-------------------------------------------------------------------*/ + +static void +set_fderives (void) +{ + symbol_number i, j; + rule_number k; + + fderives = bitsetv_create (nvars, nrules, BITSET_FIXED); + + set_firsts (); + + for (i = ntokens; i < nsyms; ++i) + for (j = ntokens; j < nsyms; ++j) + if (bitset_test (FIRSTS (i), j - ntokens)) + for (k = 0; derives[j - ntokens][k]; ++k) + bitset_set (FDERIVES (i), derives[j - ntokens][k]->number); + + if (trace_flag & trace_sets) + print_fderives (); + + bitsetv_free (firsts); +} + + + +void +new_closure (unsigned int n) +{ + itemset = xnmalloc (n, sizeof *itemset); + + ruleset = bitset_create (nrules, BITSET_FIXED); + + set_fderives (); +} + + + +void +closure (item_number const *core, size_t n) +{ + /* Index over CORE. */ + size_t c; + + /* A bit index over RULESET. */ + rule_number ruleno; + + bitset_iterator iter; + + if (trace_flag & trace_sets) + print_closure ("input", core, n); + + bitset_zero (ruleset); + + for (c = 0; c < n; ++c) + if (ISVAR (ritem[core[c]])) + bitset_or (ruleset, ruleset, FDERIVES (ritem[core[c]])); + + /* core is sorted on item index in ritem, which is sorted on rule number. + Compute itemset with the same sort. */ + nitemset = 0; + c = 0; + BITSET_FOR_EACH (iter, ruleset, ruleno, 0) + { + item_number itemno = rules[ruleno].rhs - ritem; + while (c < n && core[c] < itemno) + { + itemset[nitemset] = core[c]; + nitemset++; + c++; + } + itemset[nitemset] = itemno; + nitemset++; + }; + + while (c < n) + { + itemset[nitemset] = core[c]; + nitemset++; + c++; + } + + if (trace_flag & trace_sets) + print_closure ("output", itemset, nitemset); +} + + +void +free_closure (void) +{ + free (itemset); + bitset_free (ruleset); + bitsetv_free (fderives); +} diff --git a/contrib/tools/bison/src/closure.h b/contrib/tools/bison/src/closure.h new file mode 100644 index 0000000000..ad4a3ba96b --- /dev/null +++ b/contrib/tools/bison/src/closure.h @@ -0,0 +1,57 @@ +/* Subroutines for bison + + Copyright (C) 1984, 1989, 2000-2002, 2007, 2009-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef CLOSURE_H_ +# define CLOSURE_H_ + +# include "gram.h" + +/* Allocates the itemset and ruleset vectors, and precomputes useful + data so that closure can be called. n is the number of elements to + allocate for itemset. */ + +void new_closure (unsigned int n); + + +/* Given the kernel (aka core) of a state (a sorted vector of item numbers + ITEMS, of length N), set up RULESET and ITEMSET to indicate what + rules could be run and which items could be accepted when those + items are the active ones. + + RULESET contains a bit for each rule. CLOSURE sets the bits for + all rules which could potentially describe the next input to be + read. + + ITEMSET is a sorted vector of item numbers; NITEMSET is its size + (actually, points to just beyond the end of the part of it that is + significant). CLOSURE places there the indices of all items which + represent units of input that could arrive next. */ + +void closure (item_number const *items, size_t n); + + +/* Frees ITEMSET, RULESET and internal data. */ + +void free_closure (void); + +extern item_number *itemset; +extern size_t nitemset; + +#endif /* !CLOSURE_H_ */ diff --git a/contrib/tools/bison/src/complain.c b/contrib/tools/bison/src/complain.c new file mode 100644 index 0000000000..fdc4b5426b --- /dev/null +++ b/contrib/tools/bison/src/complain.c @@ -0,0 +1,379 @@ +/* Declaration for error-reporting function for Bison. + + Copyright (C) 2000-2002, 2004-2006, 2009-2013 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Based on error.c and error.h, + written by David MacKenzie <djm@gnu.ai.mit.edu>. */ + +#include <config.h> +#include "system.h" + +#include <argmatch.h> +#include <stdarg.h> +#include <progname.h> + +#include "complain.h" +#include "files.h" +#include "getargs.h" +#include "quote.h" + +err_status complaint_status = status_none; + +bool warnings_are_errors = false; + +/** Diagnostics severity. */ +typedef enum + { + severity_disabled = 0, + severity_unset = 1, + severity_warning = 2, + severity_error = 3, + severity_fatal = 4 + } severity; + + +/** For each warning type, its severity. */ +static severity warnings_flag[warnings_size]; + +static unsigned *indent_ptr = 0; + +/*------------------------. +| --warnings's handling. | +`------------------------*/ + +static const char * const warnings_args[] = +{ + "none", + "midrule-values", + "yacc", + "conflicts-sr", + "conflicts-rr", + "deprecated", + "empty-rule", + "precedence", + "other", + "all", + "error", + "everything", + 0 +}; + +static const int warnings_types[] = +{ + Wnone, + Wmidrule_values, + Wyacc, + Wconflicts_sr, + Wconflicts_rr, + Wdeprecated, + Wempty_rule, + Wprecedence, + Wother, + Wall, + Werror, + Weverything +}; + +ARGMATCH_VERIFY (warnings_args, warnings_types); + +void +warning_argmatch (char const *arg, size_t no, size_t err) +{ + int value = XARGMATCH ("--warning", arg + no + err, + warnings_args, warnings_types); + + /* -Wnone == -Wno-everything, and -Wno-none == -Weverything. */ + if (!value) + { + value = Weverything; + no = !no; + } + + if (no) + { + size_t b; + for (b = 0; b < warnings_size; ++b) + if (value & 1 << b) + { + if (err) + { + /* -Wno-error=foo: if foo enabled as an error, + make it a warning. */ + if (warnings_flag[b] == severity_error) + warnings_flag[b] = severity_warning; + } + else + /* -Wno-foo. */ + warnings_flag[b] = severity_disabled; + } + } + else + { + size_t b; + for (b = 0; b < warnings_size; ++b) + if (value & 1 << b) + /* -Wfoo and -Werror=foo. */ + warnings_flag[b] = err ? severity_error : severity_warning; + } +} + +/** Decode a comma-separated list of arguments from -W. + * + * \param args comma separated list of effective subarguments to decode. + * If 0, then activate all the flags. + */ + +void +warnings_argmatch (char *args) +{ + if (args) + for (args = strtok (args, ","); args; args = strtok (NULL, ",")) + if (STREQ (args, "error")) + warnings_are_errors = true; + else if (STREQ (args, "no-error")) + { + warnings_are_errors = false; + warning_argmatch ("no-error=everything", 3, 6); + } + else + { + size_t no = STRPREFIX_LIT ("no-", args) ? 3 : 0; + size_t err = STRPREFIX_LIT ("error=", args + no) ? 6 : 0; + + warning_argmatch (args, no, err); + } + else + warning_argmatch ("all", 0, 0); +} + + +/*-----------. +| complain. | +`-----------*/ + +void +complain_init (void) +{ + warnings warnings_default = + Wconflicts_sr | Wconflicts_rr | Wdeprecated | Wother; + + size_t b; + for (b = 0; b < warnings_size; ++b) + warnings_flag[b] = (1 << b & warnings_default + ? severity_warning + : severity_unset); +} + +static severity +warning_severity (warnings flags) +{ + if (flags & fatal) + return severity_fatal; + else if (flags & complaint) + return severity_error; + else + { + severity res = severity_disabled; + size_t b; + for (b = 0; b < warnings_size; ++b) + if (flags & 1 << b) + res = res < warnings_flag[b] ? warnings_flag[b] : res; + if (res == severity_warning && warnings_are_errors) + res = severity_error; + return res; + } +} + +bool +warning_is_unset (warnings flags) +{ + size_t b; + for (b = 0; b < warnings_size; ++b) + if (flags & 1 << b && warnings_flag[b] != severity_unset) + return false; + return true; +} + +/** Display a "[-Wyacc]" like message on \a f. */ + +static void +warnings_print_categories (warnings warn_flags, FILE *f) +{ + /* Display only the first match, the second is "-Wall". */ + size_t i; + for (i = 0; warnings_args[i]; ++i) + if (warn_flags & warnings_types[i]) + { + severity s = warning_severity (warnings_types[i]); + fprintf (f, " [-W%s%s]", + s == severity_error ? "error=" : "", + warnings_args[i]); + return; + } +} + +/** Report an error message. + * + * \param loc the location, defaulting to the current file, + * or the program name. + * \param flags the category for this message. + * \param prefix put before the message (e.g., "warning"). + * \param message the error message, a printf format string. Iff it + * ends with ": ", then no trailing newline is printed, + * and the caller should print the remaining + * newline-terminated message to stderr. + * \param args the arguments of the format string. + */ +static +void +error_message (const location *loc, warnings flags, const char *prefix, + const char *message, va_list args) +{ + unsigned pos = 0; + + if (loc) + pos += location_print (*loc, stderr); + else + pos += fprintf (stderr, "%s", current_file ? current_file : program_name); + pos += fprintf (stderr, ": "); + + if (indent_ptr) + { + if (*indent_ptr) + prefix = NULL; + if (!*indent_ptr) + *indent_ptr = pos; + else if (*indent_ptr > pos) + fprintf (stderr, "%*s", *indent_ptr - pos, ""); + indent_ptr = 0; + } + + if (prefix) + fprintf (stderr, "%s: ", prefix); + + vfprintf (stderr, message, args); + if (! (flags & silent)) + warnings_print_categories (flags, stderr); + { + size_t l = strlen (message); + if (l < 2 || message[l - 2] != ':' || message[l - 1] != ' ') + { + putc ('\n', stderr); + fflush (stderr); + if (loc && feature_flag & feature_caret && !(flags & no_caret)) + location_caret (*loc, stderr); + } + } + fflush (stderr); +} + +/** Raise a complaint. That can be a fatal error, an error or just a + warning. */ + +static void +complains (const location *loc, warnings flags, const char *message, + va_list args) +{ + severity s = warning_severity (flags); + if ((flags & complaint) && complaint_status < status_complaint) + complaint_status = status_complaint; + + if (severity_warning <= s) + { + const char* prefix = + s == severity_fatal ? _("fatal error") + : s == severity_error ? _("error") + : _("warning"); + if (severity_error <= s && ! complaint_status) + complaint_status = status_warning_as_error; + error_message (loc, flags, prefix, message, args); + } + + if (flags & fatal) + exit (EXIT_FAILURE); +} + +void +complain (location const *loc, warnings flags, const char *message, ...) +{ + va_list args; + va_start (args, message); + complains (loc, flags, message, args); + va_end (args); +} + +void +complain_indent (location const *loc, warnings flags, unsigned *indent, + const char *message, ...) +{ + va_list args; + indent_ptr = indent; + va_start (args, message); + complains (loc, flags, message, args); + va_end (args); +} + +void +complain_args (location const *loc, warnings w, unsigned *indent, + int argc, char *argv[]) +{ + switch (argc) + { + case 1: + complain_indent (loc, w, indent, "%s", _(argv[0])); + break; + case 2: + complain_indent (loc, w, indent, _(argv[0]), argv[1]); + break; + case 3: + complain_indent (loc, w, indent, _(argv[0]), argv[1], argv[2]); + break; + case 4: + complain_indent (loc, w, indent, _(argv[0]), argv[1], argv[2], argv[3]); + break; + case 5: + complain_indent (loc, w, indent, _(argv[0]), argv[1], argv[2], argv[3], + argv[4]); + break; + default: + complain (loc, fatal, "too many arguments for complains"); + break; + } +} + +void +deprecated_directive (location const *loc, char const *old, char const *upd) +{ + if (feature_flag & feature_caret) + complain (loc, Wdeprecated, + _("deprecated directive, use %s"), + quote_n (1, upd)); + else + complain (loc, Wdeprecated, + _("deprecated directive: %s, use %s"), + quote (old), quote_n (1, upd)); +} + +void +duplicate_directive (char const *directive, + location first, location second) +{ + unsigned i = 0; + complain (&second, complaint, _("only one %s allowed per rule"), directive); + i += SUB_INDENT; + complain_indent (&first, complaint, &i, _("previous declaration")); +} diff --git a/contrib/tools/bison/src/complain.h b/contrib/tools/bison/src/complain.h new file mode 100644 index 0000000000..0d81503df7 --- /dev/null +++ b/contrib/tools/bison/src/complain.h @@ -0,0 +1,144 @@ +/* Declaration for error-reporting function for Bison. + + Copyright (C) 2000-2002, 2006, 2009-2013 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef COMPLAIN_H_ +# define COMPLAIN_H_ 1 + +# include "location.h" + +/* Sub-messages indent. */ +# define SUB_INDENT (4) + +/*-------------. +| --warnings. | +`-------------*/ + +/** The bits assigned to each warning type. */ +typedef enum + { + warning_midrule_values, /**< Unset or unused midrule values. */ + warning_yacc, /**< POSIXME. */ + warning_conflicts_sr, /**< S/R conflicts. */ + warning_conflicts_rr, /**< R/R conflicts. */ + warning_empty_rule, /**< Implicitly empty rules. */ + warning_deprecated, /**< Obsolete constructs. */ + warning_precedence, /**< Useless precedence and associativity. */ + warning_other, /**< All other warnings. */ + + warnings_size /**< The number of warnings. Must be last. */ + } warning_bit; + +/** Whether -Werror was set. */ +extern bool warnings_are_errors; + +/** Decode a single argument from -W. + * + * \param arg the subarguments to decode. + * If null, then activate all the flags. + * \param no length of the potential "no-" prefix. + * Can be 0 or 3. If 3, negate the action of the subargument. + * \param err length of a potential "error=". + * Can be 0 or 6. If 6, treat the subargument as a CATEGORY. + * + * If VALUE != 0 then KEY sets flags and no-KEY clears them. + * If VALUE == 0 then KEY clears all flags from \c all and no-KEY sets all + * flags from \c all. Thus no-none = all and no-all = none. + */ +void warning_argmatch (char const *arg, size_t no, size_t err); + +/** Decode a comma-separated list of arguments from -W. + * + * \param args comma separated list of effective subarguments to decode. + * If 0, then activate all the flags. + */ +void warnings_argmatch (char *args); + + +/*-----------. +| complain. | +`-----------*/ + +/** Initialize this module. */ +void complain_init (void); + +typedef enum + { + /**< Issue no warnings. */ + Wnone = 0, + + Wmidrule_values = 1 << warning_midrule_values, + Wyacc = 1 << warning_yacc, + Wconflicts_sr = 1 << warning_conflicts_sr, + Wconflicts_rr = 1 << warning_conflicts_rr, + Wdeprecated = 1 << warning_deprecated, + Wempty_rule = 1 << warning_empty_rule, + Wprecedence = 1 << warning_precedence, + Wother = 1 << warning_other, + + Werror = 1 << 10, /** This bit is no longer used. */ + + complaint = 1 << 11, /**< All complaints. */ + fatal = 1 << 12, /**< All fatal errors. */ + silent = 1 << 13, /**< Do not display the warning type. */ + no_caret = 1 << 14, /**< Do not display caret location. */ + + /**< All above warnings. */ + Weverything = ~complaint & ~fatal & ~silent, + Wall = Weverything & ~Wyacc + } warnings; + +/** Whether the warnings of \a flags are all unset. + (Never enabled, never disabled). */ +bool warning_is_unset (warnings flags); + +/** Make a complaint, with maybe a location. */ +void complain (location const *loc, warnings flags, char const *message, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); + +/** Likewise, but with an \a argc/argv interface. */ +void complain_args (location const *loc, warnings w, unsigned *indent, + int argc, char *arg[]); + +/** Make a complaint with location and some indentation. */ +void complain_indent (location const *loc, warnings flags, unsigned *indent, + char const *message, ...) + __attribute__ ((__format__ (__printf__, 4, 5))); + + +/** Report an obsolete syntax, suggest the updated one. */ +void deprecated_directive (location const *loc, + char const *obsolete, char const *updated); + +/** Report a repeated directive for a rule. */ +void duplicate_directive (char const *directive, + location first, location second); + +/** Warnings treated as errors shouldn't stop the execution as regular errors + should (because due to their nature, it is safe to go on). Thus, there are + three possible execution statuses. */ +typedef enum + { + status_none, + status_warning_as_error, + status_complaint + } err_status; + +/** Whether an error was reported. */ +extern err_status complaint_status; + +#endif /* !COMPLAIN_H_ */ diff --git a/contrib/tools/bison/src/conflicts.c b/contrib/tools/bison/src/conflicts.c new file mode 100644 index 0000000000..1840473620 --- /dev/null +++ b/contrib/tools/bison/src/conflicts.c @@ -0,0 +1,629 @@ +/* Find and resolve or report lookahead conflicts for bison, + + Copyright (C) 1984, 1989, 1992, 2000-2013 Free Software Foundation, + Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include <bitset.h> + +#include "LR0.h" +#include "complain.h" +#include "conflicts.h" +#include "files.h" +#include "getargs.h" +#include "gram.h" +#include "lalr.h" +#include "print-xml.h" +#include "reader.h" +#include "state.h" +#include "symtab.h" + +/* -1 stands for not specified. */ +int expected_sr_conflicts = -1; +int expected_rr_conflicts = -1; +static char *conflicts; +static struct obstack solved_conflicts_obstack; +static struct obstack solved_conflicts_xml_obstack; + +static bitset shift_set; +static bitset lookahead_set; + + + +enum conflict_resolution + { + shift_resolution, + reduce_resolution, + left_resolution, + right_resolution, + nonassoc_resolution + }; + + +/*----------------------------------------------------------------. +| Explain how an SR conflict between TOKEN and RULE was resolved: | +| RESOLUTION. | +`----------------------------------------------------------------*/ + +static inline void +log_resolution (rule *r, symbol_number token, + enum conflict_resolution resolution) +{ + if (report_flag & report_solved_conflicts) + { + /* The description of the resolution. */ + switch (resolution) + { + case shift_resolution: + case right_resolution: + obstack_printf (&solved_conflicts_obstack, + _(" Conflict between rule %d and token %s" + " resolved as shift"), + r->number, + symbols[token]->tag); + break; + + case reduce_resolution: + case left_resolution: + obstack_printf (&solved_conflicts_obstack, + _(" Conflict between rule %d and token %s" + " resolved as reduce"), + r->number, + symbols[token]->tag); + break; + + case nonassoc_resolution: + obstack_printf (&solved_conflicts_obstack, + _(" Conflict between rule %d and token %s" + " resolved as an error"), + r->number, + symbols[token]->tag); + break; + } + + /* The reason. */ + switch (resolution) + { + case shift_resolution: + obstack_printf (&solved_conflicts_obstack, + " (%s < %s)", + r->prec->tag, + symbols[token]->tag); + break; + + case reduce_resolution: + obstack_printf (&solved_conflicts_obstack, + " (%s < %s)", + symbols[token]->tag, + r->prec->tag); + break; + + case left_resolution: + obstack_printf (&solved_conflicts_obstack, + " (%%left %s)", + symbols[token]->tag); + break; + + case right_resolution: + obstack_printf (&solved_conflicts_obstack, + " (%%right %s)", + symbols[token]->tag); + break; + + case nonassoc_resolution: + obstack_printf (&solved_conflicts_obstack, + " (%%nonassoc %s)", + symbols[token]->tag); + break; + } + + obstack_sgrow (&solved_conflicts_obstack, ".\n"); + } + + /* XML report */ + if (xml_flag) + { + /* The description of the resolution. */ + switch (resolution) + { + case shift_resolution: + case right_resolution: + obstack_printf (&solved_conflicts_xml_obstack, + " <resolution rule=\"%d\" symbol=\"%s\"" + " type=\"shift\">", + r->number, + xml_escape (symbols[token]->tag)); + break; + + case reduce_resolution: + case left_resolution: + obstack_printf (&solved_conflicts_xml_obstack, + " <resolution rule=\"%d\" symbol=\"%s\"" + " type=\"reduce\">", + r->number, + xml_escape (symbols[token]->tag)); + break; + + case nonassoc_resolution: + obstack_printf (&solved_conflicts_xml_obstack, + " <resolution rule=\"%d\" symbol=\"%s\"" + " type=\"error\">", + r->number, + xml_escape (symbols[token]->tag)); + break; + } + + /* The reason. */ + switch (resolution) + { + case shift_resolution: + obstack_printf (&solved_conflicts_xml_obstack, + "%s < %s", + xml_escape_n (0, r->prec->tag), + xml_escape_n (1, symbols[token]->tag)); + break; + + case reduce_resolution: + obstack_printf (&solved_conflicts_xml_obstack, + "%s < %s", + xml_escape_n (0, symbols[token]->tag), + xml_escape_n (1, r->prec->tag)); + break; + + case left_resolution: + obstack_printf (&solved_conflicts_xml_obstack, + "%%left %s", + xml_escape (symbols[token]->tag)); + break; + + case right_resolution: + obstack_printf (&solved_conflicts_xml_obstack, + "%%right %s", + xml_escape (symbols[token]->tag)); + break; + + case nonassoc_resolution: + obstack_printf (&solved_conflicts_xml_obstack, + "%%nonassoc %s", + xml_escape (symbols[token]->tag)); + break; + } + + obstack_sgrow (&solved_conflicts_xml_obstack, "</resolution>\n"); + } +} + + +/*------------------------------------------------------------------. +| Turn off the shift recorded for the specified token in the | +| specified state. Used when we resolve a shift-reduce conflict in | +| favor of the reduction or as an error (%nonassoc). | +`------------------------------------------------------------------*/ + +static void +flush_shift (state *s, int token) +{ + transitions *trans = s->transitions; + int i; + + bitset_reset (lookahead_set, token); + for (i = 0; i < trans->num; i++) + if (!TRANSITION_IS_DISABLED (trans, i) + && TRANSITION_SYMBOL (trans, i) == token) + TRANSITION_DISABLE (trans, i); +} + + +/*--------------------------------------------------------------------. +| Turn off the reduce recorded for the specified token in the | +| specified lookahead set. Used when we resolve a shift-reduce | +| conflict in favor of the shift or as an error (%nonassoc). | +`--------------------------------------------------------------------*/ + +static void +flush_reduce (bitset lookahead_tokens, int token) +{ + bitset_reset (lookahead_tokens, token); +} + + +/*------------------------------------------------------------------. +| Attempt to resolve shift-reduce conflict for one rule by means of | +| precedence declarations. It has already been checked that the | +| rule has a precedence. A conflict is resolved by modifying the | +| shift or reduce tables so that there is no longer a conflict. | +| | +| RULENO is the number of the lookahead bitset to consider. | +| | +| ERRORS and NERRS can be used to store discovered explicit | +| errors. | +`------------------------------------------------------------------*/ + +static void +resolve_sr_conflict (state *s, int ruleno, symbol **errors, int *nerrs) +{ + symbol_number i; + reductions *reds = s->reductions; + /* Find the rule to reduce by to get precedence of reduction. */ + rule *redrule = reds->rules[ruleno]; + int redprec = redrule->prec->prec; + bitset lookahead_tokens = reds->lookahead_tokens[ruleno]; + + for (i = 0; i < ntokens; i++) + if (bitset_test (lookahead_tokens, i) + && bitset_test (lookahead_set, i) + && symbols[i]->prec) + { + /* Shift-reduce conflict occurs for token number i + and it has a precedence. + The precedence of shifting is that of token i. */ + if (symbols[i]->prec < redprec) + { + register_precedence (redrule->prec->number, i); + log_resolution (redrule, i, reduce_resolution); + flush_shift (s, i); + } + else if (symbols[i]->prec > redprec) + { + register_precedence (i, redrule->prec->number); + log_resolution (redrule, i, shift_resolution); + flush_reduce (lookahead_tokens, i); + } + else + /* Matching precedence levels. + For non-defined associativity, keep both: unexpected + associativity conflict. + For left associativity, keep only the reduction. + For right associativity, keep only the shift. + For nonassociativity, keep neither. */ + + switch (symbols[i]->assoc) + { + case undef_assoc: + abort (); + + case precedence_assoc: + break; + + case right_assoc: + register_assoc (i, redrule->prec->number); + log_resolution (redrule, i, right_resolution); + flush_reduce (lookahead_tokens, i); + break; + + case left_assoc: + register_assoc (i, redrule->prec->number); + log_resolution (redrule, i, left_resolution); + flush_shift (s, i); + break; + + case non_assoc: + register_assoc (i, redrule->prec->number); + log_resolution (redrule, i, nonassoc_resolution); + flush_shift (s, i); + flush_reduce (lookahead_tokens, i); + /* Record an explicit error for this token. */ + errors[(*nerrs)++] = symbols[i]; + break; + } + } +} + + +/*-------------------------------------------------------------------. +| Solve the S/R conflicts of state S using the | +| precedence/associativity, and flag it inconsistent if it still has | +| conflicts. ERRORS can be used as storage to compute the list of | +| lookahead tokens on which S raises a syntax error (%nonassoc). | +`-------------------------------------------------------------------*/ + +static void +set_conflicts (state *s, symbol **errors) +{ + int i; + transitions *trans = s->transitions; + reductions *reds = s->reductions; + int nerrs = 0; + + if (s->consistent) + return; + + bitset_zero (lookahead_set); + + FOR_EACH_SHIFT (trans, i) + bitset_set (lookahead_set, TRANSITION_SYMBOL (trans, i)); + + /* Loop over all rules which require lookahead in this state. First + check for shift-reduce conflict, and try to resolve using + precedence. */ + for (i = 0; i < reds->num; ++i) + if (reds->rules[i]->prec && reds->rules[i]->prec->prec + && !bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set)) + resolve_sr_conflict (s, i, errors, &nerrs); + + if (nerrs) + { + /* Some tokens have been explicitly made errors. Allocate a + permanent errs structure for this state, to record them. */ + state_errs_set (s, nerrs, errors); + } + if (obstack_object_size (&solved_conflicts_obstack)) + s->solved_conflicts = obstack_finish0 (&solved_conflicts_obstack); + if (obstack_object_size (&solved_conflicts_xml_obstack)) + s->solved_conflicts_xml = obstack_finish0 (&solved_conflicts_xml_obstack); + + /* Loop over all rules which require lookahead in this state. Check + for conflicts not resolved above. */ + for (i = 0; i < reds->num; ++i) + { + if (!bitset_disjoint_p (reds->lookahead_tokens[i], lookahead_set)) + conflicts[s->number] = 1; + bitset_or (lookahead_set, lookahead_set, reds->lookahead_tokens[i]); + } +} + + +/*----------------------------------------------------------------. +| Solve all the S/R conflicts using the precedence/associativity, | +| and flag as inconsistent the states that still have conflicts. | +`----------------------------------------------------------------*/ + +void +conflicts_solve (void) +{ + state_number i; + /* List of lookahead tokens on which we explicitly raise a syntax error. */ + symbol **errors = xnmalloc (ntokens + 1, sizeof *errors); + + conflicts = xcalloc (nstates, sizeof *conflicts); + shift_set = bitset_create (ntokens, BITSET_FIXED); + lookahead_set = bitset_create (ntokens, BITSET_FIXED); + obstack_init (&solved_conflicts_obstack); + obstack_init (&solved_conflicts_xml_obstack); + + for (i = 0; i < nstates; i++) + { + set_conflicts (states[i], errors); + + /* For uniformity of the code, make sure all the states have a valid + 'errs' member. */ + if (!states[i]->errs) + states[i]->errs = errs_new (0, 0); + } + + free (errors); +} + + +void +conflicts_update_state_numbers (state_number old_to_new[], + state_number nstates_old) +{ + state_number i; + for (i = 0; i < nstates_old; ++i) + if (old_to_new[i] != nstates_old) + conflicts[old_to_new[i]] = conflicts[i]; +} + + +/*---------------------------------------------. +| Count the number of shift/reduce conflicts. | +`---------------------------------------------*/ + +static size_t +count_state_sr_conflicts (state *s) +{ + int i; + transitions *trans = s->transitions; + reductions *reds = s->reductions; + + if (!trans) + return 0; + + bitset_zero (lookahead_set); + bitset_zero (shift_set); + + FOR_EACH_SHIFT (trans, i) + bitset_set (shift_set, TRANSITION_SYMBOL (trans, i)); + + for (i = 0; i < reds->num; ++i) + bitset_or (lookahead_set, lookahead_set, reds->lookahead_tokens[i]); + + bitset_and (lookahead_set, lookahead_set, shift_set); + + return bitset_count (lookahead_set); +} + +/*---------------------------------------------. +| The total number of shift/reduce conflicts. | +`---------------------------------------------*/ + +static size_t +count_sr_conflicts (void) +{ + size_t res = 0; + state_number i; + + /* Conflicts by state. */ + for (i = 0; i < nstates; i++) + if (conflicts[i]) + res += count_state_sr_conflicts (states[i]); + return res; +} + + + +/*----------------------------------------------------------------. +| Count the number of reduce/reduce conflicts. If ONE_PER_TOKEN, | +| count one conflict for each token that has any reduce/reduce | +| conflicts. Otherwise, count one conflict for each pair of | +| conflicting reductions. | +`----------------------------------------------------------------*/ + +static size_t +count_state_rr_conflicts (state *s, bool one_per_token) +{ + int i; + reductions *reds = s->reductions; + size_t res = 0; + + for (i = 0; i < ntokens; i++) + { + int count = 0; + int j; + for (j = 0; j < reds->num; ++j) + count += bitset_test (reds->lookahead_tokens[j], i); + if (count >= 2) + res += one_per_token ? 1 : count-1; + } + + return res; +} + +static size_t +count_rr_conflicts (bool one_per_token) +{ + size_t res = 0; + state_number i; + + /* Conflicts by state. */ + for (i = 0; i < nstates; i++) + if (conflicts[i]) + res += count_state_rr_conflicts (states[i], one_per_token); + return res; +} + + +/*-----------------------------------------------------------. +| Output the detailed description of states with conflicts. | +`-----------------------------------------------------------*/ + +void +conflicts_output (FILE *out) +{ + bool printed_sth = false; + state_number i; + for (i = 0; i < nstates; i++) + { + state *s = states[i]; + if (conflicts[i]) + { + int src = count_state_sr_conflicts (s); + int rrc = count_state_rr_conflicts (s, true); + fprintf (out, _("State %d "), i); + if (src && rrc) + fprintf (out, + _("conflicts: %d shift/reduce, %d reduce/reduce\n"), + src, rrc); + else if (src) + fprintf (out, _("conflicts: %d shift/reduce\n"), src); + else if (rrc) + fprintf (out, _("conflicts: %d reduce/reduce\n"), rrc); + printed_sth = true; + } + } + if (printed_sth) + fputs ("\n\n", out); +} + +/*--------------------------------------------------------. +| Total the number of S/R and R/R conflicts. Unlike the | +| code in conflicts_output, however, count EACH pair of | +| reductions for the same state and lookahead as one | +| conflict. | +`--------------------------------------------------------*/ + +int +conflicts_total_count (void) +{ + return count_sr_conflicts () + count_rr_conflicts (false); +} + + +/*------------------------------------------. +| Reporting the total number of conflicts. | +`------------------------------------------*/ + +void +conflicts_print (void) +{ + if (! glr_parser && expected_rr_conflicts != -1) + { + complain (NULL, Wother, _("%%expect-rr applies only to GLR parsers")); + expected_rr_conflicts = -1; + } + + /* Screams for factoring, but almost useless because of the + different strings to translate. */ + { + int total = count_sr_conflicts (); + /* If %expect is not used, but %expect-rr is, then expect 0 sr. */ + int expected = + (expected_sr_conflicts == -1 && expected_rr_conflicts != -1) + ? 0 + : expected_sr_conflicts; + if (expected != -1) + { + if (expected != total) + complain (NULL, complaint, + _("shift/reduce conflicts: %d found, %d expected"), + total, expected); + } + else if (total) + complain (NULL, Wconflicts_sr, + ngettext ("%d shift/reduce conflict", + "%d shift/reduce conflicts", + total), + total); + } + + { + int total = count_rr_conflicts (true); + /* If %expect-rr is not used, but %expect is, then expect 0 rr. */ + int expected = + (expected_rr_conflicts == -1 && expected_sr_conflicts != -1) + ? 0 + : expected_rr_conflicts; + if (expected != -1) + { + if (expected != total) + complain (NULL, complaint, + _("reduce/reduce conflicts: %d found, %d expected"), + total, expected); + } + else if (total) + complain (NULL, Wconflicts_rr, + ngettext ("%d reduce/reduce conflict", + "%d reduce/reduce conflicts", + total), + total); + } +} + + +void +conflicts_free (void) +{ + free (conflicts); + bitset_free (shift_set); + bitset_free (lookahead_set); + obstack_free (&solved_conflicts_obstack, NULL); + obstack_free (&solved_conflicts_xml_obstack, NULL); +} diff --git a/contrib/tools/bison/src/conflicts.h b/contrib/tools/bison/src/conflicts.h new file mode 100644 index 0000000000..5df5787162 --- /dev/null +++ b/contrib/tools/bison/src/conflicts.h @@ -0,0 +1,47 @@ +/* Find and resolve or report lookahead conflicts for bison, + + Copyright (C) 2000-2002, 2004, 2007, 2009-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef CONFLICTS_H_ +# define CONFLICTS_H_ +# include "state.h" + +void conflicts_solve (void); + +/** + * Update state numbers recorded in internal arrays such that: + * - \c nstates_old is the old number of states. + * - Where \c i is the old state number, <tt>old_to_new[i]</tt> is either: + * - \c nstates_old if state \c i is removed because it is unreachable. + * - The new state number. + * - The highest new state number is the number of remaining states - 1. + * - The numerical order of the remaining states has not changed. + */ +void conflicts_update_state_numbers (state_number old_to_new[], + state_number nstates_old); + +void conflicts_print (void); +int conflicts_total_count (void); +void conflicts_output (FILE *out); +void conflicts_free (void); + +/* Were there conflicts? */ +extern int expected_sr_conflicts; +extern int expected_rr_conflicts; +#endif /* !CONFLICTS_H_ */ diff --git a/contrib/tools/bison/src/derives.c b/contrib/tools/bison/src/derives.c new file mode 100644 index 0000000000..c834f0b0d0 --- /dev/null +++ b/contrib/tools/bison/src/derives.c @@ -0,0 +1,120 @@ +/* Match rules with nonterminals for bison, + + Copyright (C) 1984, 1989, 2000-2003, 2005, 2009-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include "getargs.h" + +#include "derives.h" +#include "gram.h" +#include "reader.h" +#include "symtab.h" + +/* Linked list of rule numbers. */ +typedef struct rule_list +{ + struct rule_list *next; + rule *value; +} rule_list; + +rule ***derives; + +static void +print_derives (void) +{ + int i; + + fputs ("DERIVES\n", stderr); + + for (i = ntokens; i < nsyms; i++) + { + rule **rp; + fprintf (stderr, " %s derives\n", symbols[i]->tag); + for (rp = derives[i - ntokens]; *rp; ++rp) + { + fprintf (stderr, " %3d ", (*rp)->user_number); + rule_rhs_print (*rp, stderr); + fprintf (stderr, "\n"); + } + } + + fputs ("\n\n", stderr); +} + + +void +derives_compute (void) +{ + symbol_number i; + rule_number r; + rule **q; + + /* DSET[NTERM - NTOKENS] -- A linked list of the numbers of the rules + whose LHS is NTERM. */ + rule_list **dset = xcalloc (nvars, sizeof *dset); + + /* DELTS[RULE] -- There are NRULES rule number to attach to nterms. + Instead of performing NRULES allocations for each, have an array + indexed by rule numbers. */ + rule_list *delts = xnmalloc (nrules, sizeof *delts); + + for (r = nrules - 1; r >= 0; --r) + { + symbol_number lhs = rules[r].lhs->number; + rule_list *p = &delts[r]; + /* A new LHS is found. */ + p->next = dset[lhs - ntokens]; + p->value = &rules[r]; + dset[lhs - ntokens] = p; + } + + /* DSET contains what we need under the form of a linked list. Make + it a single array. */ + + derives = xnmalloc (nvars, sizeof *derives); + q = xnmalloc (nvars + nrules, sizeof *q); + + for (i = ntokens; i < nsyms; i++) + { + rule_list *p = dset[i - ntokens]; + derives[i - ntokens] = q; + while (p) + { + *q++ = p->value; + p = p->next; + } + *q++ = NULL; + } + + if (trace_flag & trace_sets) + print_derives (); + + free (dset); + free (delts); +} + + +void +derives_free (void) +{ + free (derives[0]); + free (derives); +} diff --git a/contrib/tools/bison/src/derives.h b/contrib/tools/bison/src/derives.h new file mode 100644 index 0000000000..ea8dff7231 --- /dev/null +++ b/contrib/tools/bison/src/derives.h @@ -0,0 +1,35 @@ +/* Match rules with nonterminals for bison, + + Copyright (C) 1984, 1989, 2000-2002, 2009-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef DERIVES_H_ +# define DERIVES_H_ + +# include "gram.h" + +/* DERIVES[SYMBOL - NTOKENS] points to a vector of the rules that + SYMBOL derives, terminated with NULL. */ +extern rule ***derives; + +/* Compute DERIVES. */ + +void derives_compute (void); +void derives_free (void); + +#endif /* !DERIVES_H_ */ diff --git a/contrib/tools/bison/src/files.c b/contrib/tools/bison/src/files.c new file mode 100644 index 0000000000..3b219229bc --- /dev/null +++ b/contrib/tools/bison/src/files.c @@ -0,0 +1,420 @@ +/* Open and close files for Bison. + + Copyright (C) 1984, 1986, 1989, 1992, 2000-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include <error.h> +#include <dirname.h> +#include <get-errno.h> +#include <quote.h> +#include <quotearg.h> +#include <stdio-safer.h> +#include <xstrndup.h> +#include <stdlib.h> +#include <string.h> + +#include "complain.h" +#include "files.h" +#include "getargs.h" +#include "gram.h" + +/* Initializing some values below (such SPEC_NAME_PREFIX to 'yy') is + tempting, but don't do that: for the time being our handling of the + %directive vs --option leaves precedence to the options by deciding + that if a %directive sets a variable which is really set (i.e., not + NULL), then the %directive is ignored. As a result, %name-prefix, + for instance, will not be honored. */ + +char const *spec_outfile = NULL; /* for -o. */ +char const *spec_file_prefix = NULL; /* for -b. */ +char const *spec_name_prefix = NULL; /* for -p. */ +char *spec_verbose_file = NULL; /* for --verbose. */ +char *spec_graph_file = NULL; /* for -g. */ +char *spec_xml_file = NULL; /* for -x. */ +char *spec_defines_file = NULL; /* for --defines. */ +char *parser_file_name; + +/* All computed output file names. */ +static char **file_names = NULL; +static int file_names_count = 0; + +uniqstr grammar_file = NULL; +uniqstr current_file = NULL; + +/* If --output=dir/foo.c was specified, + DIR_PREFIX is 'dir/' and ALL_BUT_EXT and ALL_BUT_TAB_EXT are 'dir/foo'. + + If --output=dir/foo.tab.c was specified, DIR_PREFIX is 'dir/', + ALL_BUT_EXT is 'dir/foo.tab', and ALL_BUT_TAB_EXT is 'dir/foo'. + + If --output was not specified but --file-prefix=dir/foo was specified, + ALL_BUT_EXT = 'foo.tab' and ALL_BUT_TAB_EXT = 'foo'. + + If neither --output nor --file was specified but the input grammar + is name dir/foo.y, ALL_BUT_EXT and ALL_BUT_TAB_EXT are 'foo'. + + If neither --output nor --file was specified, DIR_PREFIX is the + empty string (meaning the current directory); otherwise it is + 'dir/'. */ + +char *all_but_ext; +static char *all_but_tab_ext; +char *dir_prefix; + +/* C source file extension (the parser source). */ +static char *src_extension = NULL; +/* Header file extension (if option '`-d'' is specified). */ +static char *header_extension = NULL; + +/*-----------------------------------------------------------------. +| Return a newly allocated string composed of the concatenation of | +| STR1, and STR2. | +`-----------------------------------------------------------------*/ + +#if defined _win_ || defined _WIN64 || defined _WIN32 || defined __WIN32__ +char *stpcpy(char *dst, const char *src); +#endif + +static char * +concat2 (char const *str1, char const *str2) +{ + size_t len = strlen (str1) + strlen (str2); + char *res = xmalloc (len + 1); + char *cp; + cp = stpcpy (res, str1); + cp = stpcpy (cp, str2); + return res; +} + +/*-----------------------------------------------------------------. +| Try to open file NAME with mode MODE, and print an error message | +| if fails. | +`-----------------------------------------------------------------*/ + +FILE * +xfopen (const char *name, const char *mode) +{ + FILE *ptr; + + ptr = fopen_safer (name, mode); + if (!ptr) + error (EXIT_FAILURE, get_errno (), + _("%s: cannot open"), quotearg_colon (name)); + + return ptr; +} + +/*-------------------------------------------------------------. +| Try to close file PTR, and print an error message if fails. | +`-------------------------------------------------------------*/ + +void +xfclose (FILE *ptr) +{ + if (ptr == NULL) + return; + + if (ferror (ptr)) + error (EXIT_FAILURE, 0, _("input/output error")); + + if (fclose (ptr) != 0) + error (EXIT_FAILURE, get_errno (), _("cannot close file")); +} + + +FILE * +xfdopen (int fd, char const *mode) +{ + FILE *res = fdopen (fd, mode); + if (! res) + error (EXIT_FAILURE, get_errno (), + /* On a separate line to please the "unmarked_diagnostics" + syntax-check. */ + "fdopen"); + return res; +} + +/*------------------------------------------------------------------. +| Compute ALL_BUT_EXT, ALL_BUT_TAB_EXT and output files extensions. | +`------------------------------------------------------------------*/ + +/* Compute extensions from the grammar file extension. */ +static void +compute_exts_from_gf (const char *ext) +{ + if (STREQ (ext, ".y")) + { + src_extension = xstrdup (language->src_extension); + /* header_extension = xstrdup (language->header_extension); */ + header_extension = xstrdup(".h"); + } + else + { + src_extension = xstrdup (ext); + /* + header_extension = xstrdup (ext); + tr (src_extension, 'y', 'c'); + tr (src_extension, 'Y', 'C'); + tr (header_extension, 'y', 'h'); + tr (header_extension, 'Y', 'H'); + */ + header_extension = xstrdup(".h"); + } +} + +/* Compute extensions from the given c source file extension. */ +static void +compute_exts_from_src (const char *ext) +{ + /* We use this function when the user specifies `-o' or `--output', + so the extenions must be computed unconditionally from the file name + given by this option. */ + src_extension = xstrdup (ext); + /* + header_extension = xstrdup (ext); + tr (header_extension, 'c', 'h'); + tr (header_extension, 'C', 'H'); + */ + header_extension = xstrdup(".h"); +} + + +/* Decompose FILE_NAME in four parts: *BASE, *TAB, and *EXT, the fourth + part, (the directory) is ranging from FILE_NAME to the char before + *BASE, so we don't need an additional parameter. + + *EXT points to the last period in the basename, or NULL if none. + + If there is no *EXT, *TAB is NULL. Otherwise, *TAB points to + '.tab' or '_tab' if present right before *EXT, or is NULL. *TAB + cannot be equal to *BASE. + + None are allocated, they are simply pointers to parts of FILE_NAME. + Examples: + + '/tmp/foo.tab.c' -> *BASE = 'foo.tab.c', *TAB = '.tab.c', *EXT = + '.c' + + 'foo.c' -> *BASE = 'foo.c', *TAB = NULL, *EXT = '.c' + + 'tab.c' -> *BASE = 'tab.c', *TAB = NULL, *EXT = '.c' + + '.tab.c' -> *BASE = '.tab.c', *TAB = NULL, *EXT = '.c' + + 'foo.tab' -> *BASE = 'foo.tab', *TAB = NULL, *EXT = '.tab' + + 'foo_tab' -> *BASE = 'foo_tab', *TAB = NULL, *EXT = NULL + + 'foo' -> *BASE = 'foo', *TAB = NULL, *EXT = NULL. */ + +static void +file_name_split (const char *file_name, + const char **base, const char **tab, const char **ext) +{ + *base = last_component (file_name); + + /* Look for the extension, i.e., look for the last dot. */ + *ext = strrchr (*base, '.'); + *tab = NULL; + + /* If there is an extension, check if there is a '.tab' part right + before. */ + if (*ext) + { + size_t baselen = *ext - *base; + size_t dottablen = sizeof (TAB_EXT) - 1; + if (dottablen < baselen + && STRPREFIX_LIT (TAB_EXT, *ext - dottablen)) + *tab = *ext - dottablen; + } +} + + +static void +compute_file_name_parts (void) +{ + const char *base, *tab, *ext; + + /* Compute ALL_BUT_EXT and ALL_BUT_TAB_EXT from SPEC_OUTFILE + or GRAMMAR_FILE. + + The precise -o name will be used for FTABLE. For other output + files, remove the ".c" or ".tab.c" suffix. */ + if (spec_outfile) + { + file_name_split (spec_outfile, &base, &tab, &ext); + dir_prefix = xstrndup (spec_outfile, base - spec_outfile); + + /* ALL_BUT_EXT goes up the EXT, excluding it. */ + all_but_ext = + xstrndup (spec_outfile, + (strlen (spec_outfile) - (ext ? strlen (ext) : 0))); + + /* ALL_BUT_TAB_EXT goes up to TAB, excluding it. */ + all_but_tab_ext = + xstrndup (spec_outfile, + (strlen (spec_outfile) + - (tab ? strlen (tab) : (ext ? strlen (ext) : 0)))); + + if (ext) + compute_exts_from_src (ext); + } + else + { + file_name_split (grammar_file, &base, &tab, &ext); + + if (spec_file_prefix) + { + /* If --file-prefix=foo was specified, ALL_BUT_TAB_EXT = 'foo'. */ + dir_prefix = + xstrndup (spec_file_prefix, + last_component (spec_file_prefix) - spec_file_prefix); + all_but_tab_ext = xstrdup (spec_file_prefix); + } + else if (yacc_flag) + { + /* If --yacc, then the output is 'y.tab.c'. */ + dir_prefix = xstrdup (""); + all_but_tab_ext = xstrdup ("y"); + } + else + { + /* Otherwise, ALL_BUT_TAB_EXT is computed from the input + grammar: 'foo/bar.yy' => 'bar'. */ + dir_prefix = xstrdup (""); + all_but_tab_ext = + xstrndup (base, (strlen (base) - (ext ? strlen (ext) : 0))); + } + + if (language->add_tab) + all_but_ext = concat2 (all_but_tab_ext, TAB_EXT); + else + all_but_ext = xstrdup (all_but_tab_ext); + + /* Compute the extensions from the grammar file name. */ + if (ext && !yacc_flag) + compute_exts_from_gf (ext); + } +} + + +/* Compute the output file names. Warn if we detect conflicting + outputs to the same file. */ + +void +compute_output_file_names (void) +{ + compute_file_name_parts (); + + /* If not yet done. */ + if (!src_extension) + src_extension = xstrdup (".c"); + if (!header_extension) + header_extension = xstrdup (".h"); + + parser_file_name = + (spec_outfile + ? xstrdup (spec_outfile) + : concat2 (all_but_ext, src_extension)); + + if (defines_flag) + { + if (! spec_defines_file) + spec_defines_file = concat2 (all_but_ext, header_extension); + } + + if (graph_flag) + { + if (! spec_graph_file) + spec_graph_file = concat2 (all_but_tab_ext, ".dot"); + output_file_name_check (&spec_graph_file); + } + + if (xml_flag) + { + if (! spec_xml_file) + spec_xml_file = concat2 (all_but_tab_ext, ".xml"); + output_file_name_check (&spec_xml_file); + } + + if (report_flag) + { + if (!spec_verbose_file) + spec_verbose_file = concat2 (all_but_tab_ext, OUTPUT_EXT); + output_file_name_check (&spec_verbose_file); + } + + free (all_but_tab_ext); + free (src_extension); + free (header_extension); +} + +void +output_file_name_check (char **file_name) +{ + bool conflict = false; + if (STREQ (*file_name, grammar_file)) + { + complain (NULL, complaint, _("refusing to overwrite the input file %s"), + quote (*file_name)); + conflict = true; + } + else + { + int i; + for (i = 0; i < file_names_count; i++) + if (STREQ (file_names[i], *file_name)) + { + complain (NULL, Wother, _("conflicting outputs to file %s"), + quote (*file_name)); + conflict = true; + } + } + if (conflict) + { + free (*file_name); + *file_name = strdup ("/dev/null"); + } + else + { + file_names = xnrealloc (file_names, ++file_names_count, + sizeof *file_names); + file_names[file_names_count-1] = xstrdup (*file_name); + } +} + +void +output_file_names_free (void) +{ + free (all_but_ext); + free (spec_verbose_file); + free (spec_graph_file); + free (spec_xml_file); + free (spec_defines_file); + free (parser_file_name); + free (dir_prefix); + { + int i; + for (i = 0; i < file_names_count; i++) + free (file_names[i]); + } + free (file_names); +} diff --git a/contrib/tools/bison/src/files.h b/contrib/tools/bison/src/files.h new file mode 100644 index 0000000000..ebe5037c7a --- /dev/null +++ b/contrib/tools/bison/src/files.h @@ -0,0 +1,72 @@ +/* File names and variables for bison, + + Copyright (C) 1984, 1989, 2000-2002, 2006-2007, 2009-2013 Free + Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef FILES_H_ +# define FILES_H_ + +# include "uniqstr.h" + +/* File name specified with -o for the output file, or 0 if no -o. */ +extern char const *spec_outfile; + +/* File name for the parser (i.e., the one above, or its default.) */ +extern char *parser_file_name; + +/* Symbol prefix specified with -p, or 0 if no -p. */ +extern const char *spec_name_prefix; + +/* File name prefix specified with -b, or 0 if no -b. */ +extern char const *spec_file_prefix; + +/* --verbose. */ +extern char *spec_verbose_file; + +/* File name specified for the output graph. */ +extern char *spec_graph_file; + +/* File name specified for the xml output. */ +extern char *spec_xml_file; + +/* File name specified with --defines. */ +extern char *spec_defines_file; + +/* Directory prefix of output file names. */ +extern char *dir_prefix; + +/* The file name as given on the command line. + Not named "input_file" because Flex uses this name for an argument, + and therefore GCC warns about a name clash. */ +extern uniqstr grammar_file; + +/* The current file name. Might change with %include, or with #line. */ +extern uniqstr current_file; + +/* The computed base for output file names. */ +extern char *all_but_ext; + +void compute_output_file_names (void); +void output_file_names_free (void); +void output_file_name_check (char **file_name); + +FILE *xfopen (const char *name, char const *mode); +void xfclose (FILE *ptr); +FILE *xfdopen (int fd, char const *mode); + +#endif /* !FILES_H_ */ diff --git a/contrib/tools/bison/src/flex-scanner.h b/contrib/tools/bison/src/flex-scanner.h new file mode 100644 index 0000000000..03c9ec64fd --- /dev/null +++ b/contrib/tools/bison/src/flex-scanner.h @@ -0,0 +1,90 @@ +/* Common parts between scan-code.l, scan-gram.l, and scan-skel.l. + + Copyright (C) 2006, 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef FLEX_PREFIX +# error "FLEX_PREFIX not defined" +#endif + +#include <obstack.h> + +/* Flex full version as a number. */ +#define FLEX_VERSION \ + ((YY_FLEX_MAJOR_VERSION) * 1000000 \ + + (YY_FLEX_MINOR_VERSION) * 1000 \ + + (YY_FLEX_SUBMINOR_VERSION)) + +/* Pacify "gcc -Wmissing-prototypes" when flex 2.5.31 is used. */ +#if FLEX_VERSION <= 2005031 +int FLEX_PREFIX (get_lineno) (void); +FILE *FLEX_PREFIX (get_in) (void); +FILE *FLEX_PREFIX (get_out) (void); +int FLEX_PREFIX (get_leng) (void); +char *FLEX_PREFIX (get_text) (void); +void FLEX_PREFIX (set_lineno) (int); +void FLEX_PREFIX (set_in) (FILE *); +void FLEX_PREFIX (set_out) (FILE *); +int FLEX_PREFIX (get_debug) (void); +void FLEX_PREFIX (set_debug) (int); +int FLEX_PREFIX (lex_destroy) (void); +#endif + +#define last_string FLEX_PREFIX (last_string) + +/* It seems to be a nice "feature" of Flex that one cannot use yytext, + yyleng etc. when a prefix is given, since there is no longer a + #define, but rather the token is actually changed in the output. + However, this is not true for Flex 2.5.4. */ +#ifndef yyleng +# define yyleng FLEX_PREFIX (leng) +#endif +#ifndef yytext +# define yytext FLEX_PREFIX (text) +#endif + +/* Non-reentrant scanners generated by Flex 2.5.9 and later (and some earlier + versions according to the Flex manual) leak memory if yylex_destroy is not + invoked. However, yylex_destroy is not defined before Flex 2.5.9, so give + an implementation here that at least appears to work with Flex 2.5.4. */ +#if FLEX_VERSION <= 2005009 +# define yylex_destroy() yy_delete_buffer (YY_CURRENT_BUFFER) +#endif + +/* OBSTACK_FOR_STRING -- Used to store all the characters that we need to + keep (to construct ID, STRINGS etc.). Use the following macros to + use it. + + Use STRING_GROW to append what has just been matched, and + STRING_FINISH to end the string (it puts the ending 0). + STRING_FINISH also stores this string in LAST_STRING, which can be + used, and which is used by STRING_FREE to free the last string. */ + +#ifndef FLEX_NO_OBSTACK + +static struct obstack obstack_for_string; + +# define STRING_GROW \ + obstack_grow (&obstack_for_string, yytext, yyleng) + +# define STRING_FINISH \ + (last_string = obstack_finish0 (&obstack_for_string)) + +# define STRING_FREE \ + obstack_free (&obstack_for_string, last_string) + +#endif diff --git a/contrib/tools/bison/src/getargs.c b/contrib/tools/bison/src/getargs.c new file mode 100644 index 0000000000..d63bc7f9f5 --- /dev/null +++ b/contrib/tools/bison/src/getargs.c @@ -0,0 +1,741 @@ +/* Parse command line arguments for Bison. + + Copyright (C) 1984, 1986, 1989, 1992, 2000-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" +#include "output.h" + +#include <argmatch.h> +#include <c-strcase.h> +#include <configmake.h> +#include <error.h> +#include <getopt.h> +#include <progname.h> + +#include "complain.h" +#include "files.h" +#include "getargs.h" +#include "muscle-tab.h" +#include "quote.h" +#include "uniqstr.h" + +bool defines_flag; +bool graph_flag; +bool xml_flag; +bool no_lines_flag; +bool token_table_flag; +bool yacc_flag; /* for -y */ + +bool nondeterministic_parser = false; +bool glr_parser = false; + +int feature_flag = feature_caret; +int report_flag = report_none; +int trace_flag = trace_none; + +static struct bison_language const valid_languages[] = { + { "c", "c-skel.m4", ".c", ".h", true }, + { "c++", "c++-skel.m4", ".cc", ".hh", true }, + { "java", "java-skel.m4", ".java", ".java", false }, + { "", "", "", "", false } +}; + +int skeleton_prio = default_prio; +const char *skeleton = NULL; +int language_prio = default_prio; +struct bison_language const *language = &valid_languages[0]; + +const char* m4_path = NULL; + +/** Decode an option's key. + * + * \param option option being decoded. + * \param keys array of valid subarguments. + * \param values array of corresponding (int) values. + * \param all the all value. + * \param flags the flags to update + * \param arg the subarguments to decode. + * If null, then activate all the flags. + * \param no length of the potential "no-" prefix. + * Can be 0 or 3. If 3, negate the action of the subargument. + * + * If VALUE != 0 then KEY sets flags and no-KEY clears them. + * If VALUE == 0 then KEY clears all flags from \c all and no-KEY sets all + * flags from \c all. Thus no-none = all and no-all = none. + */ +static void +flag_argmatch (const char *option, + const char * const keys[], const int values[], + int all, int *flags, char *arg, size_t no) +{ + int value = XARGMATCH (option, arg + no, keys, values); + + /* -rnone == -rno-all, and -rno-none == -rall. */ + if (!value) + { + value = all; + no = !no; + } + + if (no) + *flags &= ~value; + else + *flags |= value; +} + +/** Decode an option's set of keys. + * + * \param option option being decoded. + * \param keys array of valid subarguments. + * \param values array of corresponding (int) values. + * \param all the all value. + * \param flags the flags to update + * \param args comma separated list of effective subarguments to decode. + * If 0, then activate all the flags. + */ +static void +flags_argmatch (const char *option, + const char * const keys[], const int values[], + int all, int *flags, char *args) +{ + if (args) + for (args = strtok (args, ","); args; args = strtok (NULL, ",")) + { + size_t no = STRPREFIX_LIT ("no-", args) ? 3 : 0; + flag_argmatch (option, keys, + values, all, flags, args, no); + } + else + *flags |= all; +} + + +/** Decode a set of sub arguments. + * + * \param FlagName the flag familly to update. + * \param Args the effective sub arguments to decode. + * \param All the "all" value. + * + * \arg FlagName_args the list of keys. + * \arg FlagName_types the list of values. + * \arg FlagName_flag the flag to update. + */ +#define FLAGS_ARGMATCH(FlagName, Args, All) \ + flags_argmatch ("--" #FlagName, FlagName ## _args, FlagName ## _types, \ + All, &FlagName ## _flag, Args) + + +/*----------------------. +| --report's handling. | +`----------------------*/ + +static const char * const report_args[] = +{ + /* In a series of synonyms, present the most meaningful first, so + that argmatch_valid be more readable. */ + "none", + "state", "states", + "itemset", "itemsets", + "lookahead", "lookaheads", "look-ahead", + "solved", + "all", + 0 +}; + +static const int report_types[] = +{ + report_none, + report_states, report_states, + report_states | report_itemsets, report_states | report_itemsets, + report_states | report_lookahead_tokens, + report_states | report_lookahead_tokens, + report_states | report_lookahead_tokens, + report_states | report_solved_conflicts, + report_all +}; + +ARGMATCH_VERIFY (report_args, report_types); + + +/*---------------------. +| --trace's handling. | +`---------------------*/ + +static const char * const trace_args[] = +{ + "none - no traces", + "scan - grammar scanner traces", + "parse - grammar parser traces", + "automaton - construction of the automaton", + "bitsets - use of bitsets", + "grammar - reading, reducing the grammar", + "resource - memory consumption (where available)", + "sets - grammar sets: firsts, nullable etc.", + "muscles - m4 definitions passed to the skeleton", + "tools - m4 invocation", + "m4 - m4 traces", + "skeleton - skeleton postprocessing", + "time - time consumption", + "ielr - IELR conversion", + "all - all of the above", + 0 +}; + +static const int trace_types[] = +{ + trace_none, + trace_scan, + trace_parse, + trace_automaton, + trace_bitsets, + trace_grammar, + trace_resource, + trace_sets, + trace_muscles, + trace_tools, + trace_m4, + trace_skeleton, + trace_time, + trace_ielr, + trace_all +}; + +ARGMATCH_VERIFY (trace_args, trace_types); + + +/*-----------------------. +| --feature's handling. | +`-----------------------*/ + +static const char * const feature_args[] = +{ + "none", + "caret", "diagnostics-show-caret", + "all", + 0 +}; + +static const int feature_types[] = +{ + feature_none, + feature_caret, feature_caret, + feature_all +}; + +ARGMATCH_VERIFY (feature_args, feature_types); + +/*-------------------------------------------. +| Display the help message and exit STATUS. | +`-------------------------------------------*/ + +static void usage (int) ATTRIBUTE_NORETURN; + +static void +usage (int status) +{ + if (status != 0) + fprintf (stderr, _("Try '%s --help' for more information.\n"), + program_name); + else + { + /* For ../build-aux/cross-options.pl to work, use the format: + ^ -S, --long[=ARGS] (whitespace) + A --long option is required. + Otherwise, add exceptions to ../build-aux/cross-options.pl. */ + + printf (_("Usage: %s [OPTION]... FILE\n"), program_name); + fputs (_("\ +Generate a deterministic LR or generalized LR (GLR) parser employing\n\ +LALR(1), IELR(1), or canonical LR(1) parser tables. IELR(1) and\n\ +canonical LR(1) support is experimental.\n\ +\n\ +"), stdout); + + fputs (_("\ +Mandatory arguments to long options are mandatory for short options too.\n\ +"), stdout); + fputs (_("\ +The same is true for optional arguments.\n\ +"), stdout); + + fputs (_("\ +\n\ +Operation modes:\n\ + -h, --help display this help and exit\n\ + -V, --version output version information and exit\n\ + --print-localedir output directory containing locale-dependent data\n\ + --print-datadir output directory containing skeletons and XSLT\n\ + -y, --yacc emulate POSIX Yacc\n\ + -W, --warnings[=CATEGORY] report the warnings falling in CATEGORY\n\ + -f, --feature[=FEATURE] activate miscellaneous features\n\ +\n\ +"), stdout); + + fputs (_("\ +Parser:\n\ + -L, --language=LANGUAGE specify the output programming language\n\ + -S, --skeleton=FILE specify the skeleton to use\n\ + -t, --debug instrument the parser for tracing\n\ + same as '-Dparse.trace'\n\ + --locations enable location support\n\ + -D, --define=NAME[=VALUE] similar to '%define NAME \"VALUE\"'\n\ + -F, --force-define=NAME[=VALUE] override '%define NAME \"VALUE\"'\n\ + -p, --name-prefix=PREFIX prepend PREFIX to the external symbols\n\ + deprecated by '-Dapi.prefix=PREFIX'\n\ + -l, --no-lines don't generate '#line' directives\n\ + -k, --token-table include a table of token names\n\ +"), stdout); + putc ('\n', stdout); + + /* Keep -d and --defines separate so that ../build-aux/cross-options.pl + * won't assume that -d also takes an argument. */ + fputs (_("\ +Output:\n\ + --defines[=FILE] also produce a header file\n\ + -d likewise but cannot specify FILE (for POSIX Yacc)\n\ + -r, --report=THINGS also produce details on the automaton\n\ + --report-file=FILE write report to FILE\n\ + -v, --verbose same as '--report=state'\n\ + -b, --file-prefix=PREFIX specify a PREFIX for output files\n\ + -o, --output=FILE leave output to FILE\n\ + -g, --graph[=FILE] also output a graph of the automaton\n\ + -x, --xml[=FILE] also output an XML report of the automaton\n\ + (the XML schema is experimental)\n\ +"), stdout); + putc ('\n', stdout); + + fputs (_("\ +Warning categories include:\n\ + 'midrule-values' unset or unused midrule values\n\ + 'yacc' incompatibilities with POSIX Yacc\n\ + 'conflicts-sr' S/R conflicts (enabled by default)\n\ + 'conflicts-rr' R/R conflicts (enabled by default)\n\ + 'deprecated' obsolete constructs\n\ + 'empty-rule' empty rules without %empty\n\ + 'precedence' useless precedence and associativity\n\ + 'other' all other warnings (enabled by default)\n\ + 'all' all the warnings except 'yacc'\n\ + 'no-CATEGORY' turn off warnings in CATEGORY\n\ + 'none' turn off all the warnings\n\ + 'error[=CATEGORY]' treat warnings as errors\n\ +"), stdout); + putc ('\n', stdout); + + fputs (_("\ +THINGS is a list of comma separated words that can include:\n\ + 'state' describe the states\n\ + 'itemset' complete the core item sets with their closure\n\ + 'lookahead' explicitly associate lookahead tokens to items\n\ + 'solved' describe shift/reduce conflicts solving\n\ + 'all' include all the above information\n\ + 'none' disable the report\n\ +"), stdout); + putc ('\n', stdout); + + fputs (_("\ +FEATURE is a list of comma separated words that can include:\n\ + 'caret' show errors with carets\n\ + 'all' all of the above\n\ + 'none' disable all of the above\n\ + "), stdout); + + putc ('\n', stdout); + printf (_("Report bugs to <%s>.\n"), PACKAGE_BUGREPORT); + printf (_("%s home page: <%s>.\n"), PACKAGE_NAME, PACKAGE_URL); + fputs (_("General help using GNU software: " + "<http://www.gnu.org/gethelp/>.\n"), + stdout); + /* Don't output this redundant message for English locales. + Note we still output for 'C' so that it gets included in the + man page. */ + fputs (_("For complete documentation, run: info bison.\n"), stdout); + } + + exit (status); +} + + +/*------------------------------. +| Display the version message. | +`------------------------------*/ + +static void +version (void) +{ + /* Some efforts were made to ease the translators' task, please + continue. */ + printf (_("bison (GNU Bison) %s"), VERSION); + putc ('\n', stdout); + fputs (_("Written by Robert Corbett and Richard Stallman.\n"), stdout); + putc ('\n', stdout); + + fprintf (stdout, + _("Copyright (C) %d Free Software Foundation, Inc.\n"), + 2013); + + fputs (_("\ +This is free software; see the source for copying conditions. There is NO\n\ +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ +"), + stdout); +} + + +/*-------------------------------------. +| --skeleton and --language handling. | +`--------------------------------------*/ + +void +skeleton_arg (char const *arg, int prio, location loc) +{ + if (prio < skeleton_prio) + { + skeleton_prio = prio; + skeleton = arg; + } + else if (prio == skeleton_prio) + complain (&loc, complaint, + _("multiple skeleton declarations are invalid")); +} + +void +language_argmatch (char const *arg, int prio, location loc) +{ + char const *msg; + + if (prio < language_prio) + { + int i; + for (i = 0; valid_languages[i].language[0]; i++) + if (c_strcasecmp (arg, valid_languages[i].language) == 0) + { + language_prio = prio; + language = &valid_languages[i]; + return; + } + msg = _("%s: invalid language"); + } + else if (language_prio == prio) + msg = _("multiple language declarations are invalid"); + else + return; + + complain (&loc, complaint, msg, quotearg_colon (arg)); +} + +/*----------------------. +| Process the options. | +`----------------------*/ + +/* Shorts options. + Should be computed from long_options. */ +static char const short_options[] = + "D:" + "F:" + "L:" + "S:" + "T::" + "V" + "W::" + "b:" + "d" + "f::" + "g::" + "h" + "k" + "l" + "o:" + "p:" + "r:" + "t" + "v" + "x::" + "y" + ; + +/* Values for long options that do not have single-letter equivalents. */ +enum +{ + LOCATIONS_OPTION = CHAR_MAX + 1, + PRINT_LOCALEDIR_OPTION, + PRINT_DATADIR_OPTION, + REPORT_FILE_OPTION, + M4_PATH +}; + +static struct option const long_options[] = +{ + /* Operation modes. */ + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'V' }, + { "print-localedir", no_argument, 0, PRINT_LOCALEDIR_OPTION }, + { "print-datadir", no_argument, 0, PRINT_DATADIR_OPTION }, + { "warnings", optional_argument, 0, 'W' }, + + /* Parser. */ + { "name-prefix", required_argument, 0, 'p' }, + + /* Output. */ + { "file-prefix", required_argument, 0, 'b' }, + { "output", required_argument, 0, 'o' }, + { "output-file", required_argument, 0, 'o' }, + { "graph", optional_argument, 0, 'g' }, + { "xml", optional_argument, 0, 'x' }, + { "report", required_argument, 0, 'r' }, + { "report-file", required_argument, 0, REPORT_FILE_OPTION }, + { "verbose", no_argument, 0, 'v' }, + + /* Hidden. */ + { "trace", optional_argument, 0, 'T' }, + { "m4", required_argument, 0, M4_PATH }, + + /* Output. */ + { "defines", optional_argument, 0, 'd' }, + { "feature", optional_argument, 0, 'f' }, + + /* Operation modes. */ + { "fixed-output-files", no_argument, 0, 'y' }, + { "yacc", no_argument, 0, 'y' }, + + /* Parser. */ + { "debug", no_argument, 0, 't' }, + { "define", required_argument, 0, 'D' }, + { "force-define", required_argument, 0, 'F' }, + { "locations", no_argument, 0, LOCATIONS_OPTION }, + { "no-lines", no_argument, 0, 'l' }, + { "skeleton", required_argument, 0, 'S' }, + { "language", required_argument, 0, 'L' }, + { "token-table", no_argument, 0, 'k' }, + + {0, 0, 0, 0} +}; + +/* Under DOS, there is no difference on the case. This can be + troublesome when looking for '.tab' etc. */ +#ifdef MSDOS +# define AS_FILE_NAME(File) (strlwr (File), (File)) +#else +# define AS_FILE_NAME(File) (File) +#endif + +/* Build a location for the current command line argument. */ +static +location +command_line_location (void) +{ + location res; + /* "<command line>" is used in GCC's messages about -D. */ + boundary_set (&res.start, uniqstr_new ("<command line>"), optind - 1, -1); + res.end = res.start; + return res; +} + + +void +getargs (int argc, char *argv[]) +{ + int c; + + while ((c = getopt_long (argc, argv, short_options, long_options, NULL)) + != -1) + switch (c) + { + /* ASCII Sorting for short options (i.e., upper case then + lower case), and then long-only options. */ + + case 0: + /* Certain long options cause getopt_long to return 0. */ + break; + + case 'D': /* -DNAME[=(VALUE|"VALUE"|{VALUE})]. */ + case 'F': /* -FNAME[=(VALUE|"VALUE"|{VALUE})]. */ + { + char *name = optarg; + char *value = strchr (optarg, '='); + muscle_kind kind = muscle_keyword; + if (value) + { + char *end = value + strlen (value) - 1; + *value++ = 0; + if (*value == '{' && *end == '}') + { + kind = muscle_code; + ++value; + *end = 0; + } + else if (*value == '"' && *end == '"') + { + kind = muscle_string; + ++value; + *end = 0; + } + } + muscle_percent_define_insert (name, command_line_location (), + kind, value ? value : "", + c == 'D' ? MUSCLE_PERCENT_DEFINE_D + : MUSCLE_PERCENT_DEFINE_F); + } + break; + + case 'L': + language_argmatch (optarg, command_line_prio, + command_line_location ()); + break; + + case 'S': + skeleton_arg (AS_FILE_NAME (optarg), command_line_prio, + command_line_location ()); + break; + + case 'T': + FLAGS_ARGMATCH (trace, optarg, trace_all); + break; + + case 'V': + version (); + exit (EXIT_SUCCESS); + + case 'f': + FLAGS_ARGMATCH (feature, optarg, feature_all); + break; + + case 'W': + warnings_argmatch (optarg); + break; + + case 'b': + spec_file_prefix = AS_FILE_NAME (optarg); + break; + + case 'd': + /* Here, the -d and --defines options are differentiated. */ + defines_flag = true; + if (optarg) + { + free (spec_defines_file); + spec_defines_file = xstrdup (AS_FILE_NAME (optarg)); + } + break; + + case 'g': + graph_flag = true; + if (optarg) + { + free (spec_graph_file); + spec_graph_file = xstrdup (AS_FILE_NAME (optarg)); + } + break; + + case 'h': + usage (EXIT_SUCCESS); + + case 'k': + token_table_flag = true; + break; + + case 'l': + no_lines_flag = true; + break; + + case 'o': + spec_outfile = AS_FILE_NAME (optarg); + break; + + case 'p': + spec_name_prefix = optarg; + break; + + case 'r': + FLAGS_ARGMATCH (report, optarg, report_all); + break; + + case 't': + muscle_percent_define_insert ("parse.trace", + command_line_location (), + muscle_keyword, "", + MUSCLE_PERCENT_DEFINE_D); + break; + + case 'v': + report_flag |= report_states; + break; + + case 'x': + xml_flag = true; + if (optarg) + { + free (spec_xml_file); + spec_xml_file = xstrdup (AS_FILE_NAME (optarg)); + } + break; + + case 'y': + warning_argmatch ("error=yacc", 0, 6); + yacc_flag = true; + break; + + case LOCATIONS_OPTION: + muscle_percent_define_ensure ("locations", + command_line_location (), true); + break; + +#if 0 + case PRINT_LOCALEDIR_OPTION: + printf ("%s\n", LOCALEDIR); + exit (EXIT_SUCCESS); +#endif + + case PRINT_DATADIR_OPTION: + printf ("%s\n", pkgdatadir ()); + exit (EXIT_SUCCESS); + + case REPORT_FILE_OPTION: + free (spec_verbose_file); + spec_verbose_file = xstrdup (AS_FILE_NAME (optarg)); + break; + + case M4_PATH: + m4_path = xstrdup (AS_FILE_NAME (optarg)); + break; + + default: + usage (EXIT_FAILURE); + } + + if (argc - optind != 1) + { + if (argc - optind < 1) + error (0, 0, _("%s: missing operand"), quotearg_colon (argv[argc - 1])); + else + error (0, 0, _("extra operand %s"), quote (argv[optind + 1])); + usage (EXIT_FAILURE); + } + + current_file = grammar_file = uniqstr_new (argv[optind]); + MUSCLE_INSERT_C_STRING ("file_name", grammar_file); +} + +void +tr (char *s, char from, char to) +{ + for (; *s; s++) + if (*s == from) + *s = to; +} diff --git a/contrib/tools/bison/src/getargs.h b/contrib/tools/bison/src/getargs.h new file mode 100644 index 0000000000..178fb94377 --- /dev/null +++ b/contrib/tools/bison/src/getargs.h @@ -0,0 +1,141 @@ +/* Parse command line arguments for bison. + + Copyright (C) 1984, 1986, 1989, 1992, 2000-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef GETARGS_H_ +# define GETARGS_H_ + +# include "location.h" + +enum { command_line_prio, grammar_prio, default_prio }; + +/* flags set by % directives */ + +/* for -S */ +extern char const *skeleton; +extern int skeleton_prio; + +/* for -I */ +extern char const *include; + +extern bool defines_flag; /* for -d */ +extern bool graph_flag; /* for -g */ +extern bool xml_flag; /* for -x */ +extern bool no_lines_flag; /* for -l */ +extern bool token_table_flag; /* for -k */ +extern bool yacc_flag; /* for -y */ + +extern const char *m4_path; + + +/* GLR_PARSER is true if the input file says to use the GLR + (Generalized LR) parser, and to output some additional information + used by the GLR algorithm. */ + +extern bool glr_parser; + +/* NONDETERMINISTIC_PARSER is true iff conflicts are accepted. This + is used by the GLR parser, and might be used in BackTracking + parsers too. */ + +extern bool nondeterministic_parser; + + +/* --language. */ +struct bison_language +{ + char language[sizeof "Java"]; + char skeleton[sizeof "java-skel.m4"]; + char src_extension[sizeof ".java"]; + char header_extension[sizeof ".java"]; + bool add_tab; +}; + +extern int language_prio; +extern struct bison_language const *language; + +/*-----------. +| --report. | +`-----------*/ + +enum report + { + report_none = 0, + report_states = 1 << 0, + report_itemsets = 1 << 1, + report_lookahead_tokens = 1 << 2, + report_solved_conflicts = 1 << 3, + report_all = ~0 + }; +/** What appears in the *.output file. */ +extern int report_flag; + +/*----------. +| --trace. | +`----------*/ +enum trace + { + trace_none = 0, /**< No traces. */ + trace_scan = 1 << 0, /**< Grammar scanner traces. */ + trace_parse = 1 << 1, /**< Grammar parser traces. */ + trace_resource = 1 << 2, /**< Memory allocation. */ + trace_sets = 1 << 3, /**< Grammar sets: firsts, nullable etc. */ + trace_bitsets = 1 << 4, /**< Use of bitsets. */ + trace_tools = 1 << 5, /**< m4 invocation. */ + trace_automaton = 1 << 6, /**< Construction of the automaton. */ + trace_grammar = 1 << 7, /**< Reading, reducing the grammar. */ + trace_time = 1 << 8, /**< Time consumption. */ + trace_skeleton = 1 << 9, /**< Skeleton postprocessing. */ + trace_m4 = 1 << 10, /**< M4 traces. */ + trace_muscles = 1 << 11, /**< M4 definitions of the muscles. */ + trace_ielr = 1 << 12, /**< IELR conversion. */ + trace_all = ~0 /**< All of the above. */ + }; +/** What debug items bison displays during its run. */ +extern int trace_flag; + +/*-------------. +| --features. | +`-------------*/ + +enum feature + { + feature_none = 0, /**< No additional feature. */ + feature_caret = 1 << 0, /**< Enhance the output of errors with carets. */ + feature_all = ~0 /**< All above features. */ + }; +/** What additional features to use. */ +extern int feature_flag; + + +/** Process the command line arguments. + * + * \param argc size of \a argv + * \param argv list of arguments. + */ +void getargs (int argc, char *argv[]); + +/* Used by parse-gram.y. */ +void language_argmatch (char const *arg, int prio, location loc); +void skeleton_arg (const char *arg, int prio, location loc); + +/** In the string \c s, replace all characters \c from by \c to. */ +void tr (char *s, char from, char to); + +#endif /* !GETARGS_H_ */ diff --git a/contrib/tools/bison/src/gram.c b/contrib/tools/bison/src/gram.c new file mode 100644 index 0000000000..f6cc3c5d87 --- /dev/null +++ b/contrib/tools/bison/src/gram.c @@ -0,0 +1,310 @@ +/* Allocate input grammar variables for Bison. + + Copyright (C) 1984, 1986, 1989, 2001-2003, 2005-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include "complain.h" +#include "getargs.h" +#include "gram.h" +#include "print-xml.h" +#include "reader.h" +#include "reduce.h" +#include "symtab.h" + +/* Comments for these variables are in gram.h. */ + +item_number *ritem = NULL; +unsigned int nritems = 0; + +rule *rules = NULL; +rule_number nrules = 0; + +symbol **symbols = NULL; +int nsyms = 0; +int ntokens = 1; +int nvars = 0; + +symbol_number *token_translations = NULL; + +int max_user_token_number = 256; + +bool +rule_useful_in_grammar_p (rule const *r) +{ + return r->number < nrules; +} + +bool +rule_useless_in_grammar_p (rule const *r) +{ + return !rule_useful_in_grammar_p (r); +} + +bool +rule_useless_in_parser_p (rule const *r) +{ + return !r->useful && rule_useful_in_grammar_p (r); +} + +void +rule_lhs_print (rule const *r, symbol const *previous_lhs, FILE *out) +{ + fprintf (out, " %3d ", r->number); + if (previous_lhs != r->lhs) + fprintf (out, "%s:", r->lhs->tag); + else + fprintf (out, "%*s|", (int) strlen (previous_lhs->tag), ""); +} + +void +rule_lhs_print_xml (rule const *r, FILE *out, int level) +{ + xml_printf (out, level, "<lhs>%s</lhs>", r->lhs->tag); +} + +size_t +rule_rhs_length (rule const *r) +{ + size_t res = 0; + item_number *rhsp; + for (rhsp = r->rhs; *rhsp >= 0; ++rhsp) + ++res; + return res; +} + +void +rule_rhs_print (rule const *r, FILE *out) +{ + if (0 <= *r->rhs) + { + item_number *rp; + for (rp = r->rhs; *rp >= 0; rp++) + fprintf (out, " %s", symbols[*rp]->tag); + } + else + fputs (" %empty", out); +} + +static void +rule_rhs_print_xml (rule const *r, FILE *out, int level) +{ + if (*r->rhs >= 0) + { + item_number *rp; + xml_puts (out, level, "<rhs>"); + for (rp = r->rhs; *rp >= 0; rp++) + xml_printf (out, level + 1, "<symbol>%s</symbol>", + xml_escape (symbols[*rp]->tag)); + xml_puts (out, level, "</rhs>"); + } + else + { + xml_puts (out, level, "<rhs>"); + xml_puts (out, level + 1, "<empty/>"); + xml_puts (out, level, "</rhs>"); + } +} + +void +ritem_print (FILE *out) +{ + unsigned int i; + fputs ("RITEM\n", out); + for (i = 0; i < nritems; ++i) + if (ritem[i] >= 0) + fprintf (out, " %s", symbols[ritem[i]]->tag); + else + fprintf (out, " (rule %d)\n", item_number_as_rule_number (ritem[i])); + fputs ("\n\n", out); +} + +size_t +ritem_longest_rhs (void) +{ + int max = 0; + rule_number r; + + for (r = 0; r < nrules; ++r) + { + int length = rule_rhs_length (&rules[r]); + if (length > max) + max = length; + } + + return max; +} + +void +grammar_rules_partial_print (FILE *out, const char *title, + rule_filter filter) +{ + rule_number r; + bool first = true; + symbol *previous_lhs = NULL; + + /* rule # : LHS -> RHS */ + for (r = 0; r < nrules + nuseless_productions; r++) + { + if (filter && !filter (&rules[r])) + continue; + if (first) + fprintf (out, "%s\n\n", title); + else if (previous_lhs && previous_lhs != rules[r].lhs) + fputc ('\n', out); + first = false; + rule_lhs_print (&rules[r], previous_lhs, out); + rule_rhs_print (&rules[r], out); + fprintf (out, "\n"); + previous_lhs = rules[r].lhs; + } + if (!first) + fputs ("\n\n", out); +} + +void +grammar_rules_print (FILE *out) +{ + grammar_rules_partial_print (out, _("Grammar"), rule_useful_in_grammar_p); +} + +void +grammar_rules_print_xml (FILE *out, int level) +{ + rule_number r; + bool first = true; + + for (r = 0; r < nrules + nuseless_productions; r++) + { + if (first) + xml_puts (out, level + 1, "<rules>"); + first = false; + { + char const *usefulness; + if (rule_useless_in_grammar_p (&rules[r])) + usefulness = "useless-in-grammar"; + else if (rule_useless_in_parser_p (&rules[r])) + usefulness = "useless-in-parser"; + else + usefulness = "useful"; + xml_indent (out, level + 2); + fprintf (out, "<rule number=\"%d\" usefulness=\"%s\"", + rules[r].number, usefulness); + if (rules[r].precsym) + fprintf (out, " percent_prec=\"%s\"", + xml_escape (rules[r].precsym->tag)); + fputs (">\n", out); + } + rule_lhs_print_xml (&rules[r], out, level + 3); + rule_rhs_print_xml (&rules[r], out, level + 3); + xml_puts (out, level + 2, "</rule>"); + } + if (!first) + xml_puts (out, level + 1, "</rules>"); + else + xml_puts (out, level + 1, "<rules/>"); +} + +void +grammar_dump (FILE *out, const char *title) +{ + fprintf (out, "%s\n\n", title); + fprintf (out, + "ntokens = %d, nvars = %d, nsyms = %d, nrules = %d, nritems = %d\n\n", + ntokens, nvars, nsyms, nrules, nritems); + + + fprintf (out, "Variables\n---------\n\n"); + { + symbol_number i; + fprintf (out, "Value Sprec Sassoc Tag\n"); + + for (i = ntokens; i < nsyms; i++) + fprintf (out, "%5d %5d %5d %s\n", + i, + symbols[i]->prec, symbols[i]->assoc, + symbols[i]->tag); + fprintf (out, "\n\n"); + } + + fprintf (out, "Rules\n-----\n\n"); + { + rule_number i; + fprintf (out, + "Num (Prec, Assoc, Useful, Ritem Range) Lhs" + " -> Rhs (Ritem range) [Num]\n"); + for (i = 0; i < nrules + nuseless_productions; i++) + { + rule const *rule_i = &rules[i]; + item_number *rp = NULL; + unsigned int rhs_itemno = rule_i->rhs - ritem; + unsigned int rhs_count = 0; + /* Find the last RHS index in ritems. */ + for (rp = rule_i->rhs; *rp >= 0; ++rp) + ++rhs_count; + fprintf (out, "%3d (%2d, %2d, %2d, %2u-%2u) %2d ->", + i, + rule_i->prec ? rule_i->prec->prec : 0, + rule_i->prec ? rule_i->prec->assoc : 0, + rule_i->useful, + rhs_itemno, + rhs_itemno + rhs_count - 1, + rule_i->lhs->number); + /* Dumped the RHS. */ + for (rp = rule_i->rhs; *rp >= 0; rp++) + fprintf (out, " %3d", *rp); + fprintf (out, " [%d]\n", item_number_as_rule_number (*rp)); + } + } + fprintf (out, "\n\n"); + + fprintf (out, "Rules interpreted\n-----------------\n\n"); + { + rule_number r; + for (r = 0; r < nrules + nuseless_productions; r++) + { + fprintf (out, "%-5d %s:", r, rules[r].lhs->tag); + rule_rhs_print (&rules[r], out); + fprintf (out, "\n"); + } + } + fprintf (out, "\n\n"); +} + +void +grammar_rules_useless_report (const char *message) +{ + rule_number r; + for (r = 0; r < nrules ; ++r) + if (!rules[r].useful) + complain (&rules[r].location, Wother, "%s", message); +} + +void +grammar_free (void) +{ + if (ritem) + free (ritem - 1); + free (rules); + free (token_translations); + /* Free the symbol table data structure. */ + symbols_free (); + free_merger_functions (); +} diff --git a/contrib/tools/bison/src/gram.h b/contrib/tools/bison/src/gram.h new file mode 100644 index 0000000000..c1dd9a648a --- /dev/null +++ b/contrib/tools/bison/src/gram.h @@ -0,0 +1,273 @@ +/* Data definitions for internal representation of Bison's input. + + Copyright (C) 1984, 1986, 1989, 1992, 2001-2007, 2009-2013 Free + Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef GRAM_H_ +# define GRAM_H_ + +/* Representation of the grammar rules: + + NTOKENS is the number of tokens, and NVARS is the number of + variables (nonterminals). NSYMS is the total number, ntokens + + nvars. + + Each symbol (either token or variable) receives a symbol number. + Numbers 0 to NTOKENS - 1 are for tokens, and NTOKENS to NSYMS - 1 + are for variables. Symbol number zero is the end-of-input token. + This token is counted in ntokens. The true number of token values + assigned is NTOKENS reduced by one for each alias declaration. + + The rules receive rule numbers 1 to NRULES in the order they are + written. More precisely Bison augments the grammar with the + initial rule, '$accept: START-SYMBOL $end', which is numbered 1, + all the user rules are 2, 3 etc. Each time a rule number is + presented to the user, we subtract 1, so *displayed* rule numbers + are 0, 1, 2... + + Internally, we cannot use the number 0 for a rule because for + instance RITEM stores both symbol (the RHS) and rule numbers: the + symbols are shorts >= 0, and rule number are stored negative. + Therefore 0 cannot be used, since it would be both the rule number + 0, and the token $end). + + Actions are accessed via the rule number. + + The rules themselves are described by several arrays: amongst which + RITEM, and RULES. + + RULES is an array of rules, whose members are: + + RULES[R].lhs -- the symbol of the left hand side of rule R. + + RULES[R].rhs -- the index in RITEM of the beginning of the portion + for rule R. + + RULES[R].prec -- the symbol providing the precedence level of R. + + RULES[R].precsym -- the symbol attached (via %prec) to give its + precedence to R. Of course, if set, it is equal to 'prec', but we + need to distinguish one from the other when reducing: a symbol used + in a %prec is not useless. + + RULES[R].assoc -- the associativity of R. + + RULES[R].dprec -- the dynamic precedence level of R (for GLR + parsing). + + RULES[R].merger -- index of merging function for R (for GLR + parsing). + + RULES[R].line -- the line where R was defined. + + RULES[R].useful -- true iff the rule is used (i.e., false if thrown + away by reduce). + + The right hand side is stored as symbol numbers in a portion of + RITEM. + + The length of the portion is one greater than the number of symbols + in the rule's right hand side. The last element in the portion + contains minus R, which identifies it as the end of a portion and + says which rule it is for. + + The portions of RITEM come in order of increasing rule number. + NRITEMS is the total length of RITEM. Each element of RITEM is + called an "item" and its index in RITEM is an item number. + + Item numbers are used in the finite state machine to represent + places that parsing can get to. + + SYMBOLS[I]->prec records the precedence level of each symbol. + + Precedence levels are assigned in increasing order starting with 1 + so that numerically higher precedence values mean tighter binding + as they ought to. Zero as a symbol or rule's precedence means none + is assigned. + + Associativities are recorded similarly in SYMBOLS[I]->assoc. */ + +# include "location.h" +# include "symtab.h" + +# define ISTOKEN(i) ((i) < ntokens) +# define ISVAR(i) ((i) >= ntokens) + +extern int nsyms; +extern int ntokens; +extern int nvars; + +typedef int item_number; +# define ITEM_NUMBER_MAX INT_MAX +extern item_number *ritem; +extern unsigned int nritems; + +/* There is weird relationship between OT1H item_number and OTOH + symbol_number and rule_number: we store the latter in + item_number. symbol_number values are stored as-is, while + the negation of (rule_number + 1) is stored. + + Therefore, a symbol_number must be a valid item_number, and we + sometimes have to perform the converse transformation. */ + +static inline item_number +symbol_number_as_item_number (symbol_number sym) +{ + return sym; +} + +static inline symbol_number +item_number_as_symbol_number (item_number i) +{ + return i; +} + +static inline bool +item_number_is_symbol_number (item_number i) +{ + return i >= 0; +} + +/* Rule numbers. */ +typedef int rule_number; +# define RULE_NUMBER_MAX INT_MAX +extern rule_number nrules; + +static inline item_number +rule_number_as_item_number (rule_number r) +{ + return -1 - r; +} + +static inline rule_number +item_number_as_rule_number (item_number i) +{ + return -1 - i; +} + +static inline bool +item_number_is_rule_number (item_number i) +{ + return i < 0; +} + +/*--------. +| Rules. | +`--------*/ + +typedef struct +{ + /* The number of the rule in the source. It is usually the index in + RULES too, except if there are useless rules. */ + rule_number user_number; + + /* The index in RULES. Usually the rule number in the source, + except if some rules are useless. */ + rule_number number; + + symbol *lhs; + item_number *rhs; + + /* This symbol provides both the associativity, and the precedence. */ + symbol *prec; + + int dprec; + int merger; + + /* This symbol was attached to the rule via %prec. */ + symbol *precsym; + + location location; + bool useful; + bool is_predicate; + + const char *action; + location action_location; +} rule; + +extern rule *rules; + +/* A function that selects a rule. */ +typedef bool (*rule_filter) (rule const *); + +/* Return true IFF the rule has a 'number' smaller than NRULES. That is, it is + useful in the grammar. */ +bool rule_useful_in_grammar_p (rule const *r); + +/* Return true IFF the rule has a 'number' higher than NRULES. That is, it is + useless in the grammar. */ +bool rule_useless_in_grammar_p (rule const *r); + +/* Return true IFF the rule is not flagged as useful but is useful in the + grammar. In other words, it was discarded because of conflicts. */ +bool rule_useless_in_parser_p (rule const *r); + +/* Print this rule's number and lhs on OUT. If a PREVIOUS_LHS was + already displayed (by a previous call for another rule), avoid + useless repetitions. */ +void rule_lhs_print (rule const *r, symbol const *previous_lhs, FILE *out); +void rule_lhs_print_xml (rule const *r, FILE *out, int level); + +/* Return the length of the RHS. */ +size_t rule_rhs_length (rule const *r); + +/* Print this rule's RHS on OUT. */ +void rule_rhs_print (rule const *r, FILE *out); + + + + +/* Table of the symbols, indexed by the symbol number. */ +extern symbol **symbols; + +/* TOKEN_TRANSLATION -- a table indexed by a token number as returned + by the user's yylex routine, it yields the internal token number + used by the parser and throughout bison. */ +extern symbol_number *token_translations; +extern int max_user_token_number; + + + +/* Dump RITEM for traces. */ +void ritem_print (FILE *out); + +/* Return the size of the longest rule RHS. */ +size_t ritem_longest_rhs (void); + +/* Print the grammar's rules that match FILTER on OUT under TITLE. */ +void grammar_rules_partial_print (FILE *out, const char *title, + rule_filter filter); + +/* Print the grammar's useful rules on OUT. */ +void grammar_rules_print (FILE *out); +/* Print all of the grammar's rules with a "usefulness" attribute. */ +void grammar_rules_print_xml (FILE *out, int level); + +/* Dump the grammar. */ +void grammar_dump (FILE *out, const char *title); + +/* Report on STDERR the rules that are not flagged USEFUL, using the + MESSAGE (which can be 'rule useless in grammar' when invoked after grammar + reduction, or 'rule useless in parser due to conflicts' after conflicts + were taken into account). */ +void grammar_rules_useless_report (const char *message); + +/* Free the packed grammar. */ +void grammar_free (void); + +#endif /* !GRAM_H_ */ diff --git a/contrib/tools/bison/src/graphviz.c b/contrib/tools/bison/src/graphviz.c new file mode 100644 index 0000000000..5ee41e73f3 --- /dev/null +++ b/contrib/tools/bison/src/graphviz.c @@ -0,0 +1,218 @@ +/* Output Graphviz specification of a state machine generated by Bison. + + Copyright (C) 2006-2007, 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert and Satya Kiran Popuri. */ + +#include <config.h> +#include "system.h" + +#include <quotearg.h> + +#include "files.h" +#include "gram.h" +#include "graphviz.h" +#include "tables.h" + +/* Return an unambiguous printable representation for NAME, suitable + for C strings. Use slot 2 since the user may use slots 0 and 1. */ + +static char * +quote (char const *name) +{ + return quotearg_n_style (2, c_quoting_style, name); +} + +void +start_graph (FILE *fout) +{ + fprintf (fout, + _("// Generated by %s.\n" + "// Report bugs to <%s>.\n" + "// Home page: <%s>.\n" + "\n"), + PACKAGE_STRING, + PACKAGE_BUGREPORT, + PACKAGE_URL); + fprintf (fout, + "digraph %s\n" + "{\n", + quote (grammar_file)); + fprintf (fout, + " node [fontname = courier, shape = box, colorscheme = paired6]\n" + " edge [fontname = courier]\n" + "\n"); +} + +void +output_node (int id, char const *label, FILE *fout) +{ + fprintf (fout, " %d [label=\"%s\"]\n", id, label); +} + +void +output_edge (int source, int destination, char const *label, + char const *style, FILE *fout) +{ + fprintf (fout, " %d -> %d [style=%s", source, destination, style); + if (label) + fprintf (fout, " label=%s", quote (label)); + fputs ("]\n", fout); +} + +char const * +escape (char const *name) +{ + char *q = quote (name); + q[strlen (q) - 1] = '\0'; + return q + 1; +} + +static void +no_reduce_bitset_init (state const *s, bitset *no_reduce_set) +{ + int n; + *no_reduce_set = bitset_create (ntokens, BITSET_FIXED); + bitset_zero (*no_reduce_set); + FOR_EACH_SHIFT (s->transitions, n) + bitset_set (*no_reduce_set, TRANSITION_SYMBOL (s->transitions, n)); + for (n = 0; n < s->errs->num; ++n) + if (s->errs->symbols[n]) + bitset_set (*no_reduce_set, s->errs->symbols[n]->number); +} + +static void +conclude_red (struct obstack *out, int source, rule_number ruleno, + bool enabled, bool first, FILE *fout) +{ + /* If no lookahead tokens were valid transitions, this reduction is + actually hidden, so cancel everything. */ + if (first) + (void) obstack_finish0 (out); + else + { + char const *ed = enabled ? "" : "d"; + char const *color = enabled ? ruleno ? "3" : "1" : "5"; + + /* First, build the edge's head. The name of reduction nodes is "nRm", + with n the source state and m the rule number. This is because we + don't want all the reductions bearing a same rule number to point to + the same state, since that is not the desired format. */ + fprintf (fout, " %1$d -> \"%1$dR%2$d%3$s\" [", + source, ruleno, ed); + + /* (The lookahead tokens have been added to the beginning of the + obstack, in the caller function.) */ + if (! obstack_empty_p (out)) + { + char *label = obstack_finish0 (out); + fprintf (fout, "label=\"[%s]\", ", label); + obstack_free (out, label); + } + + /* Then, the edge's tail. */ + fprintf (fout, "style=solid]\n"); + + /* Build the associated diamond representation of the target rule. */ + fprintf (fout, " \"%dR%d%s\" [label=\"", + source, ruleno, ed); + if (ruleno) + fprintf (fout, "R%d", ruleno); + else + fprintf (fout, "Acc"); + + fprintf (fout, "\", fillcolor=%s, shape=diamond, style=filled]\n", + color); + } +} + +static bool +print_token (struct obstack *out, bool first, char const *tok) +{ + char const *q = escape (tok); + + if (! first) + obstack_sgrow (out, ", "); + obstack_sgrow (out, q); + return false; +} + +void +output_red (state const *s, reductions const *reds, FILE *fout) +{ + bitset no_reduce_set; + int j; + int source = s->number; + + /* Two obstacks are needed: one for the enabled reductions, and one + for the disabled reductions, because in the end we want two + separate edges, even though in most cases only one will actually + be printed. */ + struct obstack dout; + struct obstack eout; + + no_reduce_bitset_init (s, &no_reduce_set); + obstack_init (&dout); + obstack_init (&eout); + + for (j = 0; j < reds->num; ++j) + { + bool defaulted = false; + bool firstd = true; + bool firste = true; + rule_number ruleno = reds->rules[j]->number; + rule *default_reduction = NULL; + + if (yydefact[s->number] != 0) + default_reduction = &rules[yydefact[s->number] - 1]; + + /* Build the lookahead tokens lists, one for enabled transitions and one + for disabled transistions. */ + if (default_reduction && default_reduction == reds->rules[j]) + defaulted = true; + if (reds->lookahead_tokens) + { + int i; + for (i = 0; i < ntokens; i++) + if (bitset_test (reds->lookahead_tokens[j], i)) + { + if (bitset_test (no_reduce_set, i)) + firstd = print_token (&dout, firstd, symbols[i]->tag); + else + { + if (! defaulted) + firste = print_token (&eout, firste, symbols[i]->tag); + bitset_set (no_reduce_set, i); + } + } + } + + /* Do the actual output. */ + conclude_red (&dout, source, ruleno, false, firstd, fout); + conclude_red (&eout, source, ruleno, true, firste && !defaulted, fout); + } + obstack_free (&dout, 0); + obstack_free (&eout, 0); + bitset_free (no_reduce_set); +} + +void +finish_graph (FILE *fout) +{ + fputs ("}\n", fout); +} diff --git a/contrib/tools/bison/src/graphviz.h b/contrib/tools/bison/src/graphviz.h new file mode 100644 index 0000000000..0254ef748b --- /dev/null +++ b/contrib/tools/bison/src/graphviz.h @@ -0,0 +1,71 @@ +/* Output Graphviz specification of a state machine generated by Bison. + + Copyright (C) 2006, 2010-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Paul Eggert and Satya Kiran Popuri. */ + +#ifndef GRAPHVIZ_H_ +# define GRAPHVIZ_H_ + +# include "state.h" + +/** Begin a Dot graph. + * + * \param fout output stream. + */ +void start_graph (FILE *fout); + +/** Output a Dot node. + * + * \param id identifier of the node + * \param label human readable label of the node (no Dot escaping needed). + * \param fout output stream. + */ +void output_node (int id, char const *label, FILE *fout); + +/** Output a Dot edge. + * \param source id of the source node + * \param destination id of the target node + * \param label human readable label of the edge + * (no Dot escaping needed). Can be 0. + * \param style Dot style of the edge (e.g., "dotted" or "solid"). + * \param fout output stream. + */ +void output_edge (int source, int destination, char const *label, + char const *style, FILE *fout); + +/** Output a reduction. + * \param s current state + * \param reds the set of reductions + * \param fout output stream. + */ +void output_red (state const *s, reductions const *reds, FILE *fout); + +/** End a Dot graph. + * + * \param fout output stream. + */ +void finish_graph (FILE *fout); + +/** Escape a lookahead token. + * + * \param name the token. + */ +char const *escape (char const *name); + +#endif /* ! GRAPHVIZ_H_ */ diff --git a/contrib/tools/bison/src/ielr.c b/contrib/tools/bison/src/ielr.c new file mode 100644 index 0000000000..38156b384d --- /dev/null +++ b/contrib/tools/bison/src/ielr.c @@ -0,0 +1,1200 @@ +/* IELR main implementation. + + Copyright (C) 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include "ielr.h" + +#include <bitset.h> +#include <timevar.h> + +#include "AnnotationList.h" +#include "derives.h" +#include "getargs.h" +#include "lalr.h" +#include "muscle-tab.h" +#include "nullable.h" +#include "relation.h" +#include "state.h" +#include "symtab.h" + +/** Records the value of the \%define variable lr.type. */ +typedef enum { LR_TYPE__LALR, LR_TYPE__IELR, LR_TYPE__CANONICAL_LR } LrType; + +/** + * \post: + * - \c result = a new \c bitset of size \c ::nritems such that any bit \c i + * is set iff <tt>ritem[i]</tt> is a nonterminal after which all ritems in + * the same RHS are nullable nonterminals. In other words, the follows of + * a goto on <tt>ritem[i]</tt> include the lookahead set of the item. + */ +static bitset +ielr_compute_ritem_sees_lookahead_set (void) +{ + bitset result = bitset_create (nritems, BITSET_FIXED); + unsigned int i = nritems-1; + while (i>0) + { + --i; + while (!item_number_is_rule_number (ritem[i]) + && ISVAR (ritem[i]) + && nullable [item_number_as_symbol_number (ritem[i]) - ntokens]) + bitset_set (result, i--); + if (!item_number_is_rule_number (ritem[i]) && ISVAR (ritem[i])) + bitset_set (result, i--); + while (!item_number_is_rule_number (ritem[i]) && i>0) + --i; + } + if (trace_flag & trace_ielr) + { + fprintf (stderr, "ritem_sees_lookahead_set:\n"); + debug_bitset (result); + fprintf (stderr, "\n"); + } + return result; +} + +/** + * \pre: + * - \c ritem_sees_lookahead_set was computed by + * \c ielr_compute_ritem_sees_lookahead_set. + * \post: + * - Each of \c *edgesp and \c *edge_countsp is a new array of size + * \c ::ngotos. + * - <tt>(*edgesp)[i]</tt> points to a \c goto_number array of size + * <tt>(*edge_countsp)[i]+1</tt>. + * - In such a \c goto_number array, the last element is \c ::END_NODE. + * - All remaining elements are the indices of the gotos to which there is an + * internal follow edge from goto \c i. + * - There is an internal follow edge from goto \c i to goto \c j iff both: + * - The from states of gotos \c i and \c j are the same. + * - The transition nonterminal for goto \c i appears as the first RHS + * symbol of at least one production for which both: + * - The LHS is the transition symbol of goto \c j. + * - All other RHS symbols are nullable nonterminals. + * - In other words, the follows of goto \c i include the follows of + * goto \c j and it's an internal edge because the from states are the + * same. + */ +static void +ielr_compute_internal_follow_edges (bitset ritem_sees_lookahead_set, + goto_number ***edgesp, int **edge_countsp) +{ + *edgesp = xnmalloc (ngotos, sizeof **edgesp); + *edge_countsp = xnmalloc (ngotos, sizeof **edge_countsp); + { + bitset sources = bitset_create (ngotos, BITSET_FIXED); + goto_number i; + for (i = 0; i < ngotos; ++i) + (*edge_countsp)[i] = 0; + for (i = 0; i < ngotos; ++i) + { + int nsources = 0; + { + rule **rulep; + for (rulep = derives[states[to_state[i]]->accessing_symbol + - ntokens]; + *rulep; + ++rulep) + { + /* If there is at least one RHS symbol, if the first RHS symbol + is a nonterminal, and if all remaining RHS symbols (if any) + are nullable nonterminals, create an edge from the LHS + symbol's goto to the first RHS symbol's goto such that the RHS + symbol's goto will be the source of the edge after the + eventual relation_transpose below. + + Unlike in ielr_compute_always_follows, I use a bitset for + edges rather than an array because it is possible that + multiple RHS's with the same first symbol could fit and thus + that we could end up with redundant edges. With the + possibility of redundant edges, it's hard to know ahead of + time how large to make such an array. Another possible + redundancy is that source and destination might be the same + goto. Eliminating all these possible redundancies now might + possibly help performance a little. I have not proven any of + this, but I'm guessing the bitset shouldn't entail much of a + performance penalty, if any. */ + if (bitset_test (ritem_sees_lookahead_set, + (*rulep)->rhs - ritem)) + { + goto_number source = + map_goto (from_state[i], + item_number_as_symbol_number (*(*rulep)->rhs)); + if (i != source && !bitset_test (sources, source)) + { + bitset_set (sources, source); + ++nsources; + ++(*edge_countsp)[source]; + } + } + } + } + if (nsources == 0) + (*edgesp)[i] = NULL; + else + { + (*edgesp)[i] = xnmalloc (nsources + 1, sizeof *(*edgesp)[i]); + { + bitset_iterator biter_source; + bitset_bindex source; + int j = 0; + BITSET_FOR_EACH (biter_source, sources, source, 0) + (*edgesp)[i][j++] = source; + } + (*edgesp)[i][nsources] = END_NODE; + } + bitset_zero (sources); + } + bitset_free (sources); + } + + relation_transpose (edgesp, ngotos); + + if (trace_flag & trace_ielr) + { + fprintf (stderr, "internal_follow_edges:\n"); + relation_print (*edgesp, ngotos, stderr); + } +} + +/** + * \pre: + * - \c ritem_sees_lookahead_set was computed by + * \c ielr_compute_ritem_sees_lookahead_set. + * - \c internal_follow_edges was computed by + * \c ielr_compute_internal_follow_edges. + * \post: + * - \c *follow_kernel_itemsp is a new \c bitsetv in which the number of rows + * is \c ngotos and the number of columns is maximum number of kernel items + * in any state. + * - <tt>(*follow_kernel_itemsp)[i][j]</tt> is set iff the follows of goto + * \c i include the lookahead set of item \c j in the from state of goto + * \c i. + * - Thus, <tt>(*follow_kernel_itemsp)[i][j]</tt> is always unset if there is + * no item \c j in the from state of goto \c i. + */ +static void +ielr_compute_follow_kernel_items (bitset ritem_sees_lookahead_set, + goto_number **internal_follow_edges, + bitsetv *follow_kernel_itemsp) +{ + { + size_t max_nitems = 0; + state_number i; + for (i = 0; i < nstates; ++i) + if (states[i]->nitems > max_nitems) + max_nitems = states[i]->nitems; + *follow_kernel_itemsp = bitsetv_create (ngotos, max_nitems, BITSET_FIXED); + } + { + goto_number i; + for (i = 0; i < ngotos; ++i) + { + size_t nitems = states[from_state[i]]->nitems; + item_number *items = states[from_state[i]]->items; + size_t j; + for (j = 0; j < nitems; ++j) + /* If this item has this goto and if all subsequent symbols in this + RHS (if any) are nullable nonterminals, then record this item as + one whose lookahead set is included in this goto's follows. */ + if (item_number_is_symbol_number (ritem[items[j]]) + && item_number_as_symbol_number (ritem[items[j]]) + == states[to_state[i]]->accessing_symbol + && bitset_test (ritem_sees_lookahead_set, items[j])) + bitset_set ((*follow_kernel_itemsp)[i], j); + } + } + relation_digraph (internal_follow_edges, ngotos, follow_kernel_itemsp); + + if (trace_flag & trace_ielr) + { + fprintf (stderr, "follow_kernel_items:\n"); + debug_bitsetv (*follow_kernel_itemsp); + } +} + +/** + * \pre + * - \c *edgesp and \c edge_counts were computed by + * \c ielr_compute_internal_follow_edges. + * \post + * - \c *always_followsp is a new \c bitsetv with \c ngotos rows and + * \c ntokens columns. + * - <tt>(*always_followsp)[i][j]</tt> is set iff token \c j is an always + * follow (that is, it's computed by internal and successor edges) of goto + * \c i. + * - Rows of \c *edgesp have been realloc'ed and extended to include + * successor follow edges. \c edge_counts has not been updated. + */ +static void +ielr_compute_always_follows (goto_number ***edgesp, + int const edge_counts[], + bitsetv *always_followsp) +{ + *always_followsp = bitsetv_create (ngotos, ntokens, BITSET_FIXED); + { + goto_number *edge_array = xnmalloc (ngotos, sizeof *edge_array); + goto_number i; + for (i = 0; i < ngotos; ++i) + { + goto_number nedges = edge_counts[i]; + { + int j; + transitions *trans = states[to_state[i]]->transitions; + FOR_EACH_SHIFT (trans, j) + bitset_set ((*always_followsp)[i], TRANSITION_SYMBOL (trans, j)); + for (; j < trans->num; ++j) + { + symbol_number sym = TRANSITION_SYMBOL (trans, j); + if (nullable[sym - ntokens]) + edge_array[nedges++] = map_goto (to_state[i], sym); + } + } + if (nedges - edge_counts[i]) + { + (*edgesp)[i] = + xnrealloc ((*edgesp)[i], nedges + 1, sizeof *(*edgesp)[i]); + memcpy ((*edgesp)[i] + edge_counts[i], edge_array + edge_counts[i], + (nedges - edge_counts[i]) * sizeof *(*edgesp)[i]); + (*edgesp)[i][nedges] = END_NODE; + } + } + free (edge_array); + } + relation_digraph (*edgesp, ngotos, always_followsp); + + if (trace_flag & trace_ielr) + { + fprintf (stderr, "always follow edges:\n"); + relation_print (*edgesp, ngotos, stderr); + fprintf (stderr, "always_follows:\n"); + debug_bitsetv (*always_followsp); + } +} + +/** + * \post + * - \c result is a new array of size \c ::nstates. + * - <tt>result[i]</tt> is an array of pointers to the predecessor + * <tt>state</tt>'s of state \c i. + * - The last element of such an array is \c NULL. + */ +static state *** +ielr_compute_predecessors (void) +{ + state_number i; + int *predecessor_counts = xnmalloc (nstates, sizeof *predecessor_counts); + state ***result = xnmalloc (nstates, sizeof *result); + for (i = 0; i < nstates; ++i) + predecessor_counts[i] = 0; + for (i = 0; i < nstates; ++i) + { + int j; + for (j = 0; j < states[i]->transitions->num; ++j) + ++predecessor_counts[states[i]->transitions->states[j]->number]; + } + for (i = 0; i < nstates; ++i) + { + result[i] = xnmalloc (predecessor_counts[i]+1, sizeof *result[i]); + result[i][predecessor_counts[i]] = NULL; + predecessor_counts[i] = 0; + } + for (i = 0; i < nstates; ++i) + { + int j; + for (j = 0; j < states[i]->transitions->num; ++j) + { + state_number k = states[i]->transitions->states[j]->number; + result[k][predecessor_counts[k]++] = states[i]; + } + } + free (predecessor_counts); + return result; +} + +/** + * \post + * - \c *follow_kernel_itemsp and \c *always_followsp were computed by + * \c ielr_compute_follow_kernel_items and + * \c ielr_compute_always_follows. + * - Iff <tt>predecessorsp != NULL</tt>, then \c *predecessorsp was computed + * by \c ielr_compute_predecessors. + */ +static void +ielr_compute_auxiliary_tables (bitsetv *follow_kernel_itemsp, + bitsetv *always_followsp, + state ****predecessorsp) +{ + goto_number **edges; + int *edge_counts; + { + bitset ritem_sees_lookahead_set = ielr_compute_ritem_sees_lookahead_set (); + ielr_compute_internal_follow_edges (ritem_sees_lookahead_set, + &edges, &edge_counts); + ielr_compute_follow_kernel_items (ritem_sees_lookahead_set, edges, + follow_kernel_itemsp); + bitset_free (ritem_sees_lookahead_set); + } + ielr_compute_always_follows (&edges, edge_counts, always_followsp); + { + int i; + for (i = 0; i < ngotos; ++i) + free (edges[i]); + } + free (edges); + free (edge_counts); + if (predecessorsp) + *predecessorsp = ielr_compute_predecessors (); +} + +/** + * \note + * - FIXME: It might be an interesting experiment to compare the space and + * time efficiency of computing \c item_lookahead_sets either: + * - Fully up front. + * - Just-in-time, as implemented below. + * - Not at all. That is, just let annotations continue even when + * unnecessary. + */ +bool +ielr_item_has_lookahead (state *s, symbol_number lhs, size_t item, + symbol_number lookahead, state ***predecessors, + bitset **item_lookahead_sets) +{ + if (!item_lookahead_sets[s->number]) + { + size_t i; + item_lookahead_sets[s->number] = + xnmalloc (s->nitems, sizeof item_lookahead_sets[s->number][0]); + for (i = 0; i < s->nitems; ++i) + item_lookahead_sets[s->number][i] = NULL; + } + if (!item_lookahead_sets[s->number][item]) + { + item_lookahead_sets[s->number][item] = + bitset_create (ntokens, BITSET_FIXED); + /* If this kernel item is the beginning of a RHS, it must be the kernel + item in the start state, and so its LHS has no follows and no goto to + check. If, instead, this kernel item is the successor of the start + state's kernel item, there are still no follows and no goto. This + situation is fortunate because we want to avoid the - 2 below in both + cases. + + Actually, IELR(1) should never invoke this function for either of + those cases because (1) follow_kernel_items will never reference a + kernel item for this RHS because the end token blocks sight of the + lookahead set from the RHS's only nonterminal, and (2) no reduction + has a lookback dependency on this lookahead set. Nevertheless, I + didn't change this test to an aver just in case the usage of this + function evolves to need those two cases. In both cases, the current + implementation returns the right result. */ + if (s->items[item] > 1) + { + /* If the LHS symbol of this item isn't known (because this is a + top-level invocation), go get it. */ + if (!lhs) + { + unsigned int i; + for (i = s->items[item]; + !item_number_is_rule_number (ritem[i]); + ++i) + ; + lhs = rules[item_number_as_rule_number (ritem[i])].lhs->number; + } + /* If this kernel item is next to the beginning of the RHS, then + check all predecessors' goto follows for the LHS. */ + if (item_number_is_rule_number (ritem[s->items[item] - 2])) + { + state **predecessor; + aver (lhs != accept->number); + for (predecessor = predecessors[s->number]; + *predecessor; + ++predecessor) + bitset_or (item_lookahead_sets[s->number][item], + item_lookahead_sets[s->number][item], + goto_follows[map_goto ((*predecessor)->number, + lhs)]); + } + /* If this kernel item is later in the RHS, then check all + predecessor items' lookahead sets. */ + else + { + state **predecessor; + for (predecessor = predecessors[s->number]; + *predecessor; + ++predecessor) + { + size_t predecessor_item; + for (predecessor_item = 0; + predecessor_item < (*predecessor)->nitems; + ++predecessor_item) + if ((*predecessor)->items[predecessor_item] + == s->items[item] - 1) + break; + aver (predecessor_item != (*predecessor)->nitems); + ielr_item_has_lookahead (*predecessor, lhs, + predecessor_item, 0 /*irrelevant*/, + predecessors, item_lookahead_sets); + bitset_or (item_lookahead_sets[s->number][item], + item_lookahead_sets[s->number][item], + item_lookahead_sets[(*predecessor)->number] + [predecessor_item]); + } + } + } + } + return bitset_test (item_lookahead_sets[s->number][item], lookahead); +} + +/** + * \pre + * - \c follow_kernel_items, \c always_follows, and \c predecessors + * were computed by \c ielr_compute_auxiliary_tables. + * \post + * - Each of <tt>*inadequacy_listsp</tt> and <tt>*annotation_listsp</tt> + * points to a new array of size \c ::nstates. + * - For <tt>0 <= i < ::nstates</tt>: + * - <tt>(*inadequacy_listsp)[i]</tt> contains the \c InadequacyList head + * node for <tt>states[i]</tt>. + * - <tt>(*annotation_listsp)[i]</tt> contains the \c AnnotationList head + * node for <tt>states[i]</tt>. + * - <tt>*max_annotationsp</tt> is the maximum number of annotations per + * state. + */ +static void +ielr_compute_annotation_lists (bitsetv follow_kernel_items, + bitsetv always_follows, state ***predecessors, + AnnotationIndex *max_annotationsp, + InadequacyList ***inadequacy_listsp, + AnnotationList ***annotation_listsp, + struct obstack *annotations_obstackp) +{ + bitset **item_lookahead_sets = + xnmalloc (nstates, sizeof *item_lookahead_sets); + AnnotationIndex *annotation_counts = + xnmalloc (nstates, sizeof *annotation_counts); + ContributionIndex max_contributions = 0; + unsigned int total_annotations = 0; + state_number i; + + *inadequacy_listsp = xnmalloc (nstates, sizeof **inadequacy_listsp); + *annotation_listsp = xnmalloc (nstates, sizeof **annotation_listsp); + for (i = 0; i < nstates; ++i) + { + item_lookahead_sets[i] = NULL; + (*inadequacy_listsp)[i] = NULL; + (*annotation_listsp)[i] = NULL; + annotation_counts[i] = 0; + } + { + InadequacyListNodeCount inadequacy_list_node_count = 0; + for (i = 0; i < nstates; ++i) + AnnotationList__compute_from_inadequacies ( + states[i], follow_kernel_items, always_follows, predecessors, + item_lookahead_sets, *inadequacy_listsp, *annotation_listsp, + annotation_counts, &max_contributions, annotations_obstackp, + &inadequacy_list_node_count); + } + *max_annotationsp = 0; + for (i = 0; i < nstates; ++i) + { + if (annotation_counts[i] > *max_annotationsp) + *max_annotationsp = annotation_counts[i]; + total_annotations += annotation_counts[i]; + } + if (trace_flag & trace_ielr) + { + for (i = 0; i < nstates; ++i) + { + fprintf (stderr, "Inadequacy annotations for state %d:\n", i); + AnnotationList__debug ((*annotation_listsp)[i], + states[i]->nitems, 2); + } + fprintf (stderr, "Number of LR(0)/LALR(1) states: %d\n", nstates); + fprintf (stderr, "Average number of annotations per state: %f\n", + (float)total_annotations/nstates); + fprintf (stderr, "Max number of annotations per state: %d\n", + *max_annotationsp); + fprintf (stderr, "Max number of contributions per annotation: %d\n", + max_contributions); + } + for (i = 0; i < nstates; ++i) + if (item_lookahead_sets[i]) + { + size_t j; + for (j = 0; j < states[i]->nitems; ++j) + if (item_lookahead_sets[i][j]) + bitset_free (item_lookahead_sets[i][j]); + free (item_lookahead_sets[i]); + } + free (item_lookahead_sets); + free (annotation_counts); +} + +typedef struct state_list { + struct state_list *next; + state *state; + /** Has this state been recomputed as a successor of another state? */ + bool recomputedAsSuccessor; + /** + * \c NULL iff all lookahead sets are empty. <tt>lookaheads[i] = NULL</tt> + * iff the lookahead set on item \c i is empty. + */ + bitset *lookaheads; + /** + * nextIsocore is the next state in a circularly linked-list of all states + * with the same core. The one originally computed by generate_states in + * LR0.c is lr0Isocore. + */ + struct state_list *lr0Isocore; + struct state_list *nextIsocore; +} state_list; + +/** + * \pre + * - \c follow_kernel_items and \c always_follows were computed by + * \c ielr_compute_auxiliary_tables. + * - <tt>n->class = nterm_sym</tt>. + * \post + * - \c follow_set contains the follow set for the goto on nonterminal \c n + * in state \c s based on the lookaheads stored in <tt>s->lookaheads</tt>. + */ +static void +ielr_compute_goto_follow_set (bitsetv follow_kernel_items, + bitsetv always_follows, state_list *s, + symbol *n, bitset follow_set) +{ + goto_number n_goto = map_goto (s->lr0Isocore->state->number, n->number); + bitset_copy (follow_set, always_follows[n_goto]); + if (s->lookaheads) + { + bitset_iterator biter_item; + bitset_bindex item; + BITSET_FOR_EACH (biter_item, follow_kernel_items[n_goto], item, 0) + if (s->lookaheads[item]) + bitset_or (follow_set, follow_set, s->lookaheads[item]); + } +} + +/** + * \pre + * - \c follow_kernel_items and \c always_follows were computed by + * \c ielr_compute_auxiliary_tables. + * - \c lookahead_filter was computed by + * \c AnnotationList__computeLookaheadFilter for the original LR(0) isocore + * of \c t. + * - The number of rows in \c lookaheads is at least the number of items in + * \c t, and the number of columns is \c ::ntokens. + * \post + * - <tt>lookaheads[i][j]</tt> is set iff both: + * - <tt>lookahead_filter[i][j]</tt> is set. + * - The isocore of \c t that will be the transition successor of \c s will + * inherit from \c s token \c j into the lookahead set of item \c i. + */ +static void +ielr_compute_lookaheads (bitsetv follow_kernel_items, bitsetv always_follows, + state_list *s, state *t, bitsetv lookahead_filter, + bitsetv lookaheads) +{ + size_t s_item = 0; + size_t t_item; + bitsetv_zero (lookaheads); + for (t_item = 0; t_item < t->nitems; ++t_item) + { + /* If this kernel item is the beginning of a RHS, it must be the + kernel item in the start state, but t is supposed to be a successor + state. If, instead, this kernel item is the successor of the start + state's kernel item, the lookahead set is empty. This second case is + a special case to avoid the - 2 below, but the next successor can be + handled fine without special casing it. */ + aver (t->items[t_item] != 0); + if (t->items[t_item] > 1 + && !bitset_empty_p (lookahead_filter[t_item])) + { + if (item_number_is_rule_number (ritem[t->items[t_item] - 2])) + { + unsigned int rule_item; + for (rule_item = t->items[t_item]; + !item_number_is_rule_number (ritem[rule_item]); + ++rule_item) + ; + ielr_compute_goto_follow_set ( + follow_kernel_items, always_follows, s, + rules[item_number_as_rule_number (ritem[rule_item])].lhs, + lookaheads[t_item]); + } + else if (s->lookaheads) + { + /* We don't have to start the s item search at the beginning + every time because items from both states are sorted by their + indices in ritem. */ + for (; s_item < s->state->nitems; ++s_item) + if (s->state->items[s_item] == t->items[t_item] - 1) + break; + aver (s_item != s->state->nitems); + if (s->lookaheads[s_item]) + bitset_copy (lookaheads[t_item], s->lookaheads[s_item]); + } + bitset_and (lookaheads[t_item], + lookaheads[t_item], lookahead_filter[t_item]); + } + } +} + +/** + * \pre + * - \c follow_kernel_items and \c always_follows were computed by + * \c ielr_compute_auxiliary_tables. + * - Either: + * - <tt>annotation_lists = NULL</tt> and all bits in work2 are set. + * - \c annotation_lists was computed by \c ielr_compute_annotation_lists. + * - The number of rows in each of \c lookaheads and \c work2 is the maximum + * number of items in any state. The number of columns in each is + * \c ::ntokens. + * - \c lookaheads was computed by \c ielr_compute_lookaheads for \c t. + * - \c ::nstates is the total number of states, some not yet fully computed, + * in the list ending at \c *last_statep. It is at least the number of + * original LR(0) states. + * - The size of \c work1 is at least the number of annotations for the LR(0) + * isocore of \c t. + * \post + * - Either: + * - In the case that <tt>annotation_lists != NULL</tt>, + * <tt>lookaheads \@pre</tt> was merged with some isocore of \c t if + * permitted by the annotations for the original LR(0) isocore of \c t. + * If this changed the lookaheads in that isocore, those changes were + * propagated to all already computed transition successors recursively + * possibly resulting in the splitting of some of those successors. + * - In the case that <tt>annotation_lists = NULL</tt>, + * <tt>lookaheads \@pre</tt> was merged with some isocore of \c t if the + * isocore's lookahead sets were identical to those specified by + * <tt>lookaheads \@pre</tt>. + * - If no such merge was permitted, a new isocore of \c t containing + * <tt>lookaheads \@pre</tt> was appended to the state list whose + * previous tail was <tt>*last_statep \@pre</tt> and \c ::nstates was + * incremented. It was also appended to \c t's isocore list. + * - <tt>*tp</tt> = the isocore of \c t into which + * <tt>lookaheads \@pre</tt> was placed/merged. + * - \c lookaheads, \c work1, and \c work2 may have been altered. + */ +static void +ielr_compute_state (bitsetv follow_kernel_items, bitsetv always_follows, + AnnotationList **annotation_lists, state *t, + bitsetv lookaheads, state_list **last_statep, + ContributionIndex work1[], bitsetv work2, state **tp) +{ + state_list *lr0_isocore = t->state_list->lr0Isocore; + state_list **this_isocorep; + bool has_lookaheads; + + /* Determine whether there's an isocore of t with which these lookaheads can + be merged. */ + { + AnnotationIndex ai; + AnnotationList *a; + if (annotation_lists) + for (ai = 0, a = annotation_lists[lr0_isocore->state->number]; + a; + ++ai, a = a->next) + work1[ai] = + AnnotationList__computeDominantContribution ( + a, lr0_isocore->state->nitems, lookaheads, false); + for (this_isocorep = &t->state_list; + this_isocorep == &t->state_list || *this_isocorep != t->state_list; + this_isocorep = &(*this_isocorep)->nextIsocore) + { + if (!(*this_isocorep)->recomputedAsSuccessor) + break; + if (annotation_lists) + { + for (ai = 0, a = annotation_lists[lr0_isocore->state->number]; + a; + ++ai, a = a->next) + { + if (work1[ai] != ContributionIndex__none) + { + /* This isocore compatibility test depends on the fact + that, if the dominant contributions are the same for the + two isocores, then merging their lookahead sets will not + produce a state with a different dominant contribution. + */ + ContributionIndex ci = + AnnotationList__computeDominantContribution ( + a, lr0_isocore->state->nitems, + (*this_isocorep)->lookaheads, false); + if (ci != ContributionIndex__none && work1[ai] != ci) + break; + } + } + if (!a) + break; + } + else + { + size_t i; + for (i = 0; i < t->nitems; ++i) + { + if (!(*this_isocorep)->lookaheads + || !(*this_isocorep)->lookaheads[i]) + { + if (!bitset_empty_p (lookaheads[i])) + break; + } + /* bitset_equal_p uses the size of the first argument, + so lookaheads[i] must be the second argument. */ + else if (!bitset_equal_p ((*this_isocorep)->lookaheads[i], + lookaheads[i])) + break; + } + if (i == t->nitems) + break; + } + } + } + + has_lookaheads = false; + { + size_t i; + for (i = 0; i < lr0_isocore->state->nitems; ++i) + if (!bitset_empty_p (lookaheads[i])) + { + has_lookaheads = true; + break; + } + } + + /* Merge with an existing isocore. */ + if (this_isocorep == &t->state_list || *this_isocorep != t->state_list) + { + bool new_lookaheads = false; + *tp = (*this_isocorep)->state; + + /* Merge lookaheads into the state and record whether any of them are + actually new. */ + if (has_lookaheads) + { + size_t i; + if (!(*this_isocorep)->lookaheads) + { + (*this_isocorep)->lookaheads = + xnmalloc (t->nitems, sizeof (*this_isocorep)->lookaheads); + for (i = 0; i < t->nitems; ++i) + (*this_isocorep)->lookaheads[i] = NULL; + } + for (i = 0; i < t->nitems; ++i) + if (!bitset_empty_p (lookaheads[i])) + { + if (!(*this_isocorep)->lookaheads[i]) + (*this_isocorep)->lookaheads[i] = + bitset_create (ntokens, BITSET_FIXED); + bitset_andn (lookaheads[i], + lookaheads[i], (*this_isocorep)->lookaheads[i]); + bitset_or ((*this_isocorep)->lookaheads[i], + lookaheads[i], (*this_isocorep)->lookaheads[i]); + if (!bitset_empty_p (lookaheads[i])) + new_lookaheads = true; + } + } + + /* If new lookaheads were merged, propagate those lookaheads to the + successors, possibly splitting them. If *tp is being recomputed for + the first time, this isn't necessary because the main + ielr_split_states loop will handle the successors later. */ + if (!(*this_isocorep)->recomputedAsSuccessor) + (*this_isocorep)->recomputedAsSuccessor = true; + else if (new_lookaheads) + { + int i; + /* When merging demands identical lookahead sets, it is impossible to + merge new lookaheads. */ + aver (annotation_lists); + for (i = 0; i < (*tp)->transitions->num; ++i) + { + state *t2 = (*tp)->transitions->states[i]; + /* At any time, there's at most one state for which we have so + far initially recomputed only some of its successors in the + main ielr_split_states loop. Because we recompute successors + in order, we can just stop at the first such successor. Of + course, *tp might be a state some of whose successors have + been recomputed as successors of other states rather than as + successors of *tp. It's fine if we go ahead and propagate to + some of those. We'll propagate to them again (but stop when + we see nothing changes) and to the others when we reach *tp in + the main ielr_split_states loop later. */ + if (!t2->state_list->recomputedAsSuccessor) + break; + AnnotationList__computeLookaheadFilter ( + annotation_lists[t2->state_list->lr0Isocore->state->number], + t2->nitems, work2); + ielr_compute_lookaheads (follow_kernel_items, always_follows, + (*this_isocorep), t2, work2, + lookaheads); + /* FIXME: If splitting t2 here, it's possible that lookaheads + that had already propagated from *tp to t2 will be left in t2 + after *tp has been removed as t2's predecessor: + - We're going to recompute all lookaheads in phase 4, so these + extra lookaheads won't appear in the final parser table. + - If t2 has just one annotation, then these extra lookaheads + cannot alter the dominating contribution to the associated + inadequacy and thus cannot needlessly prevent a future merge + of some new state with t2. We can be sure of this because: + - The fact that we're splitting t2 now means that some + predecessors (at least one) other than *tp must be + propagating contributions to t2. + - The fact that t2 was merged in the first place means that, + if *tp propagated any contributions, the dominating + contribution must be the same as that from those other + predecessors. + - Thus, if some new state to be merged with t2 in the future + proves to be compatible with the contributions propagated + by the other predecessors, it will also be compatible with + the contributions made by the extra lookaheads left behind + by *tp. + - However, if t2 has more than one annotation and these extra + lookaheads contribute to one of their inadequacies, it's + possible these extra lookaheads may needlessly prevent a + future merge with t2. For example: + - Let's say there's an inadequacy A that makes the split + necessary as follows: + - There's currently just one other predecessor and it + propagates to t2 some contributions to inadequacy A. + - The new lookaheads that we were attempting to propagate + from *tp to t2 made contributions to inadequacy A with a + different dominating contribution than those from that + other predecessor. + - The extra lookaheads either make no contribution to + inadequacy A or have the same dominating contribution as + the contributions from the other predecessor. Either + way, as explained above, they can't prevent a future + merge. + - Let's say there's an inadequacy B that causes the trouble + with future merges as follows: + - The extra lookaheads make contributions to inadequacy B. + - Those extra contributions did not prevent the original + merge to create t2 because the other predecessor + propagates to t2 no contributions to inadequacy B. + - Thus, those extra contributions may prevent a future + merge with t2 even though the merge would be fine if *tp + had not left them behind. + - Is the latter case common enough to worry about? + - Perhaps we should track all predecessors and iterate them + now to recreate t2 without those extra lookaheads. */ + ielr_compute_state (follow_kernel_items, always_follows, + annotation_lists, t2, lookaheads, + last_statep, work1, work2, + &(*tp)->transitions->states[i]); + } + } + } + + /* Create a new isocore. */ + else + { + state_list *old_isocore = *this_isocorep; + (*last_statep)->next = *this_isocorep = xmalloc (sizeof **last_statep); + *last_statep = *this_isocorep; + (*last_statep)->state = *tp = state_new_isocore (t); + (*tp)->state_list = *last_statep; + (*last_statep)->recomputedAsSuccessor = true; + (*last_statep)->next = NULL; + (*last_statep)->lookaheads = NULL; + if (has_lookaheads) + { + size_t i; + (*last_statep)->lookaheads = + xnmalloc (t->nitems, sizeof (*last_statep)->lookaheads); + for (i = 0; i < t->nitems; ++i) + { + if (bitset_empty_p (lookaheads[i])) + (*last_statep)->lookaheads[i] = NULL; + else + { + (*last_statep)->lookaheads[i] = + bitset_create (ntokens, BITSET_FIXED); + bitset_copy ((*last_statep)->lookaheads[i], lookaheads[i]); + } + } + } + (*last_statep)->lr0Isocore = lr0_isocore; + (*last_statep)->nextIsocore = old_isocore; + } +} + +/** + * \pre + * - \c follow_kernel_items and \c always_follows were computed by + * \c ielr_compute_auxiliary_tables. + * - Either: + * - <tt>annotation_lists = NULL</tt> and <tt>max_annotations=0</tt>. + * - \c annotation_lists and \c max_annotations were computed by + * \c ielr_compute_annotation_lists. + * \post + * - \c ::states is of size \c ::nstates (which might be greater than + * <tt>::nstates \@pre</tt>) and no longer contains any LR(1)-relative + * inadequacy. \c annotation_lists was used to determine state + * compatibility or, if <tt>annotation_lists = NULL</tt>, the canonical + * LR(1) state compatibility test was used. + * - If <tt>annotation_lists = NULL</tt>, reduction lookahead sets were + * computed in all states. TV_IELR_PHASE4 was pushed while they were + * computed from item lookahead sets. + */ +static void +ielr_split_states (bitsetv follow_kernel_items, bitsetv always_follows, + AnnotationList **annotation_lists, + AnnotationIndex max_annotations) +{ + state_list *first_state; + state_list *last_state; + bitsetv lookahead_filter = NULL; + bitsetv lookaheads; + + /* Set up state list and some reusable bitsets. */ + { + size_t max_nitems = 0; + state_number i; + state_list **nodep = &first_state; + for (i = 0; i < nstates; ++i) + { + *nodep = states[i]->state_list = last_state = xmalloc (sizeof **nodep); + (*nodep)->state = states[i]; + (*nodep)->recomputedAsSuccessor = false; + (*nodep)->lookaheads = NULL; + (*nodep)->lr0Isocore = *nodep; + (*nodep)->nextIsocore = *nodep; + nodep = &(*nodep)->next; + if (states[i]->nitems > max_nitems) + max_nitems = states[i]->nitems; + } + *nodep = NULL; + lookahead_filter = bitsetv_create (max_nitems, ntokens, BITSET_FIXED); + if (!annotation_lists) + bitsetv_ones (lookahead_filter); + lookaheads = bitsetv_create (max_nitems, ntokens, BITSET_FIXED); + } + + /* Recompute states. */ + { + ContributionIndex *work = xnmalloc (max_annotations, sizeof *work); + state_list *this_state; + for (this_state = first_state; this_state; this_state = this_state->next) + { + state *s = this_state->state; + int i; + for (i = 0; i < s->transitions->num; ++i) + { + state *t = s->transitions->states[i]; + if (annotation_lists) + AnnotationList__computeLookaheadFilter ( + annotation_lists[t->state_list->lr0Isocore->state->number], + t->nitems, lookahead_filter); + ielr_compute_lookaheads (follow_kernel_items, always_follows, + this_state, t, lookahead_filter, + lookaheads); + ielr_compute_state (follow_kernel_items, always_follows, + annotation_lists, t, lookaheads, &last_state, + work, lookahead_filter, + &s->transitions->states[i]); + } + } + free (work); + } + + bitsetv_free (lookahead_filter); + bitsetv_free (lookaheads); + + /* Store states back in the states array. */ + states = xnrealloc (states, nstates, sizeof *states); + { + state_list *node; + for (node = first_state; node; node = node->next) + states[node->state->number] = node->state; + } + + /* In the case of canonical LR(1), copy item lookahead sets to reduction + lookahead sets. */ + if (!annotation_lists) + { + state_list *node; + timevar_push (TV_IELR_PHASE4); + initialize_LA (); + for (node = first_state; node; node = node->next) + if (!node->state->consistent) + { + size_t i = 0; + item_number *itemset = node->state->items; + size_t r; + for (r = 0; r < node->state->reductions->num; ++r) + { + rule *this_rule = node->state->reductions->rules[r]; + bitset lookahead_set = + node->state->reductions->lookahead_tokens[r]; + if (item_number_is_rule_number (*this_rule->rhs)) + ielr_compute_goto_follow_set (follow_kernel_items, + always_follows, node, + this_rule->lhs, lookahead_set); + else if (node->lookaheads) + { + /* We don't need to start the kernel item search back at + i=0 because both items and reductions are sorted on rule + number. */ + while (!item_number_is_rule_number (ritem[itemset[i]]) + || item_number_as_rule_number (ritem[itemset[i]]) + != this_rule->number) + { + ++i; + aver (i < node->state->nitems); + } + if (node->lookaheads[i]) + bitset_copy (lookahead_set, node->lookaheads[i]); + } + } + } + timevar_pop (TV_IELR_PHASE4); + } + + /* Free state list. */ + while (first_state) + { + state_list *node = first_state; + if (node->lookaheads) + { + size_t i; + for (i = 0; i < node->state->nitems; ++i) + if (node->lookaheads[i]) + bitset_free (node->lookaheads[i]); + free (node->lookaheads); + } + first_state = node->next; + free (node); + } +} + +void +ielr (void) +{ + LrType lr_type; + + /* Examine user options. */ + { + char *type = muscle_percent_define_get ("lr.type"); + if (STREQ (type, "lalr")) + lr_type = LR_TYPE__LALR; + else if (STREQ (type, "ielr")) + lr_type = LR_TYPE__IELR; + else if (STREQ (type, "canonical-lr")) + lr_type = LR_TYPE__CANONICAL_LR; + else + aver (false); + free (type); + } + + /* Phase 0: LALR(1). */ + timevar_push (TV_LALR); + if (lr_type == LR_TYPE__CANONICAL_LR) + set_goto_map (); + else + lalr (); + if (lr_type == LR_TYPE__LALR) + { + bitsetv_free (goto_follows); + timevar_pop (TV_LALR); + return; + } + timevar_pop (TV_LALR); + + { + bitsetv follow_kernel_items; + bitsetv always_follows; + InadequacyList **inadequacy_lists = NULL; + AnnotationList **annotation_lists = NULL; + struct obstack annotations_obstack; + AnnotationIndex max_annotations = 0; + + { + /* Phase 1: Compute Auxiliary Tables. */ + state ***predecessors; + timevar_push (TV_IELR_PHASE1); + ielr_compute_auxiliary_tables ( + &follow_kernel_items, &always_follows, + lr_type == LR_TYPE__CANONICAL_LR ? NULL : &predecessors); + timevar_pop (TV_IELR_PHASE1); + + /* Phase 2: Compute Annotations. */ + timevar_push (TV_IELR_PHASE2); + if (lr_type != LR_TYPE__CANONICAL_LR) + { + obstack_init (&annotations_obstack); + ielr_compute_annotation_lists (follow_kernel_items, always_follows, + predecessors, &max_annotations, + &inadequacy_lists, &annotation_lists, + &annotations_obstack); + { + state_number i; + for (i = 0; i < nstates; ++i) + free (predecessors[i]); + } + free (predecessors); + bitsetv_free (goto_follows); + lalr_free (); + } + timevar_pop (TV_IELR_PHASE2); + } + + /* Phase 3: Split States. */ + timevar_push (TV_IELR_PHASE3); + { + state_number nstates_lr0 = nstates; + ielr_split_states (follow_kernel_items, always_follows, + annotation_lists, max_annotations); + if (inadequacy_lists) + { + state_number i; + for (i = 0; i < nstates_lr0; ++i) + InadequacyList__delete (inadequacy_lists[i]); + } + } + free (inadequacy_lists); + if (annotation_lists) + obstack_free (&annotations_obstack, NULL); + free (annotation_lists); + bitsetv_free (follow_kernel_items); + bitsetv_free (always_follows); + timevar_pop (TV_IELR_PHASE3); + } + + /* Phase 4: Compute Reduction Lookaheads. */ + timevar_push (TV_IELR_PHASE4); + free (goto_map); + free (from_state); + free (to_state); + if (lr_type == LR_TYPE__CANONICAL_LR) + { + /* Reduction lookaheads are computed in ielr_split_states above + but are timed as part of phase 4. */ + set_goto_map (); + } + else + { + lalr (); + bitsetv_free (goto_follows); + } + timevar_pop (TV_IELR_PHASE4); +} diff --git a/contrib/tools/bison/src/ielr.h b/contrib/tools/bison/src/ielr.h new file mode 100644 index 0000000000..b60ae36348 --- /dev/null +++ b/contrib/tools/bison/src/ielr.h @@ -0,0 +1,46 @@ +/* IELR main implementation. + + Copyright (C) 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef IELR_H_ +# define IELR_H_ + +# include <bitset.h> + +# include "state.h" + +/** + * \pre + * - \c ::states is of size \c ::nstates and defines an LR(0) parser + * for the users's grammar. + * - \c ::ntokens is the number of tokens in the grammar. + * \post + * - \c ::states is of size \c ::nstates (which might be greater than + * <tt>::nstates \@pre</tt>) and defines the type of parser specified by + * the value of the \c \%define variable \c lr.type. Its value can be: + * - \c "lalr". + * - \c "ielr". + * - \c "canonical-lr". + */ +void ielr (void); + +bool ielr_item_has_lookahead (state *s, symbol_number lhs, size_t item, + symbol_number lookahead, state ***predecessors, + bitset **item_lookahead_sets); + +#endif /* !IELR_H_ */ diff --git a/contrib/tools/bison/src/lalr.c b/contrib/tools/bison/src/lalr.c new file mode 100644 index 0000000000..d99f960fbf --- /dev/null +++ b/contrib/tools/bison/src/lalr.c @@ -0,0 +1,500 @@ +/* Compute lookahead criteria for Bison. + + Copyright (C) 1984, 1986, 1989, 2000-2013 Free Software Foundation, + Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + + +/* Find which rules need lookahead in each state, and which lookahead + tokens they accept. */ + +#include <config.h> +#include "system.h" + +#include <bitset.h> +#include <bitsetv.h> + +#include "LR0.h" +#include "complain.h" +#include "derives.h" +#include "getargs.h" +#include "gram.h" +#include "lalr.h" +#include "muscle-tab.h" +#include "nullable.h" +#include "reader.h" +#include "relation.h" +#include "symtab.h" + +goto_number *goto_map; +goto_number ngotos; +state_number *from_state; +state_number *to_state; +bitsetv goto_follows = NULL; + +/* Linked list of goto numbers. */ +typedef struct goto_list +{ + struct goto_list *next; + goto_number value; +} goto_list; + + +/* LA is an NLA by NTOKENS matrix of bits. LA[l, i] is 1 if the rule + LArule[l] is applicable in the appropriate state when the next + token is symbol i. If LA[l, i] and LA[l, j] are both 1 for i != j, + it is a conflict. */ + +static bitsetv LA = NULL; +size_t nLA; + + +static goto_number **includes; +static goto_list **lookback; + + + + +void +set_goto_map (void) +{ + state_number s; + goto_number *temp_map; + + goto_map = xcalloc (nvars + 1, sizeof *goto_map); + temp_map = xnmalloc (nvars + 1, sizeof *temp_map); + + ngotos = 0; + for (s = 0; s < nstates; ++s) + { + transitions *sp = states[s]->transitions; + int i; + for (i = sp->num - 1; i >= 0 && TRANSITION_IS_GOTO (sp, i); --i) + { + ngotos++; + + /* Abort if (ngotos + 1) would overflow. */ + aver (ngotos != GOTO_NUMBER_MAXIMUM); + + goto_map[TRANSITION_SYMBOL (sp, i) - ntokens]++; + } + } + + { + goto_number k = 0; + int i; + for (i = ntokens; i < nsyms; i++) + { + temp_map[i - ntokens] = k; + k += goto_map[i - ntokens]; + } + + for (i = ntokens; i < nsyms; i++) + goto_map[i - ntokens] = temp_map[i - ntokens]; + + goto_map[nsyms - ntokens] = ngotos; + temp_map[nsyms - ntokens] = ngotos; + } + + from_state = xcalloc (ngotos, sizeof *from_state); + to_state = xcalloc (ngotos, sizeof *to_state); + + for (s = 0; s < nstates; ++s) + { + transitions *sp = states[s]->transitions; + int i; + for (i = sp->num - 1; i >= 0 && TRANSITION_IS_GOTO (sp, i); --i) + { + goto_number k = temp_map[TRANSITION_SYMBOL (sp, i) - ntokens]++; + from_state[k] = s; + to_state[k] = sp->states[i]->number; + } + } + + free (temp_map); +} + + +goto_number +map_goto (state_number s0, symbol_number sym) +{ + goto_number high; + goto_number low; + goto_number middle; + state_number s; + + low = goto_map[sym - ntokens]; + high = goto_map[sym - ntokens + 1] - 1; + + for (;;) + { + aver (low <= high); + middle = (low + high) / 2; + s = from_state[middle]; + if (s == s0) + return middle; + else if (s < s0) + low = middle + 1; + else + high = middle - 1; + } +} + + +static void +initialize_F (void) +{ + goto_number **reads = xnmalloc (ngotos, sizeof *reads); + goto_number *edge = xnmalloc (ngotos + 1, sizeof *edge); + goto_number nedges = 0; + + goto_number i; + + goto_follows = bitsetv_create (ngotos, ntokens, BITSET_FIXED); + + for (i = 0; i < ngotos; i++) + { + state_number stateno = to_state[i]; + transitions *sp = states[stateno]->transitions; + + int j; + FOR_EACH_SHIFT (sp, j) + bitset_set (goto_follows[i], TRANSITION_SYMBOL (sp, j)); + + for (; j < sp->num; j++) + { + symbol_number sym = TRANSITION_SYMBOL (sp, j); + if (nullable[sym - ntokens]) + edge[nedges++] = map_goto (stateno, sym); + } + + if (nedges == 0) + reads[i] = NULL; + else + { + reads[i] = xnmalloc (nedges + 1, sizeof reads[i][0]); + memcpy (reads[i], edge, nedges * sizeof edge[0]); + reads[i][nedges] = END_NODE; + nedges = 0; + } + } + + relation_digraph (reads, ngotos, &goto_follows); + + for (i = 0; i < ngotos; i++) + free (reads[i]); + + free (reads); + free (edge); +} + + +static void +add_lookback_edge (state *s, rule *r, goto_number gotono) +{ + int ri = state_reduction_find (s, r); + goto_list *sp = xmalloc (sizeof *sp); + sp->next = lookback[(s->reductions->lookahead_tokens - LA) + ri]; + sp->value = gotono; + lookback[(s->reductions->lookahead_tokens - LA) + ri] = sp; +} + + + +static void +build_relations (void) +{ + goto_number *edge = xnmalloc (ngotos + 1, sizeof *edge); + state_number *states1 = xnmalloc (ritem_longest_rhs () + 1, sizeof *states1); + goto_number i; + + includes = xnmalloc (ngotos, sizeof *includes); + + for (i = 0; i < ngotos; i++) + { + int nedges = 0; + symbol_number symbol1 = states[to_state[i]]->accessing_symbol; + rule **rulep; + + for (rulep = derives[symbol1 - ntokens]; *rulep; rulep++) + { + bool done; + int length = 1; + item_number const *rp; + state *s = states[from_state[i]]; + states1[0] = s->number; + + for (rp = (*rulep)->rhs; ! item_number_is_rule_number (*rp); rp++) + { + s = transitions_to (s->transitions, + item_number_as_symbol_number (*rp)); + states1[length++] = s->number; + } + + if (!s->consistent) + add_lookback_edge (s, *rulep, i); + + length--; + done = false; + while (!done) + { + done = true; + /* Each rhs ends in a rule number, and there is a + sentinel (ritem[-1]=0) before the first rhs, so it is safe to + decrement RP here. */ + rp--; + if (ISVAR (*rp)) + { + /* Downcasting from item_number to symbol_number. */ + edge[nedges++] = map_goto (states1[--length], + item_number_as_symbol_number (*rp)); + if (nullable[*rp - ntokens]) + done = false; + } + } + } + + if (nedges == 0) + includes[i] = NULL; + else + { + int j; + includes[i] = xnmalloc (nedges + 1, sizeof includes[i][0]); + for (j = 0; j < nedges; j++) + includes[i][j] = edge[j]; + includes[i][nedges] = END_NODE; + } + } + + free (edge); + free (states1); + + relation_transpose (&includes, ngotos); +} + + + +static void +compute_FOLLOWS (void) +{ + goto_number i; + + relation_digraph (includes, ngotos, &goto_follows); + + for (i = 0; i < ngotos; i++) + free (includes[i]); + + free (includes); +} + + +static void +compute_lookahead_tokens (void) +{ + size_t i; + goto_list *sp; + + for (i = 0; i < nLA; i++) + for (sp = lookback[i]; sp; sp = sp->next) + bitset_or (LA[i], LA[i], goto_follows[sp->value]); + + /* Free LOOKBACK. */ + for (i = 0; i < nLA; i++) + LIST_FREE (goto_list, lookback[i]); + + free (lookback); +} + + +/*----------------------------------------------------. +| Count the number of lookahead tokens required for S | +| (N_LOOKAHEAD_TOKENS member). | +`----------------------------------------------------*/ + +static int +state_lookahead_tokens_count (state *s, bool default_reduction_only_for_accept) +{ + int n_lookahead_tokens = 0; + reductions *rp = s->reductions; + transitions *sp = s->transitions; + + /* Transitions are only disabled during conflict resolution, and that + hasn't happened yet, so there should be no need to check that + transition 0 hasn't been disabled before checking if it is a shift. + However, this check was performed at one time, so we leave it as an + aver. */ + aver (sp->num == 0 || !TRANSITION_IS_DISABLED (sp, 0)); + + /* We need a lookahead either to distinguish different reductions + (i.e., there are two or more), or to distinguish a reduction from a + shift. Otherwise, it is straightforward, and the state is + 'consistent'. However, do not treat a state with any reductions as + consistent unless it is the accepting state (because there is never + a lookahead token that makes sense there, and so no lookahead token + should be read) if the user has otherwise disabled default + reductions. */ + if (rp->num > 1 + || (rp->num == 1 && sp->num && TRANSITION_IS_SHIFT (sp, 0)) + || (rp->num == 1 && rp->rules[0]->number != 0 + && default_reduction_only_for_accept)) + n_lookahead_tokens += rp->num; + else + s->consistent = 1; + + return n_lookahead_tokens; +} + + +/*----------------------------------------------------. +| Compute LA, NLA, and the lookahead_tokens members. | +`----------------------------------------------------*/ + +void +initialize_LA (void) +{ + state_number i; + bitsetv pLA; + bool default_reduction_only_for_accept; + { + char *default_reductions = + muscle_percent_define_get ("lr.default-reduction"); + default_reduction_only_for_accept = STREQ (default_reductions, "accepting"); + free (default_reductions); + } + + /* Compute the total number of reductions requiring a lookahead. */ + nLA = 0; + for (i = 0; i < nstates; i++) + nLA += + state_lookahead_tokens_count (states[i], + default_reduction_only_for_accept); + /* Avoid having to special case 0. */ + if (!nLA) + nLA = 1; + + pLA = LA = bitsetv_create (nLA, ntokens, BITSET_FIXED); + + /* Initialize the members LOOKAHEAD_TOKENS for each state whose reductions + require lookahead tokens. */ + for (i = 0; i < nstates; i++) + { + int count = + state_lookahead_tokens_count (states[i], + default_reduction_only_for_accept); + if (count) + { + states[i]->reductions->lookahead_tokens = pLA; + pLA += count; + } + } +} + + +/*---------------------------------------------. +| Output the lookahead tokens for each state. | +`---------------------------------------------*/ + +static void +lookahead_tokens_print (FILE *out) +{ + state_number i; + int j, k; + fprintf (out, "Lookahead tokens: BEGIN\n"); + for (i = 0; i < nstates; ++i) + { + reductions *reds = states[i]->reductions; + bitset_iterator iter; + int n_lookahead_tokens = 0; + + if (reds->lookahead_tokens) + for (k = 0; k < reds->num; ++k) + if (reds->lookahead_tokens[k]) + ++n_lookahead_tokens; + + fprintf (out, "State %d: %d lookahead tokens\n", + i, n_lookahead_tokens); + + if (reds->lookahead_tokens) + for (j = 0; j < reds->num; ++j) + BITSET_FOR_EACH (iter, reds->lookahead_tokens[j], k, 0) + { + fprintf (out, " on %d (%s) -> rule %d\n", + k, symbols[k]->tag, + reds->rules[j]->number); + }; + } + fprintf (out, "Lookahead tokens: END\n"); +} + +void +lalr (void) +{ + initialize_LA (); + set_goto_map (); + initialize_F (); + lookback = xcalloc (nLA, sizeof *lookback); + build_relations (); + compute_FOLLOWS (); + compute_lookahead_tokens (); + + if (trace_flag & trace_sets) + lookahead_tokens_print (stderr); +} + + +void +lalr_update_state_numbers (state_number old_to_new[], state_number nstates_old) +{ + goto_number ngotos_reachable = 0; + symbol_number nonterminal = 0; + aver (nsyms == nvars + ntokens); + { + goto_number i; + for (i = 0; i < ngotos; ++i) + { + while (i == goto_map[nonterminal]) + goto_map[nonterminal++] = ngotos_reachable; + /* If old_to_new[from_state[i]] = nstates_old, remove this goto + entry. */ + if (old_to_new[from_state[i]] != nstates_old) + { + /* from_state[i] is not removed, so it and thus to_state[i] are + reachable, so to_state[i] != nstates_old. */ + aver (old_to_new[to_state[i]] != nstates_old); + from_state[ngotos_reachable] = old_to_new[from_state[i]]; + to_state[ngotos_reachable] = old_to_new[to_state[i]]; + ++ngotos_reachable; + } + } + } + while (nonterminal <= nvars) + { + aver (ngotos == goto_map[nonterminal]); + goto_map[nonterminal++] = ngotos_reachable; + } + ngotos = ngotos_reachable; +} + + +void +lalr_free (void) +{ + state_number s; + for (s = 0; s < nstates; ++s) + states[s]->reductions->lookahead_tokens = NULL; + bitsetv_free (LA); +} diff --git a/contrib/tools/bison/src/lalr.h b/contrib/tools/bison/src/lalr.h new file mode 100644 index 0000000000..f483315747 --- /dev/null +++ b/contrib/tools/bison/src/lalr.h @@ -0,0 +1,106 @@ +/* Compute lookahead criteria for bison, + + Copyright (C) 1984, 1986, 1989, 2000, 2002, 2004, 2006-2007, + 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef LALR_H_ +# define LALR_H_ + +# include <bitset.h> +# include <bitsetv.h> + +/* Import the definition of RULE_T. */ +# include "gram.h" + +/* Import the definition of CORE, TRANSITIONS and REDUCTIONS. */ +# include "state.h" + + +/** Build the LALR(1) automaton. + + Find which rules need lookahead in each state, and which lookahead + tokens they accept. + + Also builds: + - #goto_map + - #from_state + - #to_state + - #goto_follows +*/ +void lalr (void); + +/** + * Set #nLA and allocate all reduction lookahead sets. Normally invoked by + * #lalr. + */ +void initialize_LA (void); + +/** + * Build only: + * - #goto_map + * - #from_state + * - #to_state + * Normally invoked by #lalr. + */ +void set_goto_map (void); + +/** + * Update state numbers recorded in #goto_map, #from_state, and #to_state such + * that: + * - \c nstates_old is the old number of states. + * - Where \c i is the old state number, <tt>old_to_new[i]</tt> is either: + * - \c nstates_old if state \c i is removed because it is unreachable. + * Thus, remove all goto entries involving this state. + * - The new state number. + */ +void lalr_update_state_numbers (state_number old_to_new[], + state_number nstates_old); + + +/** Release the information related to lookahead tokens. + + Can be performed once the action tables are computed. */ +void lalr_free (void); + +typedef size_t goto_number; +# define GOTO_NUMBER_MAXIMUM ((goto_number) -1) + +/** Index into #from_state and #to_state. + + All the transitions that accept a particular variable are grouped + together and GOTO_MAP[I - NTOKENS] is the index in FROM_STATE and + TO_STATE of the first of them. */ +extern goto_number *goto_map; + +/** The size of #from_state and #to_state. */ +extern goto_number ngotos; + +/** State number which a transition leads from. */ +extern state_number *from_state; + +/** State number it leads to. */ +extern state_number *to_state; + +/** Map a state/symbol pair into its numeric representation. */ +goto_number map_goto (state_number s0, symbol_number sym); + +/* goto_follows[i] is the set of tokens following goto i. */ +extern bitsetv goto_follows; + + +#endif /* !LALR_H_ */ diff --git a/contrib/tools/bison/src/location.c b/contrib/tools/bison/src/location.c new file mode 100644 index 0000000000..662b2a12a0 --- /dev/null +++ b/contrib/tools/bison/src/location.c @@ -0,0 +1,232 @@ +/* Locations for Bison + + Copyright (C) 2002, 2005-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include <mbswidth.h> +#include <quotearg.h> + +#include "complain.h" +#include "location.h" + +location const empty_location = EMPTY_LOCATION_INIT; + +/* If BUF is null, add BUFSIZE (which in this case must be less than + INT_MAX) to COLUMN; otherwise, add mbsnwidth (BUF, BUFSIZE, 0) to + COLUMN. If an overflow occurs, or might occur but is undetectable, + return INT_MAX. Assume COLUMN is nonnegative. */ + +static inline int +add_column_width (int column, char const *buf, size_t bufsize) +{ + size_t width; + unsigned int remaining_columns = INT_MAX - column; + + if (buf) + { + if (INT_MAX / 2 <= bufsize) + return INT_MAX; + width = mbsnwidth (buf, bufsize, 0); + } + else + width = bufsize; + + return width <= remaining_columns ? column + width : INT_MAX; +} + +/* Set *LOC and adjust scanner cursor to account for token TOKEN of + size SIZE. */ + +void +location_compute (location *loc, boundary *cur, char const *token, size_t size) +{ + int line = cur->line; + int column = cur->column; + char const *p0 = token; + char const *p = token; + char const *lim = token + size; + + loc->start = *cur; + + for (p = token; p < lim; p++) + switch (*p) + { + case '\n': + line += line < INT_MAX; + column = 1; + p0 = p + 1; + break; + + case '\t': + column = add_column_width (column, p0, p - p0); + column = add_column_width (column, NULL, 8 - ((column - 1) & 7)); + p0 = p + 1; + break; + + default: + break; + } + + cur->line = line; + cur->column = column = add_column_width (column, p0, p - p0); + + loc->end = *cur; + + if (line == INT_MAX && loc->start.line != INT_MAX) + complain (loc, Wother, _("line number overflow")); + if (column == INT_MAX && loc->start.column != INT_MAX) + complain (loc, Wother, _("column number overflow")); +} + + +unsigned +location_print (location loc, FILE *out) +{ + unsigned res = 0; + int end_col = 0 != loc.end.column ? loc.end.column - 1 : 0; + res += fprintf (out, "%s", + quotearg_n_style (3, escape_quoting_style, loc.start.file)); + if (0 <= loc.start.line) + { + res += fprintf (out, ":%d", loc.start.line); + if (0 <= loc.start.column) + res += fprintf (out, ".%d", loc.start.column); + } + if (loc.start.file != loc.end.file) + { + res += fprintf (out, "-%s", + quotearg_n_style (3, escape_quoting_style, + loc.end.file)); + if (0 <= loc.end.line) + { + res += fprintf (out, ":%d", loc.end.line); + if (0 <= end_col) + res += fprintf (out, ".%d", end_col); + } + } + else if (0 <= loc.end.line) + { + if (loc.start.line < loc.end.line) + { + res += fprintf (out, "-%d", loc.end.line); + if (0 <= end_col) + res += fprintf (out, ".%d", end_col); + } + else if (0 <= end_col && loc.start.column < end_col) + res += fprintf (out, "-%d", end_col); + } + + return res; +} + + +/* Persistant data used by location_caret to avoid reopening and rereading the + same file all over for each error. */ +struct caret_info +{ + FILE *source; + size_t line; + size_t offset; +}; + +static struct caret_info caret_info = { NULL, 1, 0 }; + +void +cleanup_caret () +{ + if (caret_info.source) + fclose (caret_info.source); + caret_info.source = NULL; + caret_info.line = 1; + caret_info.offset = 0; +} + +void +location_caret (location loc, FILE *out) +{ + /* FIXME: find a way to support multifile locations, and only open once each + file. That would make the procedure future-proof. */ + if (! (caret_info.source + || (caret_info.source = fopen (loc.start.file, "r"))) + || loc.start.column == -1 || loc.start.line == -1) + return; + + /* If the line we want to quote is seekable (the same line as the previous + location), just seek it. If it was a previous line, we lost track of it, + so return to the start of file. */ + if (caret_info.line <= loc.start.line) + fseek (caret_info.source, caret_info.offset, SEEK_SET); + else + { + caret_info.line = 1; + caret_info.offset = 0; + fseek (caret_info.source, caret_info.offset, SEEK_SET); + } + + /* Advance to the line's position, keeping track of the offset. */ + while (caret_info.line < loc.start.line) + caret_info.line += getc (caret_info.source) == '\n'; + caret_info.offset = ftell (caret_info.source); + + /* Read the actual line. Don't update the offset, so that we keep a pointer + to the start of the line. */ + { + char c = getc (caret_info.source); + if (c != EOF) + { + /* Quote the file, indent by a single column. */ + putc (' ', out); + do + putc (c, out); + while ((c = getc (caret_info.source)) != EOF && c != '\n'); + putc ('\n', out); + + { + /* The caret of a multiline location ends with the first line. */ + size_t len = loc.start.line != loc.end.line + ? ftell (caret_info.source) - caret_info.offset + : loc.end.column; + int i; + + /* Print the carets (at least one), with the same indent as above.*/ + fprintf (out, " %*s", loc.start.column - 1, ""); + for (i = loc.start.column; i == loc.start.column || i < len; ++i) + putc ('^', out); + } + putc ('\n', out); + } + } +} + +void +boundary_set_from_string (boundary *bound, char *loc_str) +{ + /* Must search in reverse since the file name field may + * contain '.' or ':'. */ + char *delim = strrchr (loc_str, '.'); + aver (delim); + *delim = '\0'; + bound->column = atoi (delim+1); + delim = strrchr (loc_str, ':'); + aver (delim); + *delim = '\0'; + bound->line = atoi (delim+1); + bound->file = uniqstr_new (loc_str); +} diff --git a/contrib/tools/bison/src/location.h b/contrib/tools/bison/src/location.h new file mode 100644 index 0000000000..9c6e53c190 --- /dev/null +++ b/contrib/tools/bison/src/location.h @@ -0,0 +1,131 @@ +/* Locations for Bison + + Copyright (C) 2002, 2004-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef LOCATION_H_ +# define LOCATION_H_ + +# include <stdbool.h> +# include <stdio.h> +# include <string.h> /* strcmp */ + +# include "uniqstr.h" + +/* A boundary between two characters. */ +typedef struct +{ + /* The name of the file that contains the boundary. */ + uniqstr file; + + /* If nonnegative, the (origin-1) line that contains the boundary. + If this is INT_MAX, the line number has overflowed. + + Meaningless and not displayed if negative. + */ + int line; + + /* If nonnegative, the (origin-1) column just after the boundary. + This is neither a byte count, nor a character count; it is a + column count. If this is INT_MAX, the column number has + overflowed. + + Meaningless and not displayed if negative. + */ + int column; + +} boundary; + +/* Set the position of \a a. */ +static inline void +boundary_set (boundary *b, const char *f, int l, int c) +{ + b->file = f; + b->line = l; + b->column = c; +} + +/* Return -1, 0, 1, depending whether a is before, equal, or + after b. */ +static inline int +boundary_cmp (boundary a, boundary b) +{ + int res = strcmp (a.file, b.file); + if (!res) + res = a.line - b.line; + if (!res) + res = a.column - b.column; + return res; +} + +/* Return nonzero if A and B are equal boundaries. */ +static inline bool +equal_boundaries (boundary a, boundary b) +{ + return (a.column == b.column + && a.line == b.line + && UNIQSTR_EQ (a.file, b.file)); +} + +/* A location, that is, a region of source code. */ +typedef struct +{ + /* Boundary just before the location starts. */ + boundary start; + + /* Boundary just after the location ends. */ + boundary end; + +} location; + +# define GRAM_LTYPE location + +# define EMPTY_LOCATION_INIT {{NULL, 0, 0}, {NULL, 0, 0}} +extern location const empty_location; + +/* Set *LOC and adjust scanner cursor to account for token TOKEN of + size SIZE. */ +void location_compute (location *loc, + boundary *cur, char const *token, size_t size); + +/* Print location to file. + Return number of actually printed characters. + Warning: uses quotearg's slot 3. */ +unsigned location_print (location loc, FILE *out); + +/* Free any allocated ressources and close any open file handles that are + left-over by the usage of location_caret. */ +void cleanup_caret (void); + +/* Output to OUT the line and caret corresponding to location LOC. */ +void location_caret (location loc, FILE *out); + +/* Return -1, 0, 1, depending whether a is before, equal, or + after b. */ +static inline int +location_cmp (location a, location b) +{ + int res = boundary_cmp (a.start, b.start); + if (!res) + res = boundary_cmp (a.end, b.end); + return res; +} + +/* LOC_STR must be formatted as 'file:line.column', it will be modified. */ +void boundary_set_from_string (boundary *bound, char *loc_str); + +#endif /* ! defined LOCATION_H_ */ diff --git a/contrib/tools/bison/src/main.c b/contrib/tools/bison/src/main.c new file mode 100644 index 0000000000..f391a9417e --- /dev/null +++ b/contrib/tools/bison/src/main.c @@ -0,0 +1,226 @@ +/* Top level entry point of Bison. + + Copyright (C) 1984, 1986, 1989, 1992, 1995, 2000-2002, 2004-2013 Free + Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include <bitset_stats.h> +#include <bitset.h> +#include <configmake.h> +#include <progname.h> +#include <quotearg.h> +#include <timevar.h> + +#include "LR0.h" +#include "closeout.h" +#include "complain.h" +#include "conflicts.h" +#include "derives.h" +#include "files.h" +#include "getargs.h" +#include "gram.h" +#include "lalr.h" +#include "ielr.h" +#include "muscle-tab.h" +#include "nullable.h" +#include "output.h" +#include "print.h" +#include "print_graph.h" +#include "print-xml.h" +#include <quote.h> +#include "reader.h" +#include "reduce.h" +#include "scan-code.h" +#include "scan-gram.h" +#include "scan-skel.h" +#include "symtab.h" +#include "tables.h" +#include "uniqstr.h" + + +int +main (int argc, char *argv[]) +{ + set_program_name (argv[0]); + setlocale (LC_ALL, ""); +#if 0 + (void) bindtextdomain (PACKAGE, LOCALEDIR); + (void) bindtextdomain ("bison-runtime", LOCALEDIR); + (void) textdomain (PACKAGE); +#endif + + { + char const *cp = getenv ("LC_CTYPE"); + if (cp && STREQ (cp, "C")) + set_custom_quoting ("e_quoting_options, "'", "'"); + else + set_quoting_style ("e_quoting_options, locale_quoting_style); + } + + atexit (close_stdout); + + uniqstrs_new (); + muscle_init (); + complain_init (); + + getargs (argc, argv); + + timevar_report = trace_flag & trace_time; + init_timevar (); + timevar_start (TV_TOTAL); + + if (trace_flag & trace_bitsets) + bitset_stats_enable (); + + /* Read the input. Copy some parts of it to FGUARD, FACTION, FTABLE + and FATTRS. In file reader.c. The other parts are recorded in + the grammar; see gram.h. */ + + timevar_push (TV_READER); + reader (); + timevar_pop (TV_READER); + + if (complaint_status == status_complaint) + goto finish; + + /* Find useless nonterminals and productions and reduce the grammar. */ + timevar_push (TV_REDUCE); + reduce_grammar (); + timevar_pop (TV_REDUCE); + + /* Record other info about the grammar. In files derives and + nullable. */ + timevar_push (TV_SETS); + derives_compute (); + nullable_compute (); + timevar_pop (TV_SETS); + + /* Compute LR(0) parser states. See state.h for more info. */ + timevar_push (TV_LR0); + generate_states (); + timevar_pop (TV_LR0); + + /* Add lookahead sets to parser states. Except when LALR(1) is + requested, split states to eliminate LR(1)-relative + inadequacies. */ + ielr (); + + /* Find and record any conflicts: places where one token of + lookahead is not enough to disambiguate the parsing. In file + conflicts. Also resolve s/r conflicts based on precedence + declarations. */ + timevar_push (TV_CONFLICTS); + conflicts_solve (); + if (!muscle_percent_define_flag_if ("lr.keep-unreachable-state")) + { + state_number *old_to_new = xnmalloc (nstates, sizeof *old_to_new); + state_number nstates_old = nstates; + state_remove_unreachable_states (old_to_new); + lalr_update_state_numbers (old_to_new, nstates_old); + conflicts_update_state_numbers (old_to_new, nstates_old); + free (old_to_new); + } + conflicts_print (); + timevar_pop (TV_CONFLICTS); + + /* Compute the parser tables. */ + timevar_push (TV_ACTIONS); + tables_generate (); + timevar_pop (TV_ACTIONS); + + grammar_rules_useless_report (_("rule useless in parser due to conflicts")); + + print_precedence_warnings (); + + /* Output file names. */ + compute_output_file_names (); + + /* Output the detailed report on the grammar. */ + if (report_flag) + { + timevar_push (TV_REPORT); + print_results (); + timevar_pop (TV_REPORT); + } + + /* Output the graph. */ + if (graph_flag) + { + timevar_push (TV_GRAPH); + print_graph (); + timevar_pop (TV_GRAPH); + } + + /* Output xml. */ + if (xml_flag) + { + timevar_push (TV_XML); + print_xml (); + timevar_pop (TV_XML); + } + + /* Stop if there were errors, to avoid trashing previous output + files. */ + if (complaint_status == status_complaint) + goto finish; + + /* Lookahead tokens are no longer needed. */ + timevar_push (TV_FREE); + lalr_free (); + timevar_pop (TV_FREE); + + /* Output the tables and the parser to ftable. In file output. */ + timevar_push (TV_PARSER); + output (); + timevar_pop (TV_PARSER); + + timevar_push (TV_FREE); + nullable_free (); + derives_free (); + tables_free (); + states_free (); + reduce_free (); + conflicts_free (); + grammar_free (); + output_file_names_free (); + + /* The scanner memory cannot be released right after parsing, as it + contains things such as user actions, prologue, epilogue etc. */ + gram_scanner_free (); + muscle_free (); + uniqstrs_free (); + code_scanner_free (); + skel_scanner_free (); + quotearg_free (); + timevar_pop (TV_FREE); + + if (trace_flag & trace_bitsets) + bitset_stats_dump (stderr); + + finish: + + /* Stop timing and print the times. */ + timevar_stop (TV_TOTAL); + timevar_print (stderr); + + cleanup_caret (); + + return complaint_status ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/contrib/tools/bison/src/muscle-tab.c b/contrib/tools/bison/src/muscle-tab.c new file mode 100644 index 0000000000..ca63ed21ad --- /dev/null +++ b/contrib/tools/bison/src/muscle-tab.c @@ -0,0 +1,775 @@ +/* Muscle table manager for Bison. + + Copyright (C) 2001-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include <hash.h> + +#include "complain.h" +#include "files.h" +#include "getargs.h" +#include "muscle-tab.h" +#include "quote.h" + +muscle_kind +muscle_kind_new (char const *k) +{ + if (STREQ (k, "code")) + return muscle_code; + else if (STREQ (k, "keyword")) + return muscle_keyword; + else if (STREQ (k, "string")) + return muscle_string; + aver (0); +} + +char const * +muscle_kind_string (muscle_kind k) +{ + switch (k) + { + case muscle_code: return "code"; + case muscle_keyword: return "keyword"; + case muscle_string: return "string"; + } + aver (0); +} + + +/* A key-value pair, along with storage that can be reclaimed when + this pair is no longer needed. */ +typedef struct +{ + char const *key; + char const *value; + char *storage; + muscle_kind kind; +} muscle_entry; + + +/* The name of muscle for the %define variable VAR (corresponding to + FIELD, if defined). */ +static uniqstr +muscle_name (char const *var, char const *field) +{ + if (field) + return uniqstr_vsprintf("percent_define_%s(%s)", field, var); + else + return uniqstr_vsprintf("percent_define(%s)", var); +} + +/* An obstack used to create some entries. */ +struct obstack muscle_obstack; + +/* Initial capacity of muscles hash table. */ +#define HT_INITIAL_CAPACITY 257 + +static struct hash_table *muscle_table = NULL; + +static bool +hash_compare_muscles (void const *x, void const *y) +{ + muscle_entry const *m1 = x; + muscle_entry const *m2 = y; + return STREQ (m1->key, m2->key); +} + +static size_t +hash_muscle (const void *x, size_t tablesize) +{ + muscle_entry const *m = x; + return hash_string (m->key, tablesize); +} + +/* Create a fresh muscle name KEY, and insert in the hash table. */ +static void * +muscle_entry_new (char const *key) +{ + muscle_entry *res = xmalloc (sizeof *res); + res->key = key; + res->value = NULL; + res->storage = NULL; + if (!hash_insert (muscle_table, res)) + xalloc_die (); + return res; +} + +static void +muscle_entry_free (void *entry) +{ + muscle_entry *mentry = entry; + free (mentry->storage); + free (mentry); +} + +void +muscle_init (void) +{ + /* Initialize the muscle obstack. */ + obstack_init (&muscle_obstack); + + muscle_table = hash_initialize (HT_INITIAL_CAPACITY, NULL, hash_muscle, + hash_compare_muscles, muscle_entry_free); + + /* Version and input file. */ + MUSCLE_INSERT_STRING ("version", VERSION); +} + + +void +muscle_free (void) +{ + hash_free (muscle_table); + obstack_free (&muscle_obstack, NULL); +} + +/* Look for the muscle named KEY. Return NULL if does not exist. */ +static +muscle_entry * +muscle_lookup (char const *key) +{ + muscle_entry probe; + probe.key = key; + return hash_lookup (muscle_table, &probe); +} + + +void +muscle_insert (char const *key, char const *value) +{ + muscle_entry *entry = muscle_lookup (key); + if (entry) + free (entry->storage); + else + /* First insertion in the hash. */ + entry = muscle_entry_new (key); + entry->value = value; + entry->storage = NULL; +} + + +/* Append VALUE to the current value of KEY. If KEY did not already + exist, create it. Use MUSCLE_OBSTACK. De-allocate the previously + associated value. Copy VALUE and SEPARATOR. If VALUE does not end + with TERMINATOR, append one. */ + +static void +muscle_grow (const char *key, const char *val, + const char *separator, const char *terminator) +{ + muscle_entry *entry = muscle_lookup (key); + size_t vals = strlen (val); + size_t terms = strlen (terminator); + + if (entry) + { + obstack_sgrow (&muscle_obstack, entry->value); + obstack_sgrow (&muscle_obstack, separator); + free (entry->storage); + } + else + entry = muscle_entry_new (key); + + obstack_sgrow (&muscle_obstack, val); + + if (terms <= vals + && STRNEQ (val + vals - terms, terminator)) + obstack_sgrow (&muscle_obstack, terminator); + + { + char *new_val = obstack_finish0 (&muscle_obstack); + entry->value = entry->storage = xstrdup (new_val); + obstack_free (&muscle_obstack, new_val); + } +} + +/*------------------------------------------------------------------. +| Using muscle_grow, append a synchronization line for the location | +| LOC to the current value of KEY. | +`------------------------------------------------------------------*/ + +static void +muscle_syncline_grow (char const *key, location loc) +{ + char *extension = NULL; + obstack_printf (&muscle_obstack, "]b4_syncline(%d, ", loc.start.line); + obstack_quote (&muscle_obstack, + quotearg_style (c_quoting_style, loc.start.file)); + obstack_sgrow (&muscle_obstack, ")["); + extension = obstack_finish0 (&muscle_obstack); + muscle_grow (key, extension, "", ""); + obstack_free (&muscle_obstack, extension); +} + +/*------------------------------------------------------------------. +| Append VALUE to the current value of KEY, using muscle_grow. But | +| in addition, issue a synchronization line for the location LOC | +| using muscle_syncline_grow. | +`------------------------------------------------------------------*/ + +void +muscle_code_grow (const char *key, const char *val, location loc) +{ + muscle_syncline_grow (key, loc); + muscle_grow (key, val, "\n", "\n"); +} + + +void +muscle_pair_list_grow (const char *muscle, + const char *a1, const char *a2) +{ + char *pair; + obstack_sgrow (&muscle_obstack, "["); + obstack_quote (&muscle_obstack, a1); + obstack_sgrow (&muscle_obstack, ", "); + obstack_quote (&muscle_obstack, a2); + obstack_sgrow (&muscle_obstack, "]"); + pair = obstack_finish0 (&muscle_obstack); + muscle_grow (muscle, pair, ",\n", ""); + obstack_free (&muscle_obstack, pair); +} + + +char const * +muscle_find_const (char const *key) +{ + muscle_entry *entry = muscle_lookup (key); + return entry ? entry->value : NULL; +} + + +char * +muscle_find (char const *key) +{ + muscle_entry *entry = muscle_lookup (key); + if (entry) + { + aver (entry->value == entry->storage); + return entry->storage; + } + return NULL; +} + + +/* In the format 'file_name:line.column', append BOUND to MUSCLE. Use + digraphs for special characters in the file name. */ + +static void +muscle_boundary_grow (char const *key, boundary bound) +{ + char *extension; + obstack_sgrow (&muscle_obstack, "[["); + obstack_escape (&muscle_obstack, bound.file); + obstack_printf (&muscle_obstack, ":%d.%d]]", bound.line, bound.column); + extension = obstack_finish0 (&muscle_obstack); + muscle_grow (key, extension, "", ""); + obstack_free (&muscle_obstack, extension); +} + + +/* In the format '[[file_name:line.column]], [[file_name:line.column]]', + append LOC to MUSCLE. Use digraphs for special characters in each + file name. */ + +static void +muscle_location_grow (char const *key, location loc) +{ + muscle_boundary_grow (key, loc.start); + muscle_grow (key, "", ", ", ""); + muscle_boundary_grow (key, loc.end); +} + +#define COMMON_DECODE(Value) \ + case '$': \ + aver (*++(Value) == ']'); \ + aver (*++(Value) == '['); \ + obstack_sgrow (&muscle_obstack, "$"); \ + break; \ + case '@': \ + switch (*++(Value)) \ + { \ + case '@': obstack_sgrow (&muscle_obstack, "@" ); break; \ + case '{': obstack_sgrow (&muscle_obstack, "[" ); break; \ + case '}': obstack_sgrow (&muscle_obstack, "]" ); break; \ + default: aver (false); break; \ + } \ + break; \ + default: \ + obstack_1grow (&muscle_obstack, *(Value)); \ + break; + +/* Reverse of obstack_escape. */ +static char * +string_decode (char const *key) +{ + char const *value = muscle_find_const (key); + char *value_decoded; + char *result; + + if (!value) + return NULL; + do { + switch (*value) + { + COMMON_DECODE (value) + case '[': + case ']': + aver (false); + break; + } + } while (*value++); + value_decoded = obstack_finish (&muscle_obstack); + result = xstrdup (value_decoded); + obstack_free (&muscle_obstack, value_decoded); + return result; +} + +/* Reverse of muscle_location_grow. */ +static location +location_decode (char const *value) +{ + location loc; + aver (value); + aver (*value == '['); + aver (*++value == '['); + while (*++value) + switch (*value) + { + COMMON_DECODE (value) + case '[': + aver (false); + break; + case ']': + { + char *boundary_str; + aver (*++value == ']'); + boundary_str = obstack_finish0 (&muscle_obstack); + switch (*++value) + { + case ',': + boundary_set_from_string (&loc.start, boundary_str); + obstack_free (&muscle_obstack, boundary_str); + aver (*++value == ' '); + aver (*++value == '['); + aver (*++value == '['); + break; + case '\0': + boundary_set_from_string (&loc.end, boundary_str); + obstack_free (&muscle_obstack, boundary_str); + return loc; + break; + default: + aver (false); + break; + } + } + break; + } + aver (false); + return loc; +} + +void +muscle_user_name_list_grow (char const *key, char const *user_name, + location loc) +{ + muscle_grow (key, "[[[[", ",", ""); + muscle_grow (key, user_name, "", ""); + muscle_grow (key, "]], ", "", ""); + muscle_location_grow (key, loc); + muscle_grow (key, "]]", "", ""); +} + + +/** Return an allocated string that represents the %define directive + that performs the assignment. + + @param assignment "VAR", or "VAR=VAL". + @param value default value if VAL \a assignment has no '='. + + For instance: + "foo", NULL => "%define foo" + "foo", "baz" => "%define foo baz" + "foo=bar", NULL => "%define foo bar" + "foo=bar", "baz" => "%define foo bar" + "foo=", NULL => "%define foo" + "foo=", "baz" => "%define foo" + */ + +static +char * +define_directive (char const *assignment, char const *value) +{ + char *eq = strchr (assignment, '='); + char const *fmt = !eq && value && *value ? "%%define %s %s" : "%%define %s"; + char *res = xmalloc (strlen (fmt) + strlen (assignment) + + (value ? strlen (value) : 0)); + sprintf (res, fmt, assignment, value); + eq = strchr (res, '='); + if (eq) + *eq = eq[1] ? ' ' : '\0'; + return res; +} + +/** If the \a variable name is obsolete, return the name to use, + * otherwise \a variable. If the \a value is obsolete, update it too. + * + * Allocates the returned value. */ +static +char * +muscle_percent_variable_update (char const *variable, location variable_loc, + char const **value) +{ + typedef struct + { + const char *obsolete; + const char *updated; + } conversion_type; + const conversion_type conversion[] = + { + { "api.push_pull", "api.push-pull", }, + { "api.tokens.prefix", "api.token.prefix", }, + { "lex_symbol", "api.token.constructor", }, + { "location_type", "api.location.type", }, + { "lr.default-reductions", "lr.default-reduction", }, + { "lr.keep-unreachable-states", "lr.keep-unreachable-state", }, + { "lr.keep_unreachable_states", "lr.keep-unreachable-state", }, + { "namespace", "api.namespace", }, + { "stype", "api.value.type", }, + { "variant=", "api.value.type=variant", }, + { "variant=true", "api.value.type=variant", }, + { NULL, NULL, } + }; + conversion_type const *c; + char* res; + char* eq2; + for (c = conversion; c->obsolete; ++c) + { + char const *eq = strchr (c->obsolete, '='); + if (eq + ? (!strncmp (c->obsolete, variable, eq - c->obsolete) + && STREQ (eq + 1, *value)) + : STREQ (c->obsolete, variable)) + { + char *old = define_directive (c->obsolete, *value); + char *upd = define_directive (c->updated, *value); + deprecated_directive (&variable_loc, old, upd); + free (old); + free (upd); + res = xstrdup (c->updated); + { + eq2 = strchr (res, '='); + if (eq2) + { + *eq2 = '\0'; + *value = eq2 + 1; + } + } + return res; + } + } + return xstrdup (variable); +} + +void +muscle_percent_define_insert (char const *var, location variable_loc, + muscle_kind kind, + char const *value, + muscle_percent_define_how how) +{ + /* Backward compatibility. */ + char *variable = muscle_percent_variable_update (var, variable_loc, &value); + uniqstr name = muscle_name (variable, NULL); + uniqstr loc_name = muscle_name (variable, "loc"); + uniqstr syncline_name = muscle_name (variable, "syncline"); + uniqstr how_name = muscle_name (variable, "how"); + uniqstr kind_name = muscle_name (variable, "kind"); + location loc; + + /* Command-line options are processed before the grammar file. */ + if (how == MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE + && muscle_find_const (name)) + { + muscle_percent_define_how how_old = atoi (muscle_find_const (how_name)); + unsigned i = 0; + if (how_old == MUSCLE_PERCENT_DEFINE_F) + goto end; + complain_indent (&variable_loc, complaint, &i, + _("%%define variable %s redefined"), + quote (variable)); + i += SUB_INDENT; + loc = muscle_percent_define_get_loc (variable); + complain_indent (&loc, complaint, &i, _("previous definition")); + } + + MUSCLE_INSERT_STRING (name, value); + muscle_insert (loc_name, ""); + muscle_location_grow (loc_name, variable_loc); + muscle_insert (syncline_name, ""); + muscle_syncline_grow (syncline_name, variable_loc); + muscle_user_name_list_grow ("percent_define_user_variables", variable, + variable_loc); + MUSCLE_INSERT_INT (how_name, how); + MUSCLE_INSERT_STRING (kind_name, muscle_kind_string (kind)); + end: + free (variable); +} + +/* This is used for backward compatibility, e.g., "%define api.pure" + supersedes "%pure-parser". */ +void +muscle_percent_define_ensure (char const *variable, location loc, + bool value) +{ + uniqstr name = muscle_name (variable, NULL); + char const *val = value ? "" : "false"; + + /* Don't complain is VARIABLE is already defined, but be sure to set + its value to VAL. */ + if (!muscle_find_const (name) + || muscle_percent_define_flag_if (variable) != value) + muscle_percent_define_insert (variable, loc, muscle_keyword, val, + MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); +} + +/* Mark %define VARIABLE as used. */ +static void +muscle_percent_define_use (char const *variable) +{ + muscle_insert (muscle_name (variable, "bison_variables"), ""); +} + +/* The value of %define variable VARIABLE (corresponding to FIELD, if + defined). Do not register as used, but diagnose unset variables. */ + +static +char const * +muscle_percent_define_get_raw (char const *variable, char const *field) +{ + uniqstr name = muscle_name (variable, field); + char const *res = muscle_find_const (name); + if (!res) + complain (NULL, fatal, _("%s: undefined %%define variable %s"), + "muscle_percent_define_get_raw", quote (variable)); + return res; +} + +char * +muscle_percent_define_get (char const *variable) +{ + uniqstr name = muscle_name (variable, NULL); + char *value = string_decode (name); + if (!value) + value = xstrdup (""); + muscle_percent_define_use (variable); + return value; +} + +/* The kind of VARIABLE. An error if undefined. */ +static muscle_kind +muscle_percent_define_get_kind (char const *variable) +{ + return muscle_kind_new (muscle_percent_define_get_raw (variable, "kind")); +} + +/* Check the kind of VARIABLE. An error if undefined. */ +static void +muscle_percent_define_check_kind (char const *variable, muscle_kind kind) +{ + if (muscle_percent_define_get_kind (variable) != kind) + { + location loc = muscle_percent_define_get_loc (variable); + switch (kind) + { + case muscle_code: + complain (&loc, Wdeprecated, + "%%define variable '%s' requires '{...}' values", + variable); + break; + case muscle_keyword: + complain (&loc, Wdeprecated, + "%%define variable '%s' requires keyword values", + variable); + break; + case muscle_string: + complain (&loc, Wdeprecated, + "%%define variable '%s' requires '\"...\"' values", + variable); + break; + } + } +} + + +location +muscle_percent_define_get_loc (char const *variable) +{ + return location_decode (muscle_percent_define_get_raw (variable, "loc")); +} + +char const * +muscle_percent_define_get_syncline (char const *variable) +{ + return muscle_percent_define_get_raw (variable, "syncline"); +} + +bool +muscle_percent_define_ifdef (char const *variable) +{ + if (muscle_find_const (muscle_name (variable, NULL))) + { + muscle_percent_define_use (variable); + return true; + } + else + return false; +} + +bool +muscle_percent_define_flag_if (char const *variable) +{ + uniqstr invalid_boolean_name = muscle_name (variable, "invalid_boolean"); + bool result = false; + location loc; + + if (muscle_percent_define_ifdef (variable)) + { + char *value = muscle_percent_define_get (variable); + muscle_percent_define_check_kind (variable, muscle_keyword); + if (value[0] == '\0' || STREQ (value, "true")) + result = true; + else if (STREQ (value, "false")) + result = false; + else if (!muscle_find_const (invalid_boolean_name)) + { + muscle_insert (invalid_boolean_name, ""); + loc = muscle_percent_define_get_loc (variable); + complain (&loc, complaint, + _("invalid value for %%define Boolean variable %s"), + quote (variable)); + } + free (value); + } + else + complain (NULL, fatal, _("%s: undefined %%define variable %s"), + "muscle_percent_define_flag", quote (variable)); + + return result; +} + +void +muscle_percent_define_default (char const *variable, char const *value) +{ + uniqstr name = muscle_name (variable, NULL); + if (!muscle_find_const (name)) + { + MUSCLE_INSERT_STRING (name, value); + MUSCLE_INSERT_STRING (muscle_name (variable, "kind"), "keyword"); + { + uniqstr loc_name = muscle_name (variable, "loc"); + location loc; + loc.start.file = loc.end.file = "<default value>"; + loc.start.line = loc.end.line = -1; + loc.start.column = loc.end.column = -1; + muscle_insert (loc_name, ""); + muscle_location_grow (loc_name, loc); + } + muscle_insert (muscle_name (variable, "syncline"), ""); + } +} + +void +muscle_percent_define_check_values (char const * const *values) +{ + for (; *values; ++values) + { + char const * const *variablep = values; + uniqstr name = muscle_name (*variablep, NULL); + char *value = string_decode (name); + muscle_percent_define_check_kind (*variablep, muscle_keyword); + if (value) + { + for (++values; *values; ++values) + { + if (STREQ (value, *values)) + break; + } + if (!*values) + { + unsigned i = 0; + location loc = muscle_percent_define_get_loc (*variablep); + complain_indent (&loc, complaint, &i, + _("invalid value for %%define variable %s: %s"), + quote (*variablep), quote_n (1, value)); + i += SUB_INDENT; + for (values = variablep + 1; *values; ++values) + complain_indent (&loc, complaint | no_caret | silent, &i, + _("accepted value: %s"), quote (*values)); + } + else + { + while (*values) + ++values; + } + free (value); + } + else + complain (NULL, fatal, _("%s: undefined %%define variable %s"), + "muscle_percent_define_check_values", quote (*variablep)); + } +} + +void +muscle_percent_code_grow (char const *qualifier, location qualifier_loc, + char const *code, location code_loc) +{ + char const *name = uniqstr_vsprintf("percent_code(%s)", qualifier); + muscle_code_grow (name, code, code_loc); + muscle_user_name_list_grow ("percent_code_user_qualifiers", qualifier, + qualifier_loc); +} + + +/*------------------------------------------------. +| Output the definition of ENTRY as a m4_define. | +`------------------------------------------------*/ + +static inline bool +muscle_m4_output (muscle_entry *entry, FILE *out) +{ + fprintf (out, + "m4_define([b4_%s],\n" + "[[%s]])\n\n\n", entry->key, entry->value); + return true; +} + +static bool +muscle_m4_output_processor (void *entry, void *out) +{ + return muscle_m4_output (entry, out); +} + + +void +muscles_m4_output (FILE *out) +{ + hash_do_for_each (muscle_table, muscle_m4_output_processor, out); +} diff --git a/contrib/tools/bison/src/muscle-tab.h b/contrib/tools/bison/src/muscle-tab.h new file mode 100644 index 0000000000..2150327ba6 --- /dev/null +++ b/contrib/tools/bison/src/muscle-tab.h @@ -0,0 +1,218 @@ +/* Muscle table manager for Bison, + + Copyright (C) 2001-2003, 2006-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef MUSCLE_TAB_H_ +# define MUSCLE_TAB_H_ + +# include <quotearg.h> +# include <obstack.h> + +# include "location.h" + +/* The kind of value associated to this muscle, depending on the + syntax of the value: keyword (no delimiter, e.g., true), string + (double quotes, e.g., "foo.h"), or code (braces, e.g., {int}). */ +typedef enum +{ + muscle_code, + muscle_keyword, + muscle_string +} muscle_kind; + +/* Conversion from string. */ +muscle_kind muscle_kind_new (char const *k); + +/* Conversion to string. */ +char const *muscle_kind_string (muscle_kind k); + + +/* Create the MUSCLE_TABLE, and initialize it with default values. + Also set up the MUSCLE_OBSTACK. */ +void muscle_init (void); + +/* Insert (KEY, VALUE). If KEY already existed, overwrite the + previous value. Otherwise create as a muscle_string type. */ +void muscle_insert (char const *key, char const *value); + +/* Find the value of muscle KEY. Unlike MUSCLE_FIND, this is always + reliable to determine whether KEY has a value. */ +char const *muscle_find_const (char const *key); + +/* Find the value of muscle KEY. Abort if muscle_insert was invoked + more recently than muscle_grow for KEY since muscle_find can't + return a char const *. */ +char *muscle_find (char const *key); + +/* Free all the memory consumed by the muscle machinery only. */ +void muscle_free (void); + + +/* An obstack dedicated to receive muscle keys and values. */ +extern struct obstack muscle_obstack; + +# define MUSCLE_INSERT_BOOL(Key, Value) \ + do { \ + int v__ = Value; \ + MUSCLE_INSERT_INT (Key, v__); \ + } while (0) + +# define MUSCLE_INSERTF(Key, Format, Value) \ + do { \ + obstack_printf (&muscle_obstack, Format, Value); \ + muscle_insert (Key, obstack_finish0 (&muscle_obstack)); \ + } while (0) + +# define MUSCLE_INSERT_INT(Key, Value) \ + MUSCLE_INSERTF (Key, "%d", Value) + +# define MUSCLE_INSERT_LONG_INT(Key, Value) \ + MUSCLE_INSERTF (Key, "%ld", Value) + +/* Key -> Value, but don't apply escaping to Value. */ +# define MUSCLE_INSERT_STRING_RAW(Key, Value) \ + MUSCLE_INSERTF (Key, "%s", Value) + +/* Key -> Value, applying M4 escaping to Value. */ +# define MUSCLE_INSERT_STRING(Key, Value) \ + do { \ + obstack_escape (&muscle_obstack, Value); \ + muscle_insert (Key, obstack_finish0 (&muscle_obstack)); \ + } while (0) + +/* Key -> Value, applying C escaping to Value (and then M4). */ +# define MUSCLE_INSERT_C_STRING(Key, Value) \ + MUSCLE_INSERT_STRING (Key, quotearg_style (c_quoting_style, Value)) + + +/* Append VALUE to the current value of KEY, using muscle_grow. But + in addition, issue a synchronization line for the location LOC. + Be sure to append on a new line. */ +void muscle_code_grow (const char *key, const char *value, location loc); + + +/* MUSCLE is an M4 list of pairs. Create or extend it with the pair + (A1, A2) after escaping both values with digraphs. Note that because the + muscle values are output *double* quoted, one needs to strip the first level + of quotes to reach the list itself. */ +void muscle_pair_list_grow (const char *muscle, + const char *a1, const char *a2); + +/* Grow KEY for the occurrence of the name USER_NAME at LOC appropriately for + use with b4_check_user_names in ../data/bison.m4. USER_NAME is not escaped + with digraphs, so it must not contain '[' or ']'. */ +void muscle_user_name_list_grow (char const *key, char const *user_name, + location loc); + +/* Indicates whether a variable's value was specified with -D/--define, with + -F/--force-define, or in the grammar file. */ +typedef enum { + MUSCLE_PERCENT_DEFINE_D = 0, + MUSCLE_PERCENT_DEFINE_F, + MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE +} muscle_percent_define_how; + +/* Define the muscles for %define variable VARIABLE with VALUE specified + at VARIABLE_LOC in the manner HOW unless it was specified in the + grammar file while the previous definition for VARIABLE was specified + with -F/--force-define. Complain if a previous definition is being + overridden and the new definition is specified in the grammar file. + (These rules support the documented behavior as long as command-line + definitions are processed before grammar file definitions.) Record + this as a user occurrence of VARIABLE by invoking + muscle_user_name_list_grow. */ +void muscle_percent_define_insert (char const *variable, location variable_loc, + muscle_kind kind, + char const *value, + muscle_percent_define_how how); + +/* Make sure that VARIABLE is set to the boolean VALUE. Warn on mismatches + only, but accept repeated declaration. Used for backward compatibility + between old directives such as %pure-parser, and the recommended use of + variables (%define api.pure). */ +void muscle_percent_define_ensure (char const *variable, location variable_loc, + bool value); + +/* Mimic b4_percent_define_get in ../data/bison.m4 exactly. That is, if the + %define variable VARIABLE is defined, return its value. Otherwise, return + the empty string. Also, record Bison's usage of VARIABLE by defining + b4_percent_define_bison_variables(VARIABLE). The caller is responsible for + freeing the memory of the returned string. */ +char *muscle_percent_define_get (char const *variable); + +/* Mimic muscle_percent_define_get_loc in ../data/bison.m4 exactly. That is, + if the %define variable VARIABLE is undefined, complain fatally since that's + a Bison error. Otherwise, return its definition location in a form + approriate for the first argument of warn_at, complain_at, or fatal_at. + Don't record this as a Bison usage of VARIABLE as there's no reason to + suspect that the user-supplied value has yet influenced the output. */ +location muscle_percent_define_get_loc (char const *variable); + +/* Mimic muscle_percent_define_get_syncline in ../data/bison.m4 exactly. That + is, if the %define variable VARIABLE is undefined, complain fatally since + that's a Bison error. Otherwise, return its definition location as a + b4_syncline invocation. Don't record this as a Bison usage of VARIABLE as + there's no reason to suspect that the user-supplied value has yet influenced + the output. */ +char const *muscle_percent_define_get_syncline (char const *variable); + +/* Mimic b4_percent_define_ifdef in ../data/bison.m4 exactly. That is, if the + %define variable VARIABLE is defined, return true. Otherwise, return false. + Also, record Bison's usage of VARIABLE by defining + b4_percent_define_bison_variables(VARIABLE). */ +bool muscle_percent_define_ifdef (char const *variable); + +/* Mimic b4_percent_define_flag_if in ../data/bison.m4 exactly. That is, if + the %define variable VARIABLE is defined to "" or "true", return true. If + it is defined to "false", return false. Complain if it is undefined (a + Bison error since the default value should have been set already) or defined + to any other value (possibly a user error). Also, record Bison's usage of + VARIABLE by defining b4_percent_define_bison_variables(VARIABLE). */ +bool muscle_percent_define_flag_if (char const *variable); + +/* Mimic b4_percent_define_default in ../data/bison.m4 exactly. That is, if + the %define variable VARIABLE is undefined, set its value to VALUE. + Don't record this as a Bison usage of VARIABLE as there's no reason to + suspect that the value has yet influenced the output. */ +void muscle_percent_define_default (char const *variable, char const *value); + +/* Mimic b4_percent_define_check_values in ../data/bison.m4 exactly except that + the VALUES structure is more appropriate for C. That is, VALUES points to a + list of strings that is partitioned into sublists by NULL's, one terminating + each sublist. The last sublist is followed by a second NULL. For each + sublist, the first string is the name of a %define variable, and all + remaining strings in that sublist are the valid values for that variable. + Complain if such a variable is undefined (a Bison error since the default + value should have been set already) or defined to any other value (possibly + a user error). Don't record this as a Bison usage of the variable as + there's no reason to suspect that the value has yet influenced the + output. */ +void muscle_percent_define_check_values (char const * const *values); + +/* Grow the muscle for the %code qualifier QUALIFIER appearing at + QUALIFIER_LOC with code CODE appearing at CODE_LOC. Record this as a + user occurrence of QUALIFIER by invoking + muscle_user_name_list_grow. */ +void muscle_percent_code_grow (char const *qualifier, location qualifier_loc, + char const *code, location code_loc); + +/* Output the definition of all the current muscles into a list of + m4_defines. */ +void muscles_m4_output (FILE *out); + +#endif /* not MUSCLE_TAB_H_ */ diff --git a/contrib/tools/bison/src/named-ref.c b/contrib/tools/bison/src/named-ref.c new file mode 100644 index 0000000000..1693767918 --- /dev/null +++ b/contrib/tools/bison/src/named-ref.c @@ -0,0 +1,46 @@ +/* Named symbol references for Bison + + Copyright (C) 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include "named-ref.h" + +named_ref * +named_ref_new (uniqstr id, location loc) +{ + named_ref *res = xmalloc (sizeof *res); + + res->id = id; + res->loc = loc; + + return res; +} + +named_ref * +named_ref_copy (const named_ref *r) +{ + return named_ref_new (r->id, r->loc); +} + +void +named_ref_free (named_ref *r) +{ + free (r); +} diff --git a/contrib/tools/bison/src/named-ref.h b/contrib/tools/bison/src/named-ref.h new file mode 100644 index 0000000000..84d02d7adb --- /dev/null +++ b/contrib/tools/bison/src/named-ref.h @@ -0,0 +1,46 @@ +/* Named symbol references for Bison + + Copyright (C) 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef NAMED_REF_H_ +# define NAMED_REF_H_ + +# include "location.h" +# include "uniqstr.h" + +/* Named reference object. Keeps information about + a symbolic name of a symbol in a rule. */ +typedef struct named_ref +{ + /* Symbolic named given by user. */ + uniqstr id; + + /* Location of the symbolic name. Not including brackets. */ + location loc; +} named_ref; + +/* Allocate a named reference object. */ +named_ref *named_ref_new (uniqstr id, location loc); + +/* Allocate and return a copy. */ +named_ref *named_ref_copy (const named_ref *r); + +/* Free a named reference object. */ +void named_ref_free (named_ref *r); + +#endif /* !NAMED_REF_H_ */ diff --git a/contrib/tools/bison/src/nullable.c b/contrib/tools/bison/src/nullable.c new file mode 100644 index 0000000000..a150f5f5c7 --- /dev/null +++ b/contrib/tools/bison/src/nullable.c @@ -0,0 +1,142 @@ +/* Calculate which nonterminals can expand into the null string for Bison. + + Copyright (C) 1984, 1989, 2000-2006, 2009-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + + +/* Set up NULLABLE, a vector saying which nonterminals can expand into + the null string. NULLABLE[I - NTOKENS] is nonzero if symbol I can + do so. */ + +#include <config.h> +#include "system.h" + +#include "getargs.h" +#include "gram.h" +#include "nullable.h" +#include "reduce.h" +#include "symtab.h" + +/* Linked list of rules. */ +typedef struct rule_list +{ + struct rule_list *next; + rule *value; +} rule_list; + +bool *nullable = NULL; + +static void +nullable_print (FILE *out) +{ + int i; + fputs ("NULLABLE\n", out); + for (i = ntokens; i < nsyms; i++) + fprintf (out, " %s: %s\n", symbols[i]->tag, + nullable[i - ntokens] ? "yes" : "no"); + fputs ("\n\n", out); +} + +void +nullable_compute (void) +{ + rule_number ruleno; + symbol_number *s1; + symbol_number *s2; + rule_list *p; + + symbol_number *squeue = xnmalloc (nvars, sizeof *squeue); + size_t *rcount = xcalloc (nrules, sizeof *rcount); + /* RITEM contains all the rules, including useless productions. + Hence we must allocate room for useless nonterminals too. */ + rule_list **rsets = xcalloc (nvars, sizeof *rsets); + /* This is said to be more elements than we actually use. + Supposedly NRITEMS - NRULES is enough. But why take the risk? */ + rule_list *relts = xnmalloc (nritems + nvars + 1, sizeof *relts); + + nullable = xcalloc (nvars, sizeof *nullable); + + s1 = s2 = squeue; + p = relts; + + for (ruleno = 0; ruleno < nrules; ++ruleno) + if (rules[ruleno].useful) + { + rule *rules_ruleno = &rules[ruleno]; + if (rules_ruleno->rhs[0] >= 0) + { + /* This rule has a non empty RHS. */ + item_number *rp = NULL; + bool any_tokens = false; + for (rp = rules_ruleno->rhs; *rp >= 0; ++rp) + if (ISTOKEN (*rp)) + any_tokens = true; + + /* This rule has only nonterminals: schedule it for the second + pass. */ + if (!any_tokens) + for (rp = rules_ruleno->rhs; *rp >= 0; ++rp) + { + rcount[ruleno]++; + p->next = rsets[*rp - ntokens]; + p->value = rules_ruleno; + rsets[*rp - ntokens] = p; + p++; + } + } + else + { + /* This rule has an empty RHS. */ + aver (item_number_as_rule_number (rules_ruleno->rhs[0]) + == ruleno); + if (rules_ruleno->useful + && ! nullable[rules_ruleno->lhs->number - ntokens]) + { + nullable[rules_ruleno->lhs->number - ntokens] = true; + *s2++ = rules_ruleno->lhs->number; + } + } + } + + while (s1 < s2) + for (p = rsets[*s1++ - ntokens]; p; p = p->next) + { + rule *r = p->value; + if (--rcount[r->number] == 0) + if (r->useful && ! nullable[r->lhs->number - ntokens]) + { + nullable[r->lhs->number - ntokens] = true; + *s2++ = r->lhs->number; + } + } + + free (squeue); + free (rcount); + free (rsets); + free (relts); + + if (trace_flag & trace_sets) + nullable_print (stderr); +} + + +void +nullable_free (void) +{ + free (nullable); +} diff --git a/contrib/tools/bison/src/nullable.h b/contrib/tools/bison/src/nullable.h new file mode 100644 index 0000000000..63a8ae3f14 --- /dev/null +++ b/contrib/tools/bison/src/nullable.h @@ -0,0 +1,32 @@ +/* Part of the bison parser generator, + + Copyright (C) 2000, 2002, 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef NULLABLE_H_ +# define NULLABLE_H_ + +/* A vector saying which nonterminals can expand into the null string. + NULLABLE[I - NTOKENS] is nonzero if symbol I can do so. */ +extern bool *nullable; + +/* Set up NULLABLE. */ +extern void nullable_compute (void); + +/* Free NULLABLE. */ +extern void nullable_free (void); +#endif /* !NULLABLE_H_ */ diff --git a/contrib/tools/bison/src/output.c b/contrib/tools/bison/src/output.c new file mode 100644 index 0000000000..9f08095c6b --- /dev/null +++ b/contrib/tools/bison/src/output.c @@ -0,0 +1,740 @@ +/* Output the generated parsing program for Bison. + + Copyright (C) 1984, 1986, 1989, 1992, 2000-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include <concat-filename.h> +#include <configmake.h> +#include <filename.h> +#include <get-errno.h> +#include <quotearg.h> +#include <spawn-pipe.h> +#include <timevar.h> +#include <wait-process.h> + +#include "complain.h" +#include "files.h" +#include "getargs.h" +#include "gram.h" +#include "muscle-tab.h" +#include "output.h" +#include "reader.h" +#include "scan-code.h" /* max_left_semantic_context */ +#include "scan-skel.h" +#include "symtab.h" +#include "tables.h" + +#include "uniqstr.h" + +#include <contrib/tools/bison/arcadia_root.h> + +#ifndef M4 +#define M4 (m4_path) +#endif + +#ifndef PKGDATADIR +#define STR(a) XSTR(a) +#define XSTR(a) #a + +const char* +default_pkgdatadir() +{ + const char* arc_path = getenv("ARCADIA_ROOT_DISTBUILD"); + if (arc_path == NULL) + arc_path = ArcadiaRoot(); + return uniqstr_vsprintf("%s/" STR(BISON_DATA_DIR), arc_path); +} +#define PKGDATADIR (default_pkgdatadir()) +#endif + +static struct obstack format_obstack; + + +/*-------------------------------------------------------------------. +| Create a function NAME which associates to the muscle NAME the | +| result of formatting the FIRST and then TABLE_DATA[BEGIN..END[ (of | +| TYPE), and to the muscle NAME_max, the max value of the | +| TABLE_DATA. | +`-------------------------------------------------------------------*/ + + +#define GENERATE_MUSCLE_INSERT_TABLE(Name, Type) \ + \ +static void \ +Name (char const *name, \ + Type *table_data, \ + Type first, \ + int begin, \ + int end) \ +{ \ + Type min = first; \ + Type max = first; \ + long int lmin; \ + long int lmax; \ + int i; \ + int j = 1; \ + \ + obstack_printf (&format_obstack, "%6d", first); \ + for (i = begin; i < end; ++i) \ + { \ + obstack_1grow (&format_obstack, ','); \ + if (j >= 10) \ + { \ + obstack_sgrow (&format_obstack, "\n "); \ + j = 1; \ + } \ + else \ + ++j; \ + obstack_printf (&format_obstack, "%6d", table_data[i]); \ + if (table_data[i] < min) \ + min = table_data[i]; \ + if (max < table_data[i]) \ + max = table_data[i]; \ + } \ + muscle_insert (name, obstack_finish0 (&format_obstack)); \ + \ + lmin = min; \ + lmax = max; \ + /* Build 'NAME_min' and 'NAME_max' in the obstack. */ \ + obstack_printf (&format_obstack, "%s_min", name); \ + MUSCLE_INSERT_LONG_INT (obstack_finish0 (&format_obstack), lmin); \ + obstack_printf (&format_obstack, "%s_max", name); \ + MUSCLE_INSERT_LONG_INT (obstack_finish0 (&format_obstack), lmax); \ +} + +GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_unsigned_int_table, unsigned int) +GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_int_table, int) +GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_base_table, base_number) +GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_rule_number_table, rule_number) +GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_symbol_number_table, symbol_number) +GENERATE_MUSCLE_INSERT_TABLE (muscle_insert_state_number_table, state_number) + +/*----------------------------------------------------------------. +| Print to OUT a representation of CP quoted and escaped for M4. | +`----------------------------------------------------------------*/ + +static void +quoted_output (FILE *out, char const *cp) +{ + fprintf (out, "[["); + + for (; *cp; cp++) + switch (*cp) + { + case '$': fputs ("$][", out); break; + case '@': fputs ("@@", out); break; + case '[': fputs ("@{", out); break; + case ']': fputs ("@}", out); break; + default: fputc (*cp, out); break; + } + + fprintf (out, "]]"); +} + +/*----------------------------------------------------------------. +| Print to OUT a representation of STRING quoted and escaped both | +| for C and M4. | +`----------------------------------------------------------------*/ + +static void +string_output (FILE *out, char const *string) +{ + quoted_output (out, quotearg_style (c_quoting_style, string)); +} + + +/*------------------------------------------------------------------. +| Prepare the muscles related to the symbols: translate, tname, and | +| toknum. | +`------------------------------------------------------------------*/ + +static void +prepare_symbols (void) +{ + MUSCLE_INSERT_INT ("tokens_number", ntokens); + MUSCLE_INSERT_INT ("nterms_number", nvars); + MUSCLE_INSERT_INT ("symbols_number", nsyms); + MUSCLE_INSERT_INT ("undef_token_number", undeftoken->number); + MUSCLE_INSERT_INT ("user_token_number_max", max_user_token_number); + + muscle_insert_symbol_number_table ("translate", + token_translations, + token_translations[0], + 1, max_user_token_number + 1); + + /* tname -- token names. */ + { + int i; + /* We assume that the table will be output starting at column 2. */ + int j = 2; + struct quoting_options *qo = clone_quoting_options (0); + set_quoting_style (qo, c_quoting_style); + set_quoting_flags (qo, QA_SPLIT_TRIGRAPHS); + for (i = 0; i < nsyms; i++) + { + char *cp = quotearg_alloc (symbols[i]->tag, -1, qo); + /* Width of the next token, including the two quotes, the + comma and the space. */ + int width = strlen (cp) + 2; + + if (j + width > 75) + { + obstack_sgrow (&format_obstack, "\n "); + j = 1; + } + + if (i) + obstack_1grow (&format_obstack, ' '); + obstack_escape (&format_obstack, cp); + free (cp); + obstack_1grow (&format_obstack, ','); + j += width; + } + free (qo); + obstack_sgrow (&format_obstack, " ]b4_null["); + + /* Finish table and store. */ + muscle_insert ("tname", obstack_finish0 (&format_obstack)); + } + + /* Output YYTOKNUM. */ + { + int i; + int *values = xnmalloc (ntokens, sizeof *values); + for (i = 0; i < ntokens; ++i) + values[i] = symbols[i]->user_token_number; + muscle_insert_int_table ("toknum", values, + values[0], 1, ntokens); + free (values); + } +} + + +/*----------------------------------------------------------------. +| Prepare the muscles related to the rules: r1, r2, rline, dprec, | +| merger, immediate. | +`----------------------------------------------------------------*/ + +static void +prepare_rules (void) +{ + unsigned int *rline = xnmalloc (nrules, sizeof *rline); + symbol_number *r1 = xnmalloc (nrules, sizeof *r1); + unsigned int *r2 = xnmalloc (nrules, sizeof *r2); + int *dprec = xnmalloc (nrules, sizeof *dprec); + int *merger = xnmalloc (nrules, sizeof *merger); + int *immediate = xnmalloc (nrules, sizeof *immediate); + + rule_number r; + for (r = 0; r < nrules; ++r) + { + /* LHS of the rule R. */ + r1[r] = rules[r].lhs->number; + /* Length of rule R's RHS. */ + r2[r] = rule_rhs_length (&rules[r]); + /* Line where rule was defined. */ + rline[r] = rules[r].location.start.line; + /* Dynamic precedence (GLR). */ + dprec[r] = rules[r].dprec; + /* Merger-function index (GLR). */ + merger[r] = rules[r].merger; + /* Immediate reduction flags (GLR). */ + immediate[r] = rules[r].is_predicate; + } + + muscle_insert_unsigned_int_table ("rline", rline, 0, 0, nrules); + muscle_insert_symbol_number_table ("r1", r1, 0, 0, nrules); + muscle_insert_unsigned_int_table ("r2", r2, 0, 0, nrules); + muscle_insert_int_table ("dprec", dprec, 0, 0, nrules); + muscle_insert_int_table ("merger", merger, 0, 0, nrules); + muscle_insert_int_table ("immediate", immediate, 0, 0, nrules); + + MUSCLE_INSERT_INT ("rules_number", nrules); + MUSCLE_INSERT_INT ("max_left_semantic_context", max_left_semantic_context); + + free (rline); + free (r1); + free (r2); + free (dprec); + free (merger); + free (immediate); +} + +/*--------------------------------------------. +| Prepare the muscles related to the states. | +`--------------------------------------------*/ + +static void +prepare_states (void) +{ + state_number i; + symbol_number *values = xnmalloc (nstates, sizeof *values); + for (i = 0; i < nstates; ++i) + values[i] = states[i]->accessing_symbol; + muscle_insert_symbol_number_table ("stos", values, + 0, 1, nstates); + free (values); + + MUSCLE_INSERT_INT ("last", high); + MUSCLE_INSERT_INT ("final_state_number", final_state->number); + MUSCLE_INSERT_INT ("states_number", nstates); +} + + +/*-------------------------------------------------------. +| Compare two symbols by type-name, and then by number. | +`-------------------------------------------------------*/ + +static int +symbol_type_name_cmp (const symbol **lhs, const symbol **rhs) +{ + int res = uniqstr_cmp ((*lhs)->type_name, (*rhs)->type_name); + if (!res) + res = (*lhs)->number - (*rhs)->number; + return res; +} + + +/*----------------------------------------------------------------. +| Return a (malloc'ed) table of the symbols sorted by type-name. | +`----------------------------------------------------------------*/ + +static symbol ** +symbols_by_type_name (void) +{ + typedef int (*qcmp_type) (const void *, const void *); + symbol **res = xmemdup (symbols, nsyms * sizeof *res); + qsort (res, nsyms, sizeof *res, (qcmp_type) &symbol_type_name_cmp); + return res; +} + + +/*------------------------------------------------------------------. +| Define b4_type_names, which is a list of (lists of the numbers of | +| symbols with same type-name). | +`------------------------------------------------------------------*/ + +static void +type_names_output (FILE *out) +{ + int i; + symbol **syms = symbols_by_type_name (); + fputs ("m4_define([b4_type_names],\n[", out); + for (i = 0; i < nsyms; /* nothing */) + { + /* The index of the first symbol of the current type-name. */ + int i0 = i; + fputs (i ? ",\n[" : "[", out); + for (; i < nsyms && syms[i]->type_name == syms[i0]->type_name; ++i) + fprintf (out, "%s%d", i != i0 ? ", " : "", syms[i]->number); + fputs ("]", out); + } + fputs ("])\n\n", out); + free (syms); +} + + +/*-------------------------------------. +| The list of all the symbol numbers. | +`-------------------------------------*/ + +static void +symbol_numbers_output (FILE *out) +{ + int i; + fputs ("m4_define([b4_symbol_numbers],\n[", out); + for (i = 0; i < nsyms; ++i) + fprintf (out, "%s[%d]", i ? ", " : "", i); + fputs ("])\n\n", out); +} + + +/*---------------------------------. +| Output the user actions to OUT. | +`---------------------------------*/ + +static void +user_actions_output (FILE *out) +{ + rule_number r; + + fputs ("m4_define([b4_actions], \n[", out); + for (r = 0; r < nrules; ++r) + if (rules[r].action) + { + fprintf (out, "b4_%scase(%d, [b4_syncline(%d, ", + rules[r].is_predicate ? "predicate_" : "", + r + 1, rules[r].action_location.start.line); + string_output (out, rules[r].action_location.start.file); + fprintf (out, ")\n[ %s]])\n\n", rules[r].action); + } + fputs ("])\n\n", out); +} + +/*------------------------------------. +| Output the merge functions to OUT. | +`------------------------------------*/ + +static void +merger_output (FILE *out) +{ + int n; + merger_list* p; + + fputs ("m4_define([b4_mergers], \n[[", out); + for (n = 1, p = merge_functions; p != NULL; n += 1, p = p->next) + { + if (p->type[0] == '\0') + fprintf (out, " case %d: *yy0 = %s (*yy0, *yy1); break;\n", + n, p->name); + else + fprintf (out, " case %d: yy0->%s = %s (*yy0, *yy1); break;\n", + n, p->type, p->name); + } + fputs ("]])\n\n", out); +} + + +/*---------------------------------------------. +| Prepare the muscles for symbol definitions. | +`---------------------------------------------*/ + +static void +prepare_symbol_definitions (void) +{ + int i; + for (i = 0; i < nsyms; ++i) + { + symbol *sym = symbols[i]; + const char *key; + const char *value; + +#define SET_KEY(Entry) \ + obstack_printf (&format_obstack, "symbol(%d, %s)", \ + i, Entry); \ + key = obstack_finish0 (&format_obstack); + +#define SET_KEY2(Entry, Suffix) \ + obstack_printf (&format_obstack, "symbol(%d, %s_%s)", \ + i, Entry, Suffix); \ + key = obstack_finish0 (&format_obstack); + + /* Whether the symbol has an identifier. */ + value = symbol_id_get (sym); + SET_KEY ("has_id"); + MUSCLE_INSERT_INT (key, !!value); + + /* Its identifier. */ + SET_KEY ("id"); + MUSCLE_INSERT_STRING (key, value ? value : ""); + + /* Its tag. Typically for documentation purpose. */ + SET_KEY ("tag"); + MUSCLE_INSERT_STRING (key, sym->tag); + + SET_KEY ("user_number"); + MUSCLE_INSERT_INT (key, sym->user_token_number); + + SET_KEY ("is_token"); + MUSCLE_INSERT_INT (key, + i < ntokens && sym != errtoken && sym != undeftoken); + + SET_KEY ("number"); + MUSCLE_INSERT_INT (key, sym->number); + + SET_KEY ("has_type"); + MUSCLE_INSERT_INT (key, !!sym->type_name); + + SET_KEY ("type"); + MUSCLE_INSERT_STRING (key, sym->type_name ? sym->type_name : ""); + + { + int j; + for (j = 0; j < CODE_PROPS_SIZE; ++j) + { + /* "printer", not "%printer". */ + char const *pname = code_props_type_string (j) + 1; + code_props const *p = symbol_code_props_get (sym, j); + SET_KEY2 ("has", pname); + MUSCLE_INSERT_INT (key, !!p->code); + + if (p->code) + { + SET_KEY2 (pname, "file"); + MUSCLE_INSERT_STRING (key, p->location.start.file); + + SET_KEY2 (pname, "line"); + MUSCLE_INSERT_INT (key, p->location.start.line); + + SET_KEY (pname); + MUSCLE_INSERT_STRING_RAW (key, p->code); + } + } + } +#undef SET_KEY2 +#undef SET_KEY + } +} + + +static void +prepare_actions (void) +{ + /* Figure out the actions for the specified state, indexed by + lookahead token type. */ + + muscle_insert_rule_number_table ("defact", yydefact, + yydefact[0], 1, nstates); + + /* Figure out what to do after reducing with each rule, depending on + the saved state from before the beginning of parsing the data + that matched this rule. */ + muscle_insert_state_number_table ("defgoto", yydefgoto, + yydefgoto[0], 1, nsyms - ntokens); + + + /* Output PACT. */ + muscle_insert_base_table ("pact", base, + base[0], 1, nstates); + MUSCLE_INSERT_INT ("pact_ninf", base_ninf); + + /* Output PGOTO. */ + muscle_insert_base_table ("pgoto", base, + base[nstates], nstates + 1, nvectors); + + muscle_insert_base_table ("table", table, + table[0], 1, high + 1); + MUSCLE_INSERT_INT ("table_ninf", table_ninf); + + muscle_insert_base_table ("check", check, + check[0], 1, high + 1); + + /* GLR parsing slightly modifies YYTABLE and YYCHECK (and thus + YYPACT) so that in states with unresolved conflicts, the default + reduction is not used in the conflicted entries, so that there is + a place to put a conflict pointer. + + This means that YYCONFLP and YYCONFL are nonsense for a non-GLR + parser, so we could avoid accidents by not writing them out in + that case. Nevertheless, it seems even better to be able to use + the GLR skeletons even without the non-deterministic tables. */ + muscle_insert_unsigned_int_table ("conflict_list_heads", conflict_table, + conflict_table[0], 1, high + 1); + muscle_insert_unsigned_int_table ("conflicting_rules", conflict_list, + 0, 1, conflict_list_cnt); +} + + +/*--------------------------------------------. +| Output the definitions of all the muscles. | +`--------------------------------------------*/ + +static void +muscles_output (FILE *out) +{ + fputs ("m4_init()\n", out); + merger_output (out); + symbol_numbers_output (out); + type_names_output (out); + user_actions_output (out); + /* Must be last. */ + muscles_m4_output (out); +} + +/*---------------------------. +| Call the skeleton parser. | +`---------------------------*/ + +#define M4_GNU_OPTION "--gnu" + +static void +output_skeleton (void) +{ + int filter_fd[2]; + pid_t pid; + + /* Compute the names of the package data dir and skeleton files. */ + char const *m4 = (m4 = getenv ("M4")) ? m4 : M4; + char const *datadir = pkgdatadir (); + char *m4sugar = xconcatenated_filename (datadir, "m4sugar/m4sugar.m4", NULL); + char *m4bison = xconcatenated_filename (datadir, "bison.m4", NULL); + char *skel = (IS_PATH_WITH_DIR (skeleton) + ? xstrdup (skeleton) + : xconcatenated_filename (datadir, skeleton, NULL)); + + /* Test whether m4sugar.m4 is readable, to check for proper + installation. A faulty installation can cause deadlock, so a + cheap sanity check is worthwhile. */ + xfclose (xfopen (m4sugar, "r")); + + /* Create an m4 subprocess connected to us via two pipes. */ + + if (trace_flag & trace_tools) + fprintf (stderr, "running: %s %s - %s %s\n", + m4, m4sugar, m4bison, skel); + + /* Some future version of GNU M4 (most likely 1.6) may treat the -dV in a + position-dependent manner. Keep it as the first argument so that all + files are traced. + + See the thread starting at + <http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html> + for details. */ + { + char const *argv[10]; + int i = 0; + argv[i++] = m4; + + /* When POSIXLY_CORRECT is set, GNU M4 1.6 and later disable GNU + extensions, which Bison's skeletons depend on. With older M4, + it has no effect. M4 1.4.12 added a -g/--gnu command-line + option to make it explicit that a program wants GNU M4 + extensions even when POSIXLY_CORRECT is set. + + See the thread starting at + <http://lists.gnu.org/archive/html/bug-bison/2008-07/msg00000.html> + for details. */ + if (*M4_GNU_OPTION) + argv[i++] = M4_GNU_OPTION; + + argv[i++] = "-I"; + argv[i++] = datadir; + if (trace_flag & trace_m4) + argv[i++] = "-dV"; + argv[i++] = m4sugar; + argv[i++] = "-"; + argv[i++] = m4bison; + argv[i++] = skel; + argv[i++] = NULL; + aver (i <= ARRAY_CARDINALITY (argv)); + + /* The ugly cast is because gnulib gets the const-ness wrong. */ + pid = create_pipe_bidi ("m4", m4, (char **)(void*)argv, false, true, + true, filter_fd); + } + + free (m4sugar); + free (m4bison); + free (skel); + + if (trace_flag & trace_muscles) + muscles_output (stderr); + { + FILE *out = xfdopen (filter_fd[1], "w"); + muscles_output (out); + xfclose (out); + } + + /* Read and process m4's output. */ + timevar_push (TV_M4); + { + FILE *in = xfdopen (filter_fd[0], "r"); + scan_skel (in); + /* scan_skel should have read all of M4's output. Otherwise, when we + close the pipe, we risk letting M4 report a broken-pipe to the + Bison user. */ + aver (feof (in)); + xfclose (in); + } + wait_subprocess (pid, "m4", false, false, true, true, NULL); + timevar_pop (TV_M4); +} + +static void +prepare (void) +{ + /* BISON_USE_PUSH_FOR_PULL is for the test suite and should not be + documented for the user. */ + char const *cp = getenv ("BISON_USE_PUSH_FOR_PULL"); + bool use_push_for_pull_flag = cp && *cp && strtol (cp, 0, 10); + + /* Flags. */ + MUSCLE_INSERT_BOOL ("defines_flag", defines_flag); + MUSCLE_INSERT_BOOL ("glr_flag", glr_parser); + MUSCLE_INSERT_BOOL ("nondeterministic_flag", nondeterministic_parser); + MUSCLE_INSERT_BOOL ("synclines_flag", !no_lines_flag); + MUSCLE_INSERT_BOOL ("tag_seen_flag", tag_seen); + MUSCLE_INSERT_BOOL ("token_table_flag", token_table_flag); + MUSCLE_INSERT_BOOL ("use_push_for_pull_flag", use_push_for_pull_flag); + MUSCLE_INSERT_BOOL ("yacc_flag", yacc_flag); + + /* File names. */ + if (spec_name_prefix) + MUSCLE_INSERT_STRING ("prefix", spec_name_prefix); + + MUSCLE_INSERT_STRING ("file_name_all_but_ext", all_but_ext); + +#define DEFINE(Name) MUSCLE_INSERT_STRING (#Name, Name ? Name : "") + DEFINE (dir_prefix); + DEFINE (parser_file_name); + DEFINE (spec_defines_file); + DEFINE (spec_file_prefix); + DEFINE (spec_graph_file); + DEFINE (spec_name_prefix); + DEFINE (spec_outfile); + DEFINE (spec_verbose_file); +#undef DEFINE + + /* Find the right skeleton file, and add muscles about the skeletons. */ + if (skeleton) + MUSCLE_INSERT_C_STRING ("skeleton", skeleton); + else + skeleton = language->skeleton; + + /* About the skeletons. */ + { + /* b4_pkgdatadir is used inside m4_include in the skeletons, so digraphs + would never be expanded. Hopefully no one has M4-special characters in + his Bison installation path. */ + MUSCLE_INSERT_STRING_RAW ("pkgdatadir", pkgdatadir ()); + } +} + + +/*----------------------------------------------------------. +| Output the parsing tables and the parser code to ftable. | +`----------------------------------------------------------*/ + +void +output (void) +{ + obstack_init (&format_obstack); + + prepare_symbols (); + prepare_rules (); + prepare_states (); + prepare_actions (); + prepare_symbol_definitions (); + + prepare (); + + /* Process the selected skeleton file. */ + output_skeleton (); + + obstack_free (&format_obstack, NULL); +} + +char const * +pkgdatadir (void) +{ + char const *cp = getenv ("BISON_PKGDATADIR"); + return cp ? cp : PKGDATADIR; +} diff --git a/contrib/tools/bison/src/output.h b/contrib/tools/bison/src/output.h new file mode 100644 index 0000000000..63a0ca803a --- /dev/null +++ b/contrib/tools/bison/src/output.h @@ -0,0 +1,30 @@ +/* Output the generated parsing program for bison, + + Copyright (C) 2000-2003, 2006-2007, 2009-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef OUTPUT_H_ +# define OUTPUT_H_ + +/* Output the parsing tables and the parser code to FTABLE. */ +void output (void); + +/* Where our data files are installed. */ +char const *pkgdatadir (void); + +#endif /* !OUTPUT_H_ */ diff --git a/contrib/tools/bison/src/parse-gram.c b/contrib/tools/bison/src/parse-gram.c new file mode 100644 index 0000000000..5b862667e9 --- /dev/null +++ b/contrib/tools/bison/src/parse-gram.c @@ -0,0 +1,3106 @@ +/* A Bison parser, made by GNU Bison 3.0. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "3.0" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 2 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + +/* "%code top" blocks. */ +#line 27 "src/parse-gram.y" /* yacc.c:316 */ + + /* On column 0 to please syntax-check. */ +#include <config.h> +#include "string--.h" + +#line 68 "src/parse-gram.c" /* yacc.c:316 */ +/* Substitute the type names. */ +#define YYSTYPE GRAM_STYPE +#define YYLTYPE GRAM_LTYPE +/* Substitute the variable and function names. */ +#define yyparse gram_parse +#define yylex gram_lex +#define yyerror gram_error +#define yydebug gram_debug +#define yynerrs gram_nerrs + + +/* Copy the first part of user declarations. */ + +#line 82 "src/parse-gram.c" /* yacc.c:339 */ + +# ifndef YY_NULL +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULL nullptr +# else +# define YY_NULL 0 +# endif +# endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 1 +#endif + +/* In a future release of Bison, this section will be replaced + by #include "src/parse-gram.h". */ +#ifndef YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED +# define YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED +/* Debug traces. */ +#ifndef GRAM_DEBUG +# if defined YYDEBUG +#if YYDEBUG +# define GRAM_DEBUG 1 +# else +# define GRAM_DEBUG 0 +# endif +# else /* ! defined YYDEBUG */ +# define GRAM_DEBUG 1 +# endif /* ! defined YYDEBUG */ +#endif /* ! defined GRAM_DEBUG */ +#if GRAM_DEBUG +extern int gram_debug; +#endif +/* "%code requires" blocks. */ +#line 21 "src/parse-gram.y" /* yacc.c:355 */ + + #include "symlist.h" + #include "symtab.h" +#line 221 "src/parse-gram.y" /* yacc.c:355 */ + + typedef enum + { + param_none = 0, + param_lex = 1 << 0, + param_parse = 1 << 1, + param_both = param_lex | param_parse + } param_type; +#line 645 "src/parse-gram.y" /* yacc.c:355 */ +#include "muscle-tab.h" + +#line 136 "src/parse-gram.c" /* yacc.c:355 */ + +/* Token type. */ +#ifndef GRAM_TOKENTYPE +# define GRAM_TOKENTYPE + enum gram_tokentype + { + GRAM_EOF = 0, + STRING = 258, + PERCENT_TOKEN = 259, + PERCENT_NTERM = 260, + PERCENT_TYPE = 261, + PERCENT_DESTRUCTOR = 262, + PERCENT_PRINTER = 263, + PERCENT_LEFT = 264, + PERCENT_RIGHT = 265, + PERCENT_NONASSOC = 266, + PERCENT_PRECEDENCE = 267, + PERCENT_PREC = 268, + PERCENT_DPREC = 269, + PERCENT_MERGE = 270, + PERCENT_CODE = 271, + PERCENT_DEFAULT_PREC = 272, + PERCENT_DEFINE = 273, + PERCENT_DEFINES = 274, + PERCENT_ERROR_VERBOSE = 275, + PERCENT_EXPECT = 276, + PERCENT_EXPECT_RR = 277, + PERCENT_FLAG = 278, + PERCENT_FILE_PREFIX = 279, + PERCENT_GLR_PARSER = 280, + PERCENT_INITIAL_ACTION = 281, + PERCENT_LANGUAGE = 282, + PERCENT_NAME_PREFIX = 283, + PERCENT_NO_DEFAULT_PREC = 284, + PERCENT_NO_LINES = 285, + PERCENT_NONDETERMINISTIC_PARSER = 286, + PERCENT_OUTPUT = 287, + PERCENT_REQUIRE = 288, + PERCENT_SKELETON = 289, + PERCENT_START = 290, + PERCENT_TOKEN_TABLE = 291, + PERCENT_VERBOSE = 292, + PERCENT_YACC = 293, + BRACED_CODE = 294, + BRACED_PREDICATE = 295, + BRACKETED_ID = 296, + CHAR = 297, + EPILOGUE = 298, + EQUAL = 299, + ID = 300, + ID_COLON = 301, + PERCENT_PERCENT = 302, + PIPE = 303, + PROLOGUE = 304, + SEMICOLON = 305, + TAG = 306, + TAG_ANY = 307, + TAG_NONE = 308, + INT = 309, + PERCENT_PARAM = 310, + PERCENT_UNION = 311, + PERCENT_EMPTY = 312 + }; +#endif + +/* Value type. */ +#if ! defined GRAM_STYPE && ! defined GRAM_STYPE_IS_DECLARED +typedef union GRAM_STYPE GRAM_STYPE; +union GRAM_STYPE +{ +#line 182 "src/parse-gram.y" /* yacc.c:355 */ +unsigned char character; +#line 186 "src/parse-gram.y" /* yacc.c:355 */ +char *code; +#line 191 "src/parse-gram.y" /* yacc.c:355 */ +uniqstr uniqstr; +#line 199 "src/parse-gram.y" /* yacc.c:355 */ +int integer; +#line 203 "src/parse-gram.y" /* yacc.c:355 */ +symbol *symbol; +#line 208 "src/parse-gram.y" /* yacc.c:355 */ +assoc assoc; +#line 211 "src/parse-gram.y" /* yacc.c:355 */ +symbol_list *list; +#line 214 "src/parse-gram.y" /* yacc.c:355 */ +named_ref *named_ref; +#line 241 "src/parse-gram.y" /* yacc.c:355 */ +param_type param; +#line 409 "src/parse-gram.y" /* yacc.c:355 */ +code_props_type code_type; +#line 647 "src/parse-gram.y" /* yacc.c:355 */ + + struct + { + char const *chars; + muscle_kind kind; + } value; + +#line 235 "src/parse-gram.c" /* yacc.c:355 */ +}; +# define GRAM_STYPE_IS_TRIVIAL 1 +# define GRAM_STYPE_IS_DECLARED 1 +#endif + +/* Location type. */ +#if ! defined GRAM_LTYPE && ! defined GRAM_LTYPE_IS_DECLARED +typedef struct GRAM_LTYPE GRAM_LTYPE; +struct GRAM_LTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +}; +# define GRAM_LTYPE_IS_DECLARED 1 +# define GRAM_LTYPE_IS_TRIVIAL 1 +#endif + + + +int gram_parse (void); + +#endif /* !YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED */ + +/* Copy the second part of user declarations. */ + +#line 263 "src/parse-gram.c" /* yacc.c:358 */ +/* Unqualified %code blocks. */ +#line 33 "src/parse-gram.y" /* yacc.c:359 */ + + #include "system.h" + + #include "c-ctype.h" + #include "complain.h" + #include "conflicts.h" + #include "files.h" + #include "getargs.h" + #include "gram.h" + #include "named-ref.h" + #include "quotearg.h" + #include "reader.h" + #include "scan-gram.h" + #include "scan-code.h" + #include "xmemdup0.h" + + static int current_prec = 0; + static location current_lhs_location; + static named_ref *current_lhs_named_ref; + static symbol *current_lhs_symbol; + static symbol_class current_class = unknown_sym; + static uniqstr current_type = NULL; + + /** Set the new current left-hand side symbol, possibly common + * to several right-hand side parts of rule. + */ + static void current_lhs (symbol *sym, location loc, named_ref *ref); + + #define YYLLOC_DEFAULT(Current, Rhs, N) \ + (Current) = lloc_default (Rhs, N) + static YYLTYPE lloc_default (YYLTYPE const *, int); + + #define YY_LOCATION_PRINT(File, Loc) \ + location_print (Loc, File) + + /* Strip initial '{' and final '}' (must be first and last characters). + Return the result. */ + static char *strip_braces (char *code); + + /* Convert CODE by calling code_props_plain_init if PLAIN, otherwise + code_props_symbol_action_init. Call + gram_scanner_last_string_free to release the latest string from + the scanner (should be CODE). */ + static char const *translate_code (char *code, location loc, bool plain); + + /* Convert CODE by calling code_props_plain_init after having + stripped the first and last characters (expected to be '{', and + '}'). Call gram_scanner_last_string_free to release the latest + string from the scanner (should be CODE). */ + static char const *translate_code_braceless (char *code, location loc); + + static void version_check (location const *loc, char const *version); + + static void gram_error (location const *, char const *); + + /* A string that describes a char (e.g., 'a' -> "'a'"). */ + static char const *char_name (char); + + #define YYTYPE_INT16 int_fast16_t + #define YYTYPE_INT8 int_fast8_t + #define YYTYPE_UINT16 uint_fast16_t + #define YYTYPE_UINT8 uint_fast8_t +#line 231 "src/parse-gram.y" /* yacc.c:359 */ + + /** Add a lex-param and/or a parse-param. + * + * \param type where to push this formal argument. + * \param decl the formal argument. Destroyed. + * \param loc the location in the source. + */ + static void add_param (param_type type, char *decl, location loc); + static param_type current_param = param_none; + +#line 339 "src/parse-gram.c" /* yacc.c:359 */ + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#else +typedef signed char yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include <libintl.h> /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + +#ifndef __attribute__ +/* This feature is available in gcc versions 2.5 and later. */ +# if (! defined __GNUC__ || __GNUC__ < 2 \ + || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)) +# define __attribute__(Spec) /* empty */ +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(E) ((void) (E)) +#else +# define YYUSE(E) /* empty */ +#endif + +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + + +#if 1 + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +# define YYCOPY_NEEDED 1 +#endif + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined GRAM_LTYPE_IS_TRIVIAL && GRAM_LTYPE_IS_TRIVIAL \ + && defined GRAM_STYPE_IS_TRIVIAL && GRAM_STYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; + YYLTYPE yyls_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + + 2 * YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 3 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 164 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 58 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 37 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 110 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 144 + +/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned + by yylex, with out-of-bounds checking. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 312 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, without out-of-bounds checking. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57 +}; + +#if GRAM_DEBUG + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 264, 264, 273, 274, 278, 279, 285, 289, 294, + 295, 300, 306, 307, 308, 309, 314, 319, 320, 321, + 322, 323, 324, 324, 325, 326, 350, 351, 352, 353, + 357, 358, 367, 368, 369, 373, 385, 389, 393, 401, + 412, 413, 423, 424, 428, 440, 440, 445, 445, 450, + 461, 476, 477, 478, 479, 483, 484, 489, 491, 496, + 501, 511, 513, 518, 519, 523, 524, 528, 529, 530, + 535, 540, 545, 551, 557, 568, 569, 578, 579, 585, + 586, 587, 594, 594, 602, 603, 604, 609, 612, 614, + 616, 618, 620, 622, 624, 629, 630, 640, 641, 666, + 667, 668, 669, 681, 683, 692, 697, 698, 703, 711, + 712 +}; +#endif + +#if GRAM_DEBUG || YYERROR_VERBOSE || 1 +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "\"end of file\"", "error", "$undefined", "\"string\"", "\"%token\"", + "\"%nterm\"", "\"%type\"", "\"%destructor\"", "\"%printer\"", + "\"%left\"", "\"%right\"", "\"%nonassoc\"", "\"%precedence\"", + "\"%prec\"", "\"%dprec\"", "\"%merge\"", "\"%code\"", + "\"%default-prec\"", "\"%define\"", "\"%defines\"", "\"%error-verbose\"", + "\"%expect\"", "\"%expect-rr\"", "\"%<flag>\"", "\"%file-prefix\"", + "\"%glr-parser\"", "\"%initial-action\"", "\"%language\"", + "\"%name-prefix\"", "\"%no-default-prec\"", "\"%no-lines\"", + "\"%nondeterministic-parser\"", "\"%output\"", "\"%require\"", + "\"%skeleton\"", "\"%start\"", "\"%token-table\"", "\"%verbose\"", + "\"%yacc\"", "\"{...}\"", "\"%?{...}\"", "\"[identifier]\"", "\"char\"", + "\"epilogue\"", "\"=\"", "\"identifier\"", "\"identifier:\"", "\"%%\"", + "\"|\"", "\"%{...%}\"", "\";\"", "\"<tag>\"", "\"<*>\"", "\"<>\"", + "\"integer\"", "\"%param\"", "\"%union\"", "\"%empty\"", "$accept", + "input", "prologue_declarations", "prologue_declaration", "$@1", + "params", "grammar_declaration", "code_props_type", "union_name", + "symbol_declaration", "$@2", "$@3", "precedence_declaration", + "precedence_declarator", "tag.opt", "symbols.prec", "symbol.prec", + "symbols.1", "generic_symlist", "generic_symlist_item", "tag", + "symbol_def", "symbol_defs.1", "grammar", "rules_or_grammar_declaration", + "rules", "$@4", "rhses.1", "rhs", "named_ref.opt", "variable", "value", + "id", "id_colon", "symbol", "string_as_id", "epilogue.opt", YY_NULL +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312 +}; +# endif + +#define YYPACT_NINF -113 + +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-113))) + +#define YYTABLE_NINF -110 + +#define yytable_value_is_error(Yytable_value) \ + 0 + + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int8 yypact[] = +{ + -113, 16, 108, -113, -113, -113, -27, -113, -113, -113, + -113, -113, -113, -24, -113, 23, 24, -113, -21, -15, + -113, 29, -113, 3, 38, 42, -113, -113, -113, 44, + 47, 71, 31, -113, -113, -113, 55, -113, -113, -113, + 30, -113, -113, 39, -113, -113, 26, -22, -22, 31, + -113, 48, -113, -113, 1, -113, -113, -113, -113, -113, + -113, -113, -113, -113, -113, -113, -113, -113, -113, -113, + -113, 45, -113, 50, 2, -113, -113, 57, 49, -113, + 52, 41, -113, 31, -113, -113, -22, -2, -22, 31, + -113, -113, -113, -113, -113, -113, -113, -113, 46, -113, + -113, -113, -113, -113, 63, -113, -113, -113, -113, 41, + -113, -113, -113, 31, -113, 51, -113, 100, -113, -113, + -113, -113, -113, -113, -113, -113, -113, -20, 40, -113, + -113, 31, 53, 58, 57, -113, -113, 57, 40, -113, + -113, -113, -113, -113 +}; + + /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 3, 0, 0, 1, 47, 45, 0, 40, 41, 51, + 52, 53, 54, 0, 36, 0, 9, 11, 0, 0, + 7, 0, 15, 0, 0, 0, 37, 19, 20, 0, + 0, 0, 0, 26, 27, 28, 0, 6, 29, 22, + 42, 4, 5, 0, 33, 32, 55, 0, 0, 0, + 38, 0, 98, 97, 99, 10, 12, 13, 14, 16, + 17, 18, 21, 24, 25, 108, 104, 103, 106, 34, + 107, 0, 105, 0, 0, 77, 79, 95, 0, 43, + 0, 0, 56, 0, 70, 75, 48, 71, 46, 49, + 61, 39, 101, 102, 100, 8, 81, 80, 0, 78, + 2, 96, 82, 31, 23, 44, 67, 68, 69, 35, + 63, 66, 65, 50, 57, 59, 76, 72, 73, 62, + 110, 87, 30, 64, 58, 60, 74, 83, 84, 87, + 86, 0, 0, 0, 95, 90, 91, 95, 85, 92, + 93, 94, 89, 88 +}; + + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -113, -113, -113, -113, -113, -113, 102, -113, -113, -113, + -113, -113, -113, -113, -113, -113, 8, -113, -113, 13, + -113, -50, 75, -113, 73, -113, -113, -113, 19, -112, + -113, -113, 22, -113, -32, -82, -113 +}; + + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 1, 2, 41, 78, 104, 73, 43, 80, 44, + 48, 47, 45, 46, 83, 113, 114, 89, 109, 110, + 111, 85, 86, 74, 75, 76, 121, 127, 128, 102, + 54, 95, 68, 77, 112, 70, 100 +}; + + /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_int16 yytable[] = +{ + 69, 65, -109, 71, 92, 118, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 50, 3, 90, 13, 14, + 66, 51, 142, 67, 49, 143, 52, 55, 129, 84, + 130, 26, 58, 56, 65, 126, 116, 32, 116, 57, + 93, 60, 59, 65, 65, 61, 94, 62, 72, 98, + 63, 115, 117, 131, 132, 133, 71, 119, 40, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 53, 87, + 87, 13, 14, 66, 64, 79, 67, 82, 81, 134, + 135, 115, 66, 66, 26, 67, 67, 91, 103, 120, + 32, 105, 106, 107, 108, 96, 137, 136, 101, 139, + 97, 72, 122, 65, 42, 125, 137, 140, 87, 141, + 87, 40, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 124, 123, 88, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 99, 138, 0, + 0, 0, 0, 0, 0, 36, 0, 37, 38, 0, + 0, 0, 0, 39, 40 +}; + +static const yytype_int16 yycheck[] = +{ + 32, 3, 0, 1, 3, 87, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 39, 0, 49, 16, 17, + 42, 45, 134, 45, 51, 137, 3, 3, 48, 51, + 50, 29, 3, 54, 3, 117, 86, 35, 88, 54, + 39, 3, 39, 3, 3, 3, 45, 3, 46, 47, + 3, 83, 54, 13, 14, 15, 1, 89, 56, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 45, 47, + 48, 16, 17, 42, 3, 45, 45, 51, 39, 39, + 40, 113, 42, 42, 29, 45, 45, 39, 39, 43, + 35, 39, 51, 52, 53, 50, 128, 57, 41, 131, + 50, 46, 39, 3, 2, 54, 138, 54, 86, 51, + 88, 56, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 113, 109, 48, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 74, 129, -1, + -1, -1, -1, -1, -1, 47, -1, 49, 50, -1, + -1, -1, -1, 55, 56 +}; + + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 59, 60, 0, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 47, 49, 50, 55, + 56, 61, 64, 65, 67, 70, 71, 69, 68, 51, + 39, 45, 3, 45, 88, 3, 54, 54, 3, 39, + 3, 3, 3, 3, 3, 3, 42, 45, 90, 92, + 93, 1, 46, 64, 81, 82, 83, 91, 62, 45, + 66, 39, 51, 72, 51, 79, 80, 90, 80, 75, + 92, 39, 3, 39, 45, 89, 50, 50, 47, 82, + 94, 41, 87, 39, 63, 39, 51, 52, 53, 76, + 77, 78, 92, 73, 74, 92, 79, 54, 93, 92, + 43, 84, 39, 77, 74, 54, 93, 85, 86, 48, + 50, 13, 14, 15, 39, 40, 57, 92, 86, 92, + 54, 51, 87, 87 +}; + + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 58, 59, 60, 60, 61, 61, 61, 61, 61, + 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, + 61, 61, 62, 61, 61, 61, 61, 61, 61, 61, + 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, + 65, 65, 66, 66, 64, 68, 67, 69, 67, 67, + 70, 71, 71, 71, 71, 72, 72, 73, 73, 74, + 74, 75, 75, 76, 76, 77, 77, 78, 78, 78, + 79, 79, 79, 79, 79, 80, 80, 81, 81, 82, + 82, 82, 84, 83, 85, 85, 85, 86, 86, 86, + 86, 86, 86, 86, 86, 87, 87, 88, 88, 89, + 89, 89, 89, 90, 90, 91, 92, 92, 93, 94, + 94 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 4, 0, 2, 1, 1, 1, 3, 1, + 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, + 1, 2, 0, 3, 2, 2, 1, 1, 1, 1, + 2, 1, 1, 1, 2, 3, 1, 1, 2, 3, + 1, 1, 0, 1, 3, 0, 3, 0, 3, 3, + 3, 1, 1, 1, 1, 0, 1, 1, 2, 1, + 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 3, 1, 2, 1, 2, 1, + 2, 2, 0, 4, 1, 3, 2, 0, 3, 3, + 2, 2, 3, 3, 3, 0, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 2 +}; + + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + YY_LAC_DISCARD ("YYBACKUP"); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (&yylloc, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (0) + +/* Error token number */ +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (N) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (0) +#endif + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) + + +/* Enable debugging if requested. */ +#if GRAM_DEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if defined GRAM_LTYPE_IS_TRIVIAL && GRAM_LTYPE_IS_TRIVIAL + +/* Print *YYLOCP on YYO. Private, do not rely on its existence. */ + +__attribute__((__unused__)) +static unsigned +yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp) +{ + unsigned res = 0; + int end_col = 0 != yylocp->last_column ? yylocp->last_column - 1 : 0; + if (0 <= yylocp->first_line) + { + res += YYFPRINTF (yyo, "%d", yylocp->first_line); + if (0 <= yylocp->first_column) + res += YYFPRINTF (yyo, ".%d", yylocp->first_column); + } + if (0 <= yylocp->last_line) + { + if (yylocp->first_line < yylocp->last_line) + { + res += YYFPRINTF (yyo, "-%d", yylocp->last_line); + if (0 <= end_col) + res += YYFPRINTF (yyo, ".%d", end_col); + } + else if (0 <= end_col && yylocp->first_column < end_col) + res += YYFPRINTF (yyo, "-%d", end_col); + } + return res; + } + +# define YY_LOCATION_PRINT(File, Loc) \ + yy_location_print_ (File, &(Loc)) + +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value, Location); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + + +/*----------------------------------------. +| Print this symbol's value on YYOUTPUT. | +`----------------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp) +{ + FILE *yyo = yyoutput; + YYUSE (yyo); + YYUSE (yylocationp); + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + switch (yytype) + { + case 3: /* "string" */ +#line 188 "src/parse-gram.y" /* yacc.c:684 */ + { fputs (quotearg_style (c_quoting_style, ((*yyvaluep).code)), yyo); } +#line 987 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 23: /* "%<flag>" */ +#line 196 "src/parse-gram.y" /* yacc.c:684 */ + { fprintf (yyo, "%%%s", ((*yyvaluep).uniqstr)); } +#line 993 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 39: /* "{...}" */ +#line 189 "src/parse-gram.y" /* yacc.c:684 */ + { fprintf (yyo, "{\n%s\n}", ((*yyvaluep).code)); } +#line 999 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 40: /* "%?{...}" */ +#line 189 "src/parse-gram.y" /* yacc.c:684 */ + { fprintf (yyo, "{\n%s\n}", ((*yyvaluep).code)); } +#line 1005 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 41: /* "[identifier]" */ +#line 194 "src/parse-gram.y" /* yacc.c:684 */ + { fprintf (yyo, "[%s]", ((*yyvaluep).uniqstr)); } +#line 1011 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 42: /* "char" */ +#line 184 "src/parse-gram.y" /* yacc.c:684 */ + { fputs (char_name (((*yyvaluep).character)), yyo); } +#line 1017 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 43: /* "epilogue" */ +#line 189 "src/parse-gram.y" /* yacc.c:684 */ + { fprintf (yyo, "{\n%s\n}", ((*yyvaluep).code)); } +#line 1023 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 45: /* "identifier" */ +#line 193 "src/parse-gram.y" /* yacc.c:684 */ + { fputs (((*yyvaluep).uniqstr), yyo); } +#line 1029 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 46: /* "identifier:" */ +#line 195 "src/parse-gram.y" /* yacc.c:684 */ + { fprintf (yyo, "%s:", ((*yyvaluep).uniqstr)); } +#line 1035 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 49: /* "%{...%}" */ +#line 189 "src/parse-gram.y" /* yacc.c:684 */ + { fprintf (yyo, "{\n%s\n}", ((*yyvaluep).code)); } +#line 1041 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 51: /* "<tag>" */ +#line 197 "src/parse-gram.y" /* yacc.c:684 */ + { fprintf (yyo, "<%s>", ((*yyvaluep).uniqstr)); } +#line 1047 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 54: /* "integer" */ +#line 201 "src/parse-gram.y" /* yacc.c:684 */ + { fprintf (yyo, "%d", ((*yyvaluep).integer)); } +#line 1053 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 55: /* "%param" */ +#line 244 "src/parse-gram.y" /* yacc.c:684 */ + { + switch (((*yyvaluep).param)) + { +#define CASE(In, Out) \ + case param_ ## In: fputs ("%" #Out, yyo); break + CASE (lex, lex-param); + CASE (parse, parse-param); + CASE (both, param); +#undef CASE + case param_none: aver (false); break; + } +} +#line 1070 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 65: /* code_props_type */ +#line 410 "src/parse-gram.y" /* yacc.c:684 */ + { fprintf (yyo, "%s", code_props_type_string (((*yyvaluep).code_type))); } +#line 1076 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 74: /* symbol.prec */ +#line 205 "src/parse-gram.y" /* yacc.c:684 */ + { fprintf (yyo, "%s", ((*yyvaluep).symbol)->tag); } +#line 1082 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 78: /* tag */ +#line 197 "src/parse-gram.y" /* yacc.c:684 */ + { fprintf (yyo, "<%s>", ((*yyvaluep).uniqstr)); } +#line 1088 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 88: /* variable */ +#line 193 "src/parse-gram.y" /* yacc.c:684 */ + { fputs (((*yyvaluep).uniqstr), yyo); } +#line 1094 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 89: /* value */ +#line 656 "src/parse-gram.y" /* yacc.c:684 */ + { + switch (((*yyvaluep).value).kind) + { + case muscle_code: fprintf (yyo, "{%s}", ((*yyvaluep).value).chars); break; + case muscle_keyword: fprintf (yyo, "%s", ((*yyvaluep).value).chars); break; + case muscle_string: fprintf (yyo, "\"%s\"", ((*yyvaluep).value).chars); break; + } +} +#line 1107 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 90: /* id */ +#line 205 "src/parse-gram.y" /* yacc.c:684 */ + { fprintf (yyo, "%s", ((*yyvaluep).symbol)->tag); } +#line 1113 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 91: /* id_colon */ +#line 206 "src/parse-gram.y" /* yacc.c:684 */ + { fprintf (yyo, "%s:", ((*yyvaluep).symbol)->tag); } +#line 1119 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 92: /* symbol */ +#line 205 "src/parse-gram.y" /* yacc.c:684 */ + { fprintf (yyo, "%s", ((*yyvaluep).symbol)->tag); } +#line 1125 "src/parse-gram.c" /* yacc.c:684 */ + break; + + case 93: /* string_as_id */ +#line 205 "src/parse-gram.y" /* yacc.c:684 */ + { fprintf (yyo, "%s", ((*yyvaluep).symbol)->tag); } +#line 1131 "src/parse-gram.c" /* yacc.c:684 */ + break; + + + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp) +{ + YYFPRINTF (yyoutput, "%s %s (", + yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); + + YY_LOCATION_PRINT (yyoutput, *yylocationp); + YYFPRINTF (yyoutput, ": "); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void +yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule) +{ + unsigned long int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + yystos[yyssp[yyi + 1 - yynrhs]], + &(yyvsp[(yyi + 1) - (yynrhs)]) + , &(yylsp[(yyi + 1) - (yynrhs)]) ); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, yylsp, Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !GRAM_DEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !GRAM_DEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + +/* Given a state stack such that *YYBOTTOM is its bottom, such that + *YYTOP is either its top or is YYTOP_EMPTY to indicate an empty + stack, and such that *YYCAPACITY is the maximum number of elements it + can hold without a reallocation, make sure there is enough room to + store YYADD more elements. If not, allocate a new stack using + YYSTACK_ALLOC, copy the existing elements, and adjust *YYBOTTOM, + *YYTOP, and *YYCAPACITY to reflect the new capacity and memory + location. If *YYBOTTOM != YYBOTTOM_NO_FREE, then free the old stack + using YYSTACK_FREE. Return 0 if successful or if no reallocation is + required. Return 1 if memory is exhausted. */ +static int +yy_lac_stack_realloc (YYSIZE_T *yycapacity, YYSIZE_T yyadd, +#if GRAM_DEBUG + char const *yydebug_prefix, + char const *yydebug_suffix, +#endif + yytype_int16 **yybottom, + yytype_int16 *yybottom_no_free, + yytype_int16 **yytop, yytype_int16 *yytop_empty) +{ + YYSIZE_T yysize_old = + *yytop == yytop_empty ? 0 : *yytop - *yybottom + 1; + YYSIZE_T yysize_new = yysize_old + yyadd; + if (*yycapacity < yysize_new) + { + YYSIZE_T yyalloc = 2 * yysize_new; + yytype_int16 *yybottom_new; + /* Use YYMAXDEPTH for maximum stack size given that the stack + should never need to grow larger than the main state stack + needs to grow without LAC. */ + if (YYMAXDEPTH < yysize_new) + { + YYDPRINTF ((stderr, "%smax size exceeded%s", yydebug_prefix, + yydebug_suffix)); + return 1; + } + if (YYMAXDEPTH < yyalloc) + yyalloc = YYMAXDEPTH; + yybottom_new = + (yytype_int16*) YYSTACK_ALLOC (yyalloc * sizeof *yybottom_new); + if (!yybottom_new) + { + YYDPRINTF ((stderr, "%srealloc failed%s", yydebug_prefix, + yydebug_suffix)); + return 1; + } + if (*yytop != yytop_empty) + { + YYCOPY (yybottom_new, *yybottom, yysize_old); + *yytop = yybottom_new + (yysize_old - 1); + } + if (*yybottom != yybottom_no_free) + YYSTACK_FREE (*yybottom); + *yybottom = yybottom_new; + *yycapacity = yyalloc; + } + return 0; +} + +/* Establish the initial context for the current lookahead if no initial + context is currently established. + + We define a context as a snapshot of the parser stacks. We define + the initial context for a lookahead as the context in which the + parser initially examines that lookahead in order to select a + syntactic action. Thus, if the lookahead eventually proves + syntactically unacceptable (possibly in a later context reached via a + series of reductions), the initial context can be used to determine + the exact set of tokens that would be syntactically acceptable in the + lookahead's place. Moreover, it is the context after which any + further semantic actions would be erroneous because they would be + determined by a syntactically unacceptable token. + + YY_LAC_ESTABLISH should be invoked when a reduction is about to be + performed in an inconsistent state (which, for the purposes of LAC, + includes consistent states that don't know they're consistent because + their default reductions have been disabled). Iff there is a + lookahead token, it should also be invoked before reporting a syntax + error. This latter case is for the sake of the debugging output. + + For parse.lac=full, the implementation of YY_LAC_ESTABLISH is as + follows. If no initial context is currently established for the + current lookahead, then check if that lookahead can eventually be + shifted if syntactic actions continue from the current context. + Report a syntax error if it cannot. */ +#define YY_LAC_ESTABLISH \ +do { \ + if (!yy_lac_established) \ + { \ + YYDPRINTF ((stderr, \ + "LAC: initial context established for %s\n", \ + yytname[yytoken])); \ + yy_lac_established = 1; \ + { \ + int yy_lac_status = \ + yy_lac (yyesa, &yyes, &yyes_capacity, yyssp, yytoken); \ + if (yy_lac_status == 2) \ + goto yyexhaustedlab; \ + if (yy_lac_status == 1) \ + goto yyerrlab; \ + } \ + } \ +} while (0) + +/* Discard any previous initial lookahead context because of Event, + which may be a lookahead change or an invalidation of the currently + established initial context for the current lookahead. + + The most common example of a lookahead change is a shift. An example + of both cases is syntax error recovery. That is, a syntax error + occurs when the lookahead is syntactically erroneous for the + currently established initial context, so error recovery manipulates + the parser stacks to try to find a new initial context in which the + current lookahead is syntactically acceptable. If it fails to find + such a context, it discards the lookahead. */ +#if GRAM_DEBUG +# define YY_LAC_DISCARD(Event) \ +do { \ + if (yy_lac_established) \ + { \ + if (yydebug) \ + YYFPRINTF (stderr, "LAC: initial context discarded due to " \ + Event "\n"); \ + yy_lac_established = 0; \ + } \ +} while (0) +#else +# define YY_LAC_DISCARD(Event) yy_lac_established = 0 +#endif + +/* Given the stack whose top is *YYSSP, return 0 iff YYTOKEN can + eventually (after perhaps some reductions) be shifted, return 1 if + not, or return 2 if memory is exhausted. As preconditions and + postconditions: *YYES_CAPACITY is the allocated size of the array to + which *YYES points, and either *YYES = YYESA or *YYES points to an + array allocated with YYSTACK_ALLOC. yy_lac may overwrite the + contents of either array, alter *YYES and *YYES_CAPACITY, and free + any old *YYES other than YYESA. */ +static int +yy_lac (yytype_int16 *yyesa, yytype_int16 **yyes, + YYSIZE_T *yyes_capacity, yytype_int16 *yyssp, int yytoken) +{ + yytype_int16 *yyes_prev = yyssp; + yytype_int16 *yyesp = yyes_prev; + YYDPRINTF ((stderr, "LAC: checking lookahead %s:", yytname[yytoken])); + if (yytoken == YYUNDEFTOK) + { + YYDPRINTF ((stderr, " Always Err\n")); + return 1; + } + while (1) + { + int yyrule = yypact[*yyesp]; + if (yypact_value_is_default (yyrule) + || (yyrule += yytoken) < 0 || YYLAST < yyrule + || yycheck[yyrule] != yytoken) + { + yyrule = yydefact[*yyesp]; + if (yyrule == 0) + { + YYDPRINTF ((stderr, " Err\n")); + return 1; + } + } + else + { + yyrule = yytable[yyrule]; + if (yytable_value_is_error (yyrule)) + { + YYDPRINTF ((stderr, " Err\n")); + return 1; + } + if (0 < yyrule) + { + YYDPRINTF ((stderr, " S%d\n", yyrule)); + return 0; + } + yyrule = -yyrule; + } + { + YYSIZE_T yylen = yyr2[yyrule]; + YYDPRINTF ((stderr, " R%d", yyrule - 1)); + if (yyesp != yyes_prev) + { + YYSIZE_T yysize = yyesp - *yyes + 1; + if (yylen < yysize) + { + yyesp -= yylen; + yylen = 0; + } + else + { + yylen -= yysize; + yyesp = yyes_prev; + } + } + if (yylen) + yyesp = yyes_prev -= yylen; + } + { + int yystate; + { + int yylhs = yyr1[yyrule] - YYNTOKENS; + yystate = yypgoto[yylhs] + *yyesp; + if (yystate < 0 || YYLAST < yystate + || yycheck[yystate] != *yyesp) + yystate = yydefgoto[yylhs]; + else + yystate = yytable[yystate]; + } + if (yyesp == yyes_prev) + { + yyesp = *yyes; + *yyesp = yystate; + } + else + { + if (yy_lac_stack_realloc (yyes_capacity, 1, +#if GRAM_DEBUG + " (", ")", +#endif + yyes, yyesa, &yyesp, yyes_prev)) + { + YYDPRINTF ((stderr, "\n")); + return 2; + } + *++yyesp = yystate; + } + YYDPRINTF ((stderr, " G%d", yystate)); + } + } +} + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +yystrlen (const char *yystr) +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +yystpcpy (char *yydest, const char *yysrc) +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. In order to see if a particular token T is a + valid looakhead, invoke yy_lac (YYESA, YYES, YYES_CAPACITY, YYSSP, T). + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store or if + yy_lac returned 2. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyesa, yytype_int16 **yyes, + YYSIZE_T *yyes_capacity, yytype_int16 *yyssp, int yytoken) +{ + YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULL; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; + + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + In the first two cases, it might appear that the current syntax + error should have been detected in the previous state when yy_lac + was invoked. However, at that time, there might have been a + different syntax error that discarded a different initial context + during error recovery, leaving behind the current lookahead. + */ + if (yytoken != YYEMPTY) + { + int yyn = yypact[*yyssp]; + YYDPRINTF ((stderr, "Constructing syntax error message\n")); + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + int yyx; + + for (yyx = 0; yyx < YYNTOKENS; ++yyx) + if (yyx != YYTERROR && yyx != YYUNDEFTOK) + { + { + int yy_lac_status = yy_lac (yyesa, yyes, yyes_capacity, + yyssp, yyx); + if (yy_lac_status == 2) + return 2; + if (yy_lac_status == 1) + continue; + } + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } +# if GRAM_DEBUG + else if (yydebug) + YYFPRINTF (stderr, "No expected tokens.\n"); +# endif + } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; +} +#endif /* YYERROR_VERBOSE */ + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp) +{ + YYUSE (yyvaluep); + YYUSE (yylocationp); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + + + +/*----------. +| yyparse. | +`----------*/ + +int +yyparse (void) +{ +/* The lookahead symbol. */ +int yychar; + + +/* The semantic value of the lookahead symbol. */ +/* Default value used for initialization, for pacifying older GCCs + or non-GCC compilers. */ +YY_INITIAL_VALUE (static YYSTYPE yyval_default;) +YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); + +/* Location data for the lookahead symbol. */ +static YYLTYPE yyloc_default +# if defined GRAM_LTYPE_IS_TRIVIAL && GRAM_LTYPE_IS_TRIVIAL + = { 1, 1, 1, 1 } +# endif +; +YYLTYPE yylloc = yyloc_default; + + /* Number of syntax errors so far. */ + int yynerrs; + + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + 'yyss': related to states. + 'yyvs': related to semantic values. + 'yyls': related to locations. + + Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls; + YYLTYPE *yylsp; + + /* The locations where the error started and ended. */ + YYLTYPE yyerror_range[3]; + + YYSIZE_T yystacksize; + + yytype_int16 yyesa[20]; + yytype_int16 *yyes; + YYSIZE_T yyes_capacity; + + int yy_lac_established = 0; + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + YYLTYPE yyloc; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; + yylsp = yyls = yylsa; + yystacksize = YYINITDEPTH; + + yyes = yyesa; + yyes_capacity = sizeof yyesa / sizeof *yyes; + if (YYMAXDEPTH < yyes_capacity) + yyes_capacity = YYMAXDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + +/* User initialization code. */ +#line 108 "src/parse-gram.y" /* yacc.c:1429 */ +{ + /* Bison's grammar can initial empty locations, hence a default + location is needed. */ + boundary_set (&yylloc.start, current_file, 1, 1); + boundary_set (&yylloc.end, current_file, 1, 1); +} + +#line 1833 "src/parse-gram.c" /* yacc.c:1429 */ + yylsp[0] = yylloc; + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + YYLTYPE *yyls1 = yyls; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yyls1, yysize * sizeof (*yylsp), + &yystacksize); + + yyls = yyls1; + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); + YYSTACK_RELOCATE (yyls_alloc, yyls); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + yylsp = yyls + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = yylex (&yylval, &yylloc); + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + { + YY_LAC_ESTABLISH; + goto yydefault; + } + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + YY_LAC_ESTABLISH; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + YY_LAC_DISCARD ("shift"); + + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + *++yylsp = yylloc; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + /* Default location. */ + YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); + YY_REDUCE_PRINT (yyn); + { + int yychar_backup = yychar; + switch (yyn) + { + case 6: +#line 280 "src/parse-gram.y" /* yacc.c:1646 */ + { + muscle_code_grow (union_seen ? "post_prologue" : "pre_prologue", + translate_code ((yyvsp[0].code), (yylsp[0]), true), (yylsp[0])); + code_scanner_last_string_free (); + } +#line 2033 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 7: +#line 286 "src/parse-gram.y" /* yacc.c:1646 */ + { + muscle_percent_define_ensure ((yyvsp[0].uniqstr), (yylsp[0]), true); + } +#line 2041 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 8: +#line 290 "src/parse-gram.y" /* yacc.c:1646 */ + { + muscle_percent_define_insert ((yyvsp[-1].uniqstr), (yylsp[-1]), (yyvsp[0].value).kind, (yyvsp[0].value).chars, + MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); + } +#line 2050 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 9: +#line 294 "src/parse-gram.y" /* yacc.c:1646 */ + { defines_flag = true; } +#line 2056 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 10: +#line 296 "src/parse-gram.y" /* yacc.c:1646 */ + { + defines_flag = true; + spec_defines_file = xstrdup ((yyvsp[0].code)); + } +#line 2065 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 11: +#line 301 "src/parse-gram.y" /* yacc.c:1646 */ + { + muscle_percent_define_insert ("parse.error", (yylsp[0]), muscle_keyword, + "verbose", + MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE); + } +#line 2075 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 12: +#line 306 "src/parse-gram.y" /* yacc.c:1646 */ + { expected_sr_conflicts = (yyvsp[0].integer); } +#line 2081 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 13: +#line 307 "src/parse-gram.y" /* yacc.c:1646 */ + { expected_rr_conflicts = (yyvsp[0].integer); } +#line 2087 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 14: +#line 308 "src/parse-gram.y" /* yacc.c:1646 */ + { spec_file_prefix = (yyvsp[0].code); } +#line 2093 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 15: +#line 310 "src/parse-gram.y" /* yacc.c:1646 */ + { + nondeterministic_parser = true; + glr_parser = true; + } +#line 2102 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 16: +#line 315 "src/parse-gram.y" /* yacc.c:1646 */ + { + muscle_code_grow ("initial_action", translate_code ((yyvsp[0].code), (yylsp[0]), false), (yylsp[0])); + code_scanner_last_string_free (); + } +#line 2111 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 17: +#line 319 "src/parse-gram.y" /* yacc.c:1646 */ + { language_argmatch ((yyvsp[0].code), grammar_prio, (yylsp[-1])); } +#line 2117 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 18: +#line 320 "src/parse-gram.y" /* yacc.c:1646 */ + { spec_name_prefix = (yyvsp[0].code); } +#line 2123 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 19: +#line 321 "src/parse-gram.y" /* yacc.c:1646 */ + { no_lines_flag = true; } +#line 2129 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 20: +#line 322 "src/parse-gram.y" /* yacc.c:1646 */ + { nondeterministic_parser = true; } +#line 2135 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 21: +#line 323 "src/parse-gram.y" /* yacc.c:1646 */ + { spec_outfile = (yyvsp[0].code); } +#line 2141 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 22: +#line 324 "src/parse-gram.y" /* yacc.c:1646 */ + { current_param = (yyvsp[0].param); } +#line 2147 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 23: +#line 324 "src/parse-gram.y" /* yacc.c:1646 */ + { current_param = param_none; } +#line 2153 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 24: +#line 325 "src/parse-gram.y" /* yacc.c:1646 */ + { version_check (&(yylsp[0]), (yyvsp[0].code)); } +#line 2159 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 25: +#line 327 "src/parse-gram.y" /* yacc.c:1646 */ + { + char const *skeleton_user = (yyvsp[0].code); + if (strchr (skeleton_user, '/')) + { + size_t dir_length = strlen (current_file); + char *skeleton_build; + while (dir_length && current_file[dir_length - 1] != '/') + --dir_length; + while (dir_length && current_file[dir_length - 1] == '/') + --dir_length; + skeleton_build = + xmalloc (dir_length + 1 + strlen (skeleton_user) + 1); + if (dir_length > 0) + { + memcpy (skeleton_build, current_file, dir_length); + skeleton_build[dir_length++] = '/'; + } + strcpy (skeleton_build + dir_length, skeleton_user); + skeleton_user = uniqstr_new (skeleton_build); + free (skeleton_build); + } + skeleton_arg (skeleton_user, grammar_prio, (yylsp[-1])); + } +#line 2187 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 26: +#line 350 "src/parse-gram.y" /* yacc.c:1646 */ + { token_table_flag = true; } +#line 2193 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 27: +#line 351 "src/parse-gram.y" /* yacc.c:1646 */ + { report_flag |= report_states; } +#line 2199 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 28: +#line 352 "src/parse-gram.y" /* yacc.c:1646 */ + { yacc_flag = true; } +#line 2205 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 30: +#line 357 "src/parse-gram.y" /* yacc.c:1646 */ + { add_param (current_param, (yyvsp[0].code), (yylsp[0])); } +#line 2211 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 31: +#line 358 "src/parse-gram.y" /* yacc.c:1646 */ + { add_param (current_param, (yyvsp[0].code), (yylsp[0])); } +#line 2217 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 34: +#line 370 "src/parse-gram.y" /* yacc.c:1646 */ + { + grammar_start_symbol_set ((yyvsp[0].symbol), (yylsp[0])); + } +#line 2225 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 35: +#line 374 "src/parse-gram.y" /* yacc.c:1646 */ + { + code_props code; + code_props_symbol_action_init (&code, (yyvsp[-1].code), (yylsp[-1])); + code_props_translate_code (&code); + { + symbol_list *list; + for (list = (yyvsp[0].list); list; list = list->next) + symbol_list_code_props_set (list, (yyvsp[-2].code_type), &code); + symbol_list_free ((yyvsp[0].list)); + } + } +#line 2241 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 36: +#line 386 "src/parse-gram.y" /* yacc.c:1646 */ + { + default_prec = true; + } +#line 2249 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 37: +#line 390 "src/parse-gram.y" /* yacc.c:1646 */ + { + default_prec = false; + } +#line 2257 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 38: +#line 394 "src/parse-gram.y" /* yacc.c:1646 */ + { + /* Do not invoke muscle_percent_code_grow here since it invokes + muscle_user_name_list_grow. */ + muscle_code_grow ("percent_code()", + translate_code_braceless ((yyvsp[0].code), (yylsp[0])), (yylsp[0])); + code_scanner_last_string_free (); + } +#line 2269 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 39: +#line 402 "src/parse-gram.y" /* yacc.c:1646 */ + { + muscle_percent_code_grow ((yyvsp[-1].uniqstr), (yylsp[-1]), translate_code_braceless ((yyvsp[0].code), (yylsp[0])), (yylsp[0])); + code_scanner_last_string_free (); + } +#line 2278 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 40: +#line 412 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.code_type) = destructor; } +#line 2284 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 41: +#line 413 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.code_type) = printer; } +#line 2290 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 42: +#line 423 "src/parse-gram.y" /* yacc.c:1646 */ + {} +#line 2296 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 43: +#line 424 "src/parse-gram.y" /* yacc.c:1646 */ + { muscle_code_grow ("union_name", (yyvsp[0].uniqstr), (yylsp[0])); } +#line 2302 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 44: +#line 429 "src/parse-gram.y" /* yacc.c:1646 */ + { + union_seen = true; + muscle_code_grow ("union_members", translate_code_braceless ((yyvsp[0].code), (yylsp[0])), (yylsp[0])); + code_scanner_last_string_free (); + } +#line 2312 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 45: +#line 440 "src/parse-gram.y" /* yacc.c:1646 */ + { current_class = nterm_sym; } +#line 2318 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 46: +#line 441 "src/parse-gram.y" /* yacc.c:1646 */ + { + current_class = unknown_sym; + current_type = NULL; + } +#line 2327 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 47: +#line 445 "src/parse-gram.y" /* yacc.c:1646 */ + { current_class = token_sym; } +#line 2333 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 48: +#line 446 "src/parse-gram.y" /* yacc.c:1646 */ + { + current_class = unknown_sym; + current_type = NULL; + } +#line 2342 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 49: +#line 451 "src/parse-gram.y" /* yacc.c:1646 */ + { + symbol_list *list; + tag_seen = true; + for (list = (yyvsp[0].list); list; list = list->next) + symbol_type_set (list->content.sym, (yyvsp[-1].uniqstr), (yylsp[-1])); + symbol_list_free ((yyvsp[0].list)); + } +#line 2354 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 50: +#line 462 "src/parse-gram.y" /* yacc.c:1646 */ + { + symbol_list *list; + ++current_prec; + for (list = (yyvsp[0].list); list; list = list->next) + { + symbol_type_set (list->content.sym, current_type, (yylsp[-1])); + symbol_precedence_set (list->content.sym, current_prec, (yyvsp[-2].assoc), (yylsp[-2])); + } + symbol_list_free ((yyvsp[0].list)); + current_type = NULL; + } +#line 2370 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 51: +#line 476 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.assoc) = left_assoc; } +#line 2376 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 52: +#line 477 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.assoc) = right_assoc; } +#line 2382 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 53: +#line 478 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.assoc) = non_assoc; } +#line 2388 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 54: +#line 479 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.assoc) = precedence_assoc; } +#line 2394 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 55: +#line 483 "src/parse-gram.y" /* yacc.c:1646 */ + { current_type = NULL; } +#line 2400 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 56: +#line 484 "src/parse-gram.y" /* yacc.c:1646 */ + { current_type = (yyvsp[0].uniqstr); tag_seen = true; } +#line 2406 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 57: +#line 490 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); } +#line 2412 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 58: +#line 492 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.list) = symbol_list_append ((yyvsp[-1].list), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); } +#line 2418 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 59: +#line 497 "src/parse-gram.y" /* yacc.c:1646 */ + { + (yyval.symbol) = (yyvsp[0].symbol); + symbol_class_set ((yyvsp[0].symbol), token_sym, (yylsp[0]), false); + } +#line 2427 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 60: +#line 502 "src/parse-gram.y" /* yacc.c:1646 */ + { + (yyval.symbol) = (yyvsp[-1].symbol); + symbol_user_token_number_set ((yyvsp[-1].symbol), (yyvsp[0].integer), (yylsp[0])); + symbol_class_set ((yyvsp[-1].symbol), token_sym, (yylsp[-1]), false); + } +#line 2437 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 61: +#line 512 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); } +#line 2443 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 62: +#line 514 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.list) = symbol_list_append ((yyvsp[-1].list), symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0]))); } +#line 2449 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 63: +#line 518 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.list) = (yyvsp[0].list); } +#line 2455 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 64: +#line 519 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.list) = symbol_list_append ((yyvsp[-1].list), (yyvsp[0].list)); } +#line 2461 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 65: +#line 523 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.list) = symbol_list_sym_new ((yyvsp[0].symbol), (yylsp[0])); } +#line 2467 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 66: +#line 524 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.list) = symbol_list_type_new ((yyvsp[0].uniqstr), (yylsp[0])); } +#line 2473 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 68: +#line 529 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.uniqstr) = uniqstr_new ("*"); } +#line 2479 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 69: +#line 530 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.uniqstr) = uniqstr_new (""); } +#line 2485 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 70: +#line 536 "src/parse-gram.y" /* yacc.c:1646 */ + { + current_type = (yyvsp[0].uniqstr); + tag_seen = true; + } +#line 2494 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 71: +#line 541 "src/parse-gram.y" /* yacc.c:1646 */ + { + symbol_class_set ((yyvsp[0].symbol), current_class, (yylsp[0]), true); + symbol_type_set ((yyvsp[0].symbol), current_type, (yylsp[0])); + } +#line 2503 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 72: +#line 546 "src/parse-gram.y" /* yacc.c:1646 */ + { + symbol_class_set ((yyvsp[-1].symbol), current_class, (yylsp[-1]), true); + symbol_type_set ((yyvsp[-1].symbol), current_type, (yylsp[-1])); + symbol_user_token_number_set ((yyvsp[-1].symbol), (yyvsp[0].integer), (yylsp[0])); + } +#line 2513 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 73: +#line 552 "src/parse-gram.y" /* yacc.c:1646 */ + { + symbol_class_set ((yyvsp[-1].symbol), current_class, (yylsp[-1]), true); + symbol_type_set ((yyvsp[-1].symbol), current_type, (yylsp[-1])); + symbol_make_alias ((yyvsp[-1].symbol), (yyvsp[0].symbol), (yyloc)); + } +#line 2523 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 74: +#line 558 "src/parse-gram.y" /* yacc.c:1646 */ + { + symbol_class_set ((yyvsp[-2].symbol), current_class, (yylsp[-2]), true); + symbol_type_set ((yyvsp[-2].symbol), current_type, (yylsp[-2])); + symbol_user_token_number_set ((yyvsp[-2].symbol), (yyvsp[-1].integer), (yylsp[-1])); + symbol_make_alias ((yyvsp[-2].symbol), (yyvsp[0].symbol), (yyloc)); + } +#line 2534 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 81: +#line 588 "src/parse-gram.y" /* yacc.c:1646 */ + { + yyerrok; + } +#line 2542 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 82: +#line 594 "src/parse-gram.y" /* yacc.c:1646 */ + { current_lhs ((yyvsp[-1].symbol), (yylsp[-1]), (yyvsp[0].named_ref)); } +#line 2548 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 83: +#line 595 "src/parse-gram.y" /* yacc.c:1646 */ + { + /* Free the current lhs. */ + current_lhs (0, (yylsp[-3]), 0); + } +#line 2557 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 84: +#line 602 "src/parse-gram.y" /* yacc.c:1646 */ + { grammar_current_rule_end ((yylsp[0])); } +#line 2563 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 85: +#line 603 "src/parse-gram.y" /* yacc.c:1646 */ + { grammar_current_rule_end ((yylsp[0])); } +#line 2569 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 87: +#line 610 "src/parse-gram.y" /* yacc.c:1646 */ + { grammar_current_rule_begin (current_lhs_symbol, current_lhs_location, + current_lhs_named_ref); } +#line 2576 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 88: +#line 613 "src/parse-gram.y" /* yacc.c:1646 */ + { grammar_current_rule_symbol_append ((yyvsp[-1].symbol), (yylsp[-1]), (yyvsp[0].named_ref)); } +#line 2582 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 89: +#line 615 "src/parse-gram.y" /* yacc.c:1646 */ + { grammar_current_rule_action_append ((yyvsp[-1].code), (yylsp[-1]), (yyvsp[0].named_ref), false); } +#line 2588 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 90: +#line 617 "src/parse-gram.y" /* yacc.c:1646 */ + { grammar_current_rule_action_append ((yyvsp[0].code), (yylsp[0]), NULL, true); } +#line 2594 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 91: +#line 619 "src/parse-gram.y" /* yacc.c:1646 */ + { grammar_current_rule_empty_set ((yylsp[0])); } +#line 2600 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 92: +#line 621 "src/parse-gram.y" /* yacc.c:1646 */ + { grammar_current_rule_prec_set ((yyvsp[0].symbol), (yylsp[0])); } +#line 2606 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 93: +#line 623 "src/parse-gram.y" /* yacc.c:1646 */ + { grammar_current_rule_dprec_set ((yyvsp[0].integer), (yylsp[0])); } +#line 2612 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 94: +#line 625 "src/parse-gram.y" /* yacc.c:1646 */ + { grammar_current_rule_merge_set ((yyvsp[0].uniqstr), (yylsp[0])); } +#line 2618 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 95: +#line 629 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.named_ref) = 0; } +#line 2624 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 96: +#line 630 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.named_ref) = named_ref_new ((yyvsp[0].uniqstr), (yylsp[0])); } +#line 2630 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 98: +#line 641 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.uniqstr) = uniqstr_new ((yyvsp[0].code)); } +#line 2636 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 99: +#line 666 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.value).kind = muscle_keyword; (yyval.value).chars = ""; } +#line 2642 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 100: +#line 667 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.value).kind = muscle_keyword; (yyval.value).chars = (yyvsp[0].uniqstr); } +#line 2648 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 101: +#line 668 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.value).kind = muscle_string; (yyval.value).chars = (yyvsp[0].code); } +#line 2654 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 102: +#line 669 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.value).kind = muscle_code; (yyval.value).chars = strip_braces ((yyvsp[0].code)); } +#line 2660 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 103: +#line 682 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[0].uniqstr), (yylsp[0])); } +#line 2666 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 104: +#line 684 "src/parse-gram.y" /* yacc.c:1646 */ + { + (yyval.symbol) = symbol_get (char_name ((yyvsp[0].character)), (yylsp[0])); + symbol_class_set ((yyval.symbol), token_sym, (yylsp[0]), false); + symbol_user_token_number_set ((yyval.symbol), (yyvsp[0].character), (yylsp[0])); + } +#line 2676 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 105: +#line 692 "src/parse-gram.y" /* yacc.c:1646 */ + { (yyval.symbol) = symbol_from_uniqstr ((yyvsp[0].uniqstr), (yylsp[0])); } +#line 2682 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 108: +#line 704 "src/parse-gram.y" /* yacc.c:1646 */ + { + (yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[0].code)), (yylsp[0])); + symbol_class_set ((yyval.symbol), token_sym, (yylsp[0]), false); + } +#line 2691 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + case 110: +#line 713 "src/parse-gram.y" /* yacc.c:1646 */ + { + muscle_code_grow ("epilogue", translate_code ((yyvsp[0].code), (yylsp[0]), true), (yylsp[0])); + code_scanner_last_string_free (); + } +#line 2700 "src/parse-gram.c" /* yacc.c:1646 */ + break; + + +#line 2704 "src/parse-gram.c" /* yacc.c:1646 */ + default: break; + } + if (yychar_backup != yychar) + YY_LAC_DISCARD ("yychar change"); + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + *++yylsp = yyloc; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (&yylloc, YY_("syntax error")); +#else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyesa, &yyes, &yyes_capacity, \ + yyssp, yytoken) + { + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + if (yychar != YYEMPTY) + YY_LAC_ESTABLISH; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (&yylloc, yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; + } +# undef YYSYNTAX_ERROR +#endif + } + + yyerror_range[1] = yylloc; + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval, &yylloc); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + yyerror_range[1] = yylsp[1-yylen]; + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + yyerror_range[1] = *yylsp; + yydestruct ("Error: popping", + yystos[yystate], yyvsp, yylsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + /* If the stack popping above didn't lose the initial context for the + current lookahead token, the shift below will for sure. */ + YY_LAC_DISCARD ("error recovery"); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + yyerror_range[2] = yylloc; + /* Using YYLLOC is tempting, but would change the location of + the lookahead. YYLOC is available though. */ + YYLLOC_DEFAULT (yyloc, yyerror_range, 2); + *++yylsp = yyloc; + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if 1 +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (&yylloc, YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, &yylloc); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp, yylsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + if (yyes != yyesa) + YYSTACK_FREE (yyes); +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + return yyresult; +} +#line 719 "src/parse-gram.y" /* yacc.c:1906 */ + + +/* Return the location of the left-hand side of a rule whose + right-hand side is RHS[1] ... RHS[N]. Ignore empty nonterminals in + the right-hand side, and return an empty location equal to the end + boundary of RHS[0] if the right-hand side is empty. */ + +static YYLTYPE +lloc_default (YYLTYPE const *rhs, int n) +{ + int i; + YYLTYPE loc; + + /* SGI MIPSpro 7.4.1m miscompiles "loc.start = loc.end = rhs[n].end;". + The bug is fixed in 7.4.2m, but play it safe for now. */ + loc.start = rhs[n].end; + loc.end = rhs[n].end; + + /* Ignore empty nonterminals the start of the right-hand side. + Do not bother to ignore them at the end of the right-hand side, + since empty nonterminals have the same end as their predecessors. */ + for (i = 1; i <= n; i++) + if (! equal_boundaries (rhs[i].start, rhs[i].end)) + { + loc.start = rhs[i].start; + break; + } + + return loc; +} + +static +char *strip_braces (char *code) +{ + code[strlen (code) - 1] = 0; + return code + 1; +} + +static +char const * +translate_code (char *code, location loc, bool plain) +{ + code_props plain_code; + if (plain) + code_props_plain_init (&plain_code, code, loc); + else + code_props_symbol_action_init (&plain_code, code, loc); + code_props_translate_code (&plain_code); + gram_scanner_last_string_free (); + return plain_code.code; +} + +static +char const * +translate_code_braceless (char *code, location loc) +{ + return translate_code (strip_braces (code), loc, true); +} + +static void +add_param (param_type type, char *decl, location loc) +{ + static char const alphanum[26 + 26 + 1 + 10] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "_" + "0123456789"; + + char const *name_start = NULL; + { + char *p; + /* Stop on last actual character. */ + for (p = decl; p[1]; p++) + if ((p == decl + || ! memchr (alphanum, p[-1], sizeof alphanum)) + && memchr (alphanum, p[0], sizeof alphanum - 10)) + name_start = p; + + /* Strip the surrounding '{' and '}', and any blanks just inside + the braces. */ + --p; + while (c_isspace ((unsigned char) *p)) + --p; + p[1] = '\0'; + ++decl; + while (c_isspace ((unsigned char) *decl)) + ++decl; + } + + if (! name_start) + complain (&loc, complaint, _("missing identifier in parameter declaration")); + else + { + char *name = xmemdup0 (name_start, strspn (name_start, alphanum)); + if (type & param_lex) + muscle_pair_list_grow ("lex_param", decl, name); + if (type & param_parse) + muscle_pair_list_grow ("parse_param", decl, name); + free (name); + } + + gram_scanner_last_string_free (); +} + + +static void +version_check (location const *loc, char const *version) +{ + if (strverscmp (version, PACKAGE_VERSION) > 0) + { + complain (loc, complaint, "require bison %s, but have %s", + version, PACKAGE_VERSION); + exit (EX_MISMATCH); + } +} + +static void +gram_error (location const *loc, char const *msg) +{ + complain (loc, complaint, "%s", msg); +} + +char const * +token_name (int type) +{ + return yytname[YYTRANSLATE (type)]; +} + +static char const * +char_name (char c) +{ + if (c == '\'') + return "'\\''"; + else + { + char buf[4]; + buf[0] = '\''; buf[1] = c; buf[2] = '\''; buf[3] = '\0'; + return quotearg_style (escape_quoting_style, buf); + } +} + +static +void +current_lhs (symbol *sym, location loc, named_ref *ref) +{ + current_lhs_symbol = sym; + current_lhs_location = loc; + /* In order to simplify memory management, named references for lhs + are always assigned by deep copy into the current symbol_list + node. This is because a single named-ref in the grammar may + result in several uses when the user factors lhs between several + rules using "|". Therefore free the parser's original copy. */ + free (current_lhs_named_ref); + current_lhs_named_ref = ref; +} diff --git a/contrib/tools/bison/src/parse-gram.h b/contrib/tools/bison/src/parse-gram.h new file mode 100644 index 0000000000..09358961d3 --- /dev/null +++ b/contrib/tools/bison/src/parse-gram.h @@ -0,0 +1,190 @@ +/* A Bison parser, made by GNU Bison 3.0. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED +# define YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED +/* Debug traces. */ +#ifndef GRAM_DEBUG +# if defined YYDEBUG +#if YYDEBUG +# define GRAM_DEBUG 1 +# else +# define GRAM_DEBUG 0 +# endif +# else /* ! defined YYDEBUG */ +# define GRAM_DEBUG 1 +# endif /* ! defined YYDEBUG */ +#endif /* ! defined GRAM_DEBUG */ +#if GRAM_DEBUG +extern int gram_debug; +#endif +/* "%code requires" blocks. */ +#line 21 "src/parse-gram.y" /* yacc.c:1909 */ + + #include "symlist.h" + #include "symtab.h" +#line 221 "src/parse-gram.y" /* yacc.c:1909 */ + + typedef enum + { + param_none = 0, + param_lex = 1 << 0, + param_parse = 1 << 1, + param_both = param_lex | param_parse + } param_type; +#line 645 "src/parse-gram.y" /* yacc.c:1909 */ +#include "muscle-tab.h" + +#line 68 "src/parse-gram.h" /* yacc.c:1909 */ + +/* Token type. */ +#ifndef GRAM_TOKENTYPE +# define GRAM_TOKENTYPE + enum gram_tokentype + { + GRAM_EOF = 0, + STRING = 258, + PERCENT_TOKEN = 259, + PERCENT_NTERM = 260, + PERCENT_TYPE = 261, + PERCENT_DESTRUCTOR = 262, + PERCENT_PRINTER = 263, + PERCENT_LEFT = 264, + PERCENT_RIGHT = 265, + PERCENT_NONASSOC = 266, + PERCENT_PRECEDENCE = 267, + PERCENT_PREC = 268, + PERCENT_DPREC = 269, + PERCENT_MERGE = 270, + PERCENT_CODE = 271, + PERCENT_DEFAULT_PREC = 272, + PERCENT_DEFINE = 273, + PERCENT_DEFINES = 274, + PERCENT_ERROR_VERBOSE = 275, + PERCENT_EXPECT = 276, + PERCENT_EXPECT_RR = 277, + PERCENT_FLAG = 278, + PERCENT_FILE_PREFIX = 279, + PERCENT_GLR_PARSER = 280, + PERCENT_INITIAL_ACTION = 281, + PERCENT_LANGUAGE = 282, + PERCENT_NAME_PREFIX = 283, + PERCENT_NO_DEFAULT_PREC = 284, + PERCENT_NO_LINES = 285, + PERCENT_NONDETERMINISTIC_PARSER = 286, + PERCENT_OUTPUT = 287, + PERCENT_REQUIRE = 288, + PERCENT_SKELETON = 289, + PERCENT_START = 290, + PERCENT_TOKEN_TABLE = 291, + PERCENT_VERBOSE = 292, + PERCENT_YACC = 293, + BRACED_CODE = 294, + BRACED_PREDICATE = 295, + BRACKETED_ID = 296, + CHAR = 297, + EPILOGUE = 298, + EQUAL = 299, + ID = 300, + ID_COLON = 301, + PERCENT_PERCENT = 302, + PIPE = 303, + PROLOGUE = 304, + SEMICOLON = 305, + TAG = 306, + TAG_ANY = 307, + TAG_NONE = 308, + INT = 309, + PERCENT_PARAM = 310, + PERCENT_UNION = 311, + PERCENT_EMPTY = 312 + }; +#endif + +/* Value type. */ +#if ! defined GRAM_STYPE && ! defined GRAM_STYPE_IS_DECLARED +typedef union GRAM_STYPE GRAM_STYPE; +union GRAM_STYPE +{ +#line 182 "src/parse-gram.y" /* yacc.c:1909 */ +unsigned char character; +#line 186 "src/parse-gram.y" /* yacc.c:1909 */ +char *code; +#line 191 "src/parse-gram.y" /* yacc.c:1909 */ +uniqstr uniqstr; +#line 199 "src/parse-gram.y" /* yacc.c:1909 */ +int integer; +#line 203 "src/parse-gram.y" /* yacc.c:1909 */ +symbol *symbol; +#line 208 "src/parse-gram.y" /* yacc.c:1909 */ +assoc assoc; +#line 211 "src/parse-gram.y" /* yacc.c:1909 */ +symbol_list *list; +#line 214 "src/parse-gram.y" /* yacc.c:1909 */ +named_ref *named_ref; +#line 241 "src/parse-gram.y" /* yacc.c:1909 */ +param_type param; +#line 409 "src/parse-gram.y" /* yacc.c:1909 */ +code_props_type code_type; +#line 647 "src/parse-gram.y" /* yacc.c:1909 */ + + struct + { + char const *chars; + muscle_kind kind; + } value; + +#line 167 "src/parse-gram.h" /* yacc.c:1909 */ +}; +# define GRAM_STYPE_IS_TRIVIAL 1 +# define GRAM_STYPE_IS_DECLARED 1 +#endif + +/* Location type. */ +#if ! defined GRAM_LTYPE && ! defined GRAM_LTYPE_IS_DECLARED +typedef struct GRAM_LTYPE GRAM_LTYPE; +struct GRAM_LTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +}; +# define GRAM_LTYPE_IS_DECLARED 1 +# define GRAM_LTYPE_IS_TRIVIAL 1 +#endif + + + +int gram_parse (void); + +#endif /* !YY_GRAM_SRC_PARSE_GRAM_H_INCLUDED */ diff --git a/contrib/tools/bison/src/print-xml.c b/contrib/tools/bison/src/print-xml.c new file mode 100644 index 0000000000..c30da729db --- /dev/null +++ b/contrib/tools/bison/src/print-xml.c @@ -0,0 +1,545 @@ +/* Print an xml on generated parser, for Bison, + + Copyright (C) 2007, 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "string--.h" +#include "system.h" + +#include <stdarg.h> + +#include <bitset.h> + +#include "LR0.h" +#include "closure.h" +#include "conflicts.h" +#include "files.h" +#include "getargs.h" +#include "gram.h" +#include "lalr.h" +#include "print.h" +#include "print-xml.h" +#include "reader.h" +#include "reduce.h" +#include "state.h" +#include "symtab.h" +#include "tables.h" + +static bitset no_reduce_set; +struct escape_buf +{ + char *ptr; + size_t size; +}; +enum { num_escape_bufs = 3 }; +static struct escape_buf escape_bufs[num_escape_bufs]; + + +/*--------------------------------. +| Report information on a state. | +`--------------------------------*/ + +static void +print_core (FILE *out, int level, state *s) +{ + size_t i; + item_number *sitems = s->items; + size_t snritems = s->nitems; + + /* Output all the items of a state, not only its kernel. */ + closure (sitems, snritems); + sitems = itemset; + snritems = nitemset; + + if (!snritems) { + xml_puts (out, level, "<itemset/>"); + return; + } + + xml_puts (out, level, "<itemset>"); + + for (i = 0; i < snritems; i++) + { + bool printed = false; + item_number *sp; + item_number *sp1; + rule_number r; + + sp1 = sp = ritem + sitems[i]; + + while (*sp >= 0) + sp++; + + r = item_number_as_rule_number (*sp); + sp = rules[r].rhs; + + /* Display the lookahead tokens? */ + if (item_number_is_rule_number (*sp1)) + { + reductions *reds = s->reductions; + int red = state_reduction_find (s, &rules[r]); + /* Print item with lookaheads if there are. */ + if (reds->lookahead_tokens && red != -1) + { + xml_printf (out, level + 1, + "<item rule-number=\"%d\" point=\"%d\">", + rules[r].number, sp1 - sp); + state_rule_lookahead_tokens_print_xml (s, &rules[r], + out, level + 2); + xml_puts (out, level + 1, "</item>"); + printed = true; + } + } + + if (!printed) + { + xml_printf (out, level + 1, + "<item rule-number=\"%d\" point=\"%d\"/>", + rules[r].number, + sp1 - sp); + } + } + xml_puts (out, level, "</itemset>"); +} + + +/*-----------------------------------------------------------. +| Report the shifts if DISPLAY_SHIFTS_P or the gotos of S on | +| OUT. | +`-----------------------------------------------------------*/ + +static void +print_transitions (state *s, FILE *out, int level) +{ + transitions *trans = s->transitions; + int n = 0; + int i; + + for (i = 0; i < trans->num; i++) + if (!TRANSITION_IS_DISABLED (trans, i)) + { + n++; + } + + /* Nothing to report. */ + if (!n) { + xml_puts (out, level, "<transitions/>"); + return; + } + + /* Report lookahead tokens and shifts. */ + xml_puts (out, level, "<transitions>"); + + for (i = 0; i < trans->num; i++) + if (!TRANSITION_IS_DISABLED (trans, i) + && TRANSITION_IS_SHIFT (trans, i)) + { + symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)]; + char const *tag = sym->tag; + state *s1 = trans->states[i]; + + xml_printf (out, level + 1, + "<transition type=\"shift\" symbol=\"%s\" state=\"%d\"/>", + xml_escape (tag), s1->number); + } + + for (i = 0; i < trans->num; i++) + if (!TRANSITION_IS_DISABLED (trans, i) + && !TRANSITION_IS_SHIFT (trans, i)) + { + symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)]; + char const *tag = sym->tag; + state *s1 = trans->states[i]; + + xml_printf (out, level + 1, + "<transition type=\"goto\" symbol=\"%s\" state=\"%d\"/>", + xml_escape (tag), s1->number); + } + + xml_puts (out, level, "</transitions>"); +} + + +/*--------------------------------------------------------. +| Report the explicit errors of S raised from %nonassoc. | +`--------------------------------------------------------*/ + +static void +print_errs (FILE *out, int level, state *s) +{ + errs *errp = s->errs; + bool count = false; + int i; + + for (i = 0; i < errp->num; ++i) + if (errp->symbols[i]) + count = true; + + /* Nothing to report. */ + if (!count) { + xml_puts (out, level, "<errors/>"); + return; + } + + /* Report lookahead tokens and errors. */ + xml_puts (out, level, "<errors>"); + for (i = 0; i < errp->num; ++i) + if (errp->symbols[i]) + { + char const *tag = errp->symbols[i]->tag; + xml_printf (out, level + 1, + "<error symbol=\"%s\">nonassociative</error>", + xml_escape (tag)); + } + xml_puts (out, level, "</errors>"); +} + + +/*-------------------------------------------------------------------------. +| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be 'default'). | +| If not ENABLED, the rule is masked by a shift or a reduce (S/R and | +| R/R conflicts). | +`-------------------------------------------------------------------------*/ + +static void +print_reduction (FILE *out, int level, char const *lookahead_token, + rule *r, bool enabled) +{ + if (r->number) + xml_printf (out, level, + "<reduction symbol=\"%s\" rule=\"%d\" enabled=\"%s\"/>", + xml_escape (lookahead_token), + r->number, + enabled ? "true" : "false"); + else + xml_printf (out, level, + "<reduction symbol=\"%s\" rule=\"accept\" enabled=\"%s\"/>", + xml_escape (lookahead_token), + enabled ? "true" : "false"); +} + + +/*-------------------------------------------. +| Report on OUT the reduction actions of S. | +`-------------------------------------------*/ + +static void +print_reductions (FILE *out, int level, state *s) +{ + transitions *trans = s->transitions; + reductions *reds = s->reductions; + rule *default_reduction = NULL; + int report = false; + int i, j; + + if (reds->num == 0) + { + xml_puts (out, level, "<reductions/>"); + return; + } + + if (yydefact[s->number] != 0) + default_reduction = &rules[yydefact[s->number] - 1]; + + bitset_zero (no_reduce_set); + FOR_EACH_SHIFT (trans, i) + bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i)); + for (i = 0; i < s->errs->num; ++i) + if (s->errs->symbols[i]) + bitset_set (no_reduce_set, s->errs->symbols[i]->number); + + if (default_reduction) + report = true; + + if (reds->lookahead_tokens) + for (i = 0; i < ntokens; i++) + { + bool count = bitset_test (no_reduce_set, i); + + for (j = 0; j < reds->num; ++j) + if (bitset_test (reds->lookahead_tokens[j], i)) + { + if (! count) + { + if (reds->rules[j] != default_reduction) + report = true; + count = true; + } + else + { + report = true; + } + } + } + + /* Nothing to report. */ + if (!report) { + xml_puts (out, level, "<reductions/>"); + return; + } + + xml_puts (out, level, "<reductions>"); + + /* Report lookahead tokens (or $default) and reductions. */ + if (reds->lookahead_tokens) + for (i = 0; i < ntokens; i++) + { + bool defaulted = false; + bool count = bitset_test (no_reduce_set, i); + + for (j = 0; j < reds->num; ++j) + if (bitset_test (reds->lookahead_tokens[j], i)) + { + if (! count) + { + if (reds->rules[j] != default_reduction) + print_reduction (out, level + 1, symbols[i]->tag, + reds->rules[j], true); + else + defaulted = true; + count = true; + } + else + { + if (defaulted) + print_reduction (out, level + 1, symbols[i]->tag, + default_reduction, true); + defaulted = false; + print_reduction (out, level + 1, symbols[i]->tag, + reds->rules[j], false); + } + } + } + + if (default_reduction) + print_reduction (out, level + 1, + "$default", default_reduction, true); + + xml_puts (out, level, "</reductions>"); +} + + +/*--------------------------------------------------------------. +| Report on OUT all the actions (shifts, gotos, reductions, and | +| explicit erros from %nonassoc) of S. | +`--------------------------------------------------------------*/ + +static void +print_actions (FILE *out, int level, state *s) +{ + xml_puts (out, level, "<actions>"); + print_transitions (s, out, level + 1); + print_errs (out, level + 1, s); + print_reductions (out, level + 1, s); + xml_puts (out, level, "</actions>"); +} + + +/*----------------------------------. +| Report all the data on S on OUT. | +`----------------------------------*/ + +static void +print_state (FILE *out, int level, state *s) +{ + fputc ('\n', out); + xml_printf (out, level, "<state number=\"%d\">", s->number); + print_core (out, level + 1, s); + print_actions (out, level + 1, s); + if (s->solved_conflicts_xml) + { + xml_puts (out, level + 1, "<solved-conflicts>"); + fputs (s->solved_conflicts_xml, out); + xml_puts (out, level + 1, "</solved-conflicts>"); + } + else + xml_puts (out, level + 1, "<solved-conflicts/>"); + xml_puts (out, level, "</state>"); +} + + +/*-----------------------------------------. +| Print information on the whole grammar. | +`-----------------------------------------*/ + +static void +print_grammar (FILE *out, int level) +{ + symbol_number i; + + fputc ('\n', out); + xml_puts (out, level, "<grammar>"); + grammar_rules_print_xml (out, level); + + /* Terminals */ + xml_puts (out, level + 1, "<terminals>"); + for (i = 0; i < max_user_token_number + 1; i++) + if (token_translations[i] != undeftoken->number) + { + char const *tag = symbols[token_translations[i]]->tag; + int precedence = symbols[token_translations[i]]->prec; + assoc associativity = symbols[token_translations[i]]->assoc; + xml_indent (out, level + 2); + fprintf (out, + "<terminal symbol-number=\"%d\" token-number=\"%d\"" + " name=\"%s\" usefulness=\"%s\"", + token_translations[i], i, xml_escape (tag), + reduce_token_unused_in_grammar (token_translations[i]) + ? "unused-in-grammar" : "useful"); + if (precedence) + fprintf (out, " prec=\"%d\"", precedence); + if (associativity != undef_assoc) + fprintf (out, " assoc=\"%s\"", assoc_to_string (associativity) + 1); + fputs ("/>\n", out); + } + xml_puts (out, level + 1, "</terminals>"); + + /* Nonterminals */ + xml_puts (out, level + 1, "<nonterminals>"); + for (i = ntokens; i < nsyms + nuseless_nonterminals; i++) + { + char const *tag = symbols[i]->tag; + xml_printf (out, level + 2, + "<nonterminal symbol-number=\"%d\" name=\"%s\"" + " usefulness=\"%s\"/>", + i, xml_escape (tag), + reduce_nonterminal_useless_in_grammar (i) + ? "useless-in-grammar" : "useful"); + } + xml_puts (out, level + 1, "</nonterminals>"); + xml_puts (out, level, "</grammar>"); +} + +void +xml_indent (FILE *out, int level) +{ + int i; + for (i = 0; i < level; i++) + fputs (" ", out); +} + +void +xml_puts (FILE *out, int level, char const *s) +{ + xml_indent (out, level); + fputs (s, out); + fputc ('\n', out); +} + +void +xml_printf (FILE *out, int level, char const *fmt, ...) +{ + va_list arglist; + + xml_indent (out, level); + + va_start (arglist, fmt); + vfprintf (out, fmt, arglist); + va_end (arglist); + + fputc ('\n', out); +} + +static char const * +xml_escape_string (struct escape_buf *buf, char const *str) +{ + size_t len = strlen (str); + size_t max_expansion = sizeof """ - 1; + char *p; + + if (buf->size <= max_expansion * len) + { + buf->size = max_expansion * len + 1; + buf->ptr = x2realloc (buf->ptr, &buf->size); + } + p = buf->ptr; + + for (; *str; str++) + switch (*str) + { + default: *p++ = *str; break; + case '&': p = stpcpy (p, "&" ); break; + case '<': p = stpcpy (p, "<" ); break; + case '>': p = stpcpy (p, ">" ); break; + case '"': p = stpcpy (p, """); break; + } + + *p = '\0'; + return buf->ptr; +} + +char const * +xml_escape_n (int n, char const *str) +{ + return xml_escape_string (escape_bufs + n, str); +} + +char const * +xml_escape (char const *str) +{ + return xml_escape_n (0, str); +} + +void +print_xml (void) +{ + int level = 0; + + FILE *out = xfopen (spec_xml_file, "w"); + + fputs ("<?xml version=\"1.0\"?>\n\n", out); + xml_printf (out, level, + "<bison-xml-report version=\"%s\" bug-report=\"%s\"" + " url=\"%s\">", + xml_escape_n (0, VERSION), + xml_escape_n (1, PACKAGE_BUGREPORT), + xml_escape_n (2, PACKAGE_URL)); + + fputc ('\n', out); + xml_printf (out, level + 1, "<filename>%s</filename>", + xml_escape (grammar_file)); + + /* print grammar */ + print_grammar (out, level + 1); + + new_closure (nritems); + no_reduce_set = bitset_create (ntokens, BITSET_FIXED); + + /* print automaton */ + fputc ('\n', out); + xml_puts (out, level + 1, "<automaton>"); + { + state_number i; + for (i = 0; i < nstates; i++) + print_state (out, level + 2, states[i]); + } + xml_puts (out, level + 1, "</automaton>"); + + bitset_free (no_reduce_set); + free_closure (); + + xml_puts (out, 0, "</bison-xml-report>"); + + { + int i; + for (i = 0; i < num_escape_bufs; ++i) + free (escape_bufs[i].ptr); + } + + xfclose (out); +} diff --git a/contrib/tools/bison/src/print-xml.h b/contrib/tools/bison/src/print-xml.h new file mode 100644 index 0000000000..251c2033b9 --- /dev/null +++ b/contrib/tools/bison/src/print-xml.h @@ -0,0 +1,30 @@ +/* Output an xml of the generated parser, for Bison. + + Copyright (C) 2007, 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef PRINT_XML_H_ +# define PRINT_XML_H_ + +void xml_indent (FILE *out, int level); +void xml_puts (FILE *, int, char const *); +void xml_printf (FILE *, int, char const *, ...); +char const *xml_escape_n (int n, char const *str); +char const *xml_escape (char const *str); +void print_xml (void); + +#endif /* !PRINT_XML_H_ */ diff --git a/contrib/tools/bison/src/print.c b/contrib/tools/bison/src/print.c new file mode 100644 index 0000000000..824bb4ae82 --- /dev/null +++ b/contrib/tools/bison/src/print.c @@ -0,0 +1,529 @@ +/* Print information on generated parser, for bison, + + Copyright (C) 1984, 1986, 1989, 2000-2005, 2007, 2009-2013 Free + Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include <bitset.h> + +#include "LR0.h" +#include "closure.h" +#include "conflicts.h" +#include "files.h" +#include "getargs.h" +#include "gram.h" +#include "lalr.h" +#include "muscle-tab.h" +#include "print.h" +#include "reader.h" +#include "reduce.h" +#include "state.h" +#include "symtab.h" +#include "tables.h" + +static bitset no_reduce_set; + +#if 0 +static void +print_token (int extnum, int token) +{ + fprintf (out, _(" type %d is %s\n"), extnum, tags[token]); +} +#endif + + + +/*---------------------------------------. +| *WIDTH := max (*WIDTH, strlen (STR)). | +`---------------------------------------*/ + +static void +max_length (size_t *width, const char *str) +{ + size_t len = strlen (str); + if (len > *width) + *width = len; +} + +/*--------------------------------. +| Report information on a state. | +`--------------------------------*/ + +static void +print_core (FILE *out, state *s) +{ + size_t i; + item_number *sitems = s->items; + size_t snritems = s->nitems; + symbol *previous_lhs = NULL; + + /* Output all the items of a state, not only its kernel. */ + if (report_flag & report_itemsets) + { + closure (sitems, snritems); + sitems = itemset; + snritems = nitemset; + } + + if (!snritems) + return; + + fputc ('\n', out); + + for (i = 0; i < snritems; i++) + { + item_number *sp; + item_number *sp1; + rule_number r; + + sp1 = sp = ritem + sitems[i]; + + while (*sp >= 0) + sp++; + + r = item_number_as_rule_number (*sp); + + rule_lhs_print (&rules[r], previous_lhs, out); + previous_lhs = rules[r].lhs; + + for (sp = rules[r].rhs; sp < sp1; sp++) + fprintf (out, " %s", symbols[*sp]->tag); + fputs (" .", out); + for (/* Nothing */; *sp >= 0; ++sp) + fprintf (out, " %s", symbols[*sp]->tag); + + /* Display the lookahead tokens? */ + if (report_flag & report_lookahead_tokens + && item_number_is_rule_number (*sp1)) + state_rule_lookahead_tokens_print (s, &rules[r], out); + + fputc ('\n', out); + } +} + + +/*------------------------------------------------------------. +| Report the shifts iff DISPLAY_SHIFTS_P or the gotos of S on | +| OUT. | +`------------------------------------------------------------*/ + +static void +print_transitions (state *s, FILE *out, bool display_transitions_p) +{ + transitions *trans = s->transitions; + size_t width = 0; + int i; + + /* Compute the width of the lookahead token column. */ + for (i = 0; i < trans->num; i++) + if (!TRANSITION_IS_DISABLED (trans, i) + && TRANSITION_IS_SHIFT (trans, i) == display_transitions_p) + { + symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)]; + max_length (&width, sym->tag); + } + + /* Nothing to report. */ + if (!width) + return; + + fputc ('\n', out); + width += 2; + + /* Report lookahead tokens and shifts. */ + for (i = 0; i < trans->num; i++) + if (!TRANSITION_IS_DISABLED (trans, i) + && TRANSITION_IS_SHIFT (trans, i) == display_transitions_p) + { + symbol *sym = symbols[TRANSITION_SYMBOL (trans, i)]; + const char *tag = sym->tag; + state *s1 = trans->states[i]; + int j; + + fprintf (out, " %s", tag); + for (j = width - strlen (tag); j > 0; --j) + fputc (' ', out); + if (display_transitions_p) + fprintf (out, _("shift, and go to state %d\n"), s1->number); + else + fprintf (out, _("go to state %d\n"), s1->number); + } +} + + +/*--------------------------------------------------------. +| Report the explicit errors of S raised from %nonassoc. | +`--------------------------------------------------------*/ + +static void +print_errs (FILE *out, state *s) +{ + errs *errp = s->errs; + size_t width = 0; + int i; + + /* Compute the width of the lookahead token column. */ + for (i = 0; i < errp->num; ++i) + if (errp->symbols[i]) + max_length (&width, errp->symbols[i]->tag); + + /* Nothing to report. */ + if (!width) + return; + + fputc ('\n', out); + width += 2; + + /* Report lookahead tokens and errors. */ + for (i = 0; i < errp->num; ++i) + if (errp->symbols[i]) + { + const char *tag = errp->symbols[i]->tag; + int j; + fprintf (out, " %s", tag); + for (j = width - strlen (tag); j > 0; --j) + fputc (' ', out); + fputs (_("error (nonassociative)\n"), out); + } +} + + +/*-------------------------------------------------------------------------. +| Report a reduction of RULE on LOOKAHEAD_TOKEN (which can be 'default'). | +| If not ENABLED, the rule is masked by a shift or a reduce (S/R and | +| R/R conflicts). | +`-------------------------------------------------------------------------*/ + +static void +print_reduction (FILE *out, size_t width, + const char *lookahead_token, + rule *r, bool enabled) +{ + int j; + fprintf (out, " %s", lookahead_token); + for (j = width - strlen (lookahead_token); j > 0; --j) + fputc (' ', out); + if (!enabled) + fputc ('[', out); + if (r->number) + fprintf (out, _("reduce using rule %d (%s)"), r->number, r->lhs->tag); + else + fprintf (out, _("accept")); + if (!enabled) + fputc (']', out); + fputc ('\n', out); +} + + +/*-------------------------------------------. +| Report on OUT the reduction actions of S. | +`-------------------------------------------*/ + +static void +print_reductions (FILE *out, state *s) +{ + transitions *trans = s->transitions; + reductions *reds = s->reductions; + rule *default_reduction = NULL; + size_t width = 0; + int i, j; + bool default_reduction_only = true; + + if (reds->num == 0) + return; + + if (yydefact[s->number] != 0) + default_reduction = &rules[yydefact[s->number] - 1]; + + bitset_zero (no_reduce_set); + FOR_EACH_SHIFT (trans, i) + bitset_set (no_reduce_set, TRANSITION_SYMBOL (trans, i)); + for (i = 0; i < s->errs->num; ++i) + if (s->errs->symbols[i]) + bitset_set (no_reduce_set, s->errs->symbols[i]->number); + + /* Compute the width of the lookahead token column. */ + if (default_reduction) + width = strlen (_("$default")); + + if (reds->lookahead_tokens) + for (i = 0; i < ntokens; i++) + { + bool count = bitset_test (no_reduce_set, i); + + for (j = 0; j < reds->num; ++j) + if (bitset_test (reds->lookahead_tokens[j], i)) + { + if (! count) + { + if (reds->rules[j] != default_reduction) + max_length (&width, symbols[i]->tag); + count = true; + } + else + { + max_length (&width, symbols[i]->tag); + } + } + } + + /* Nothing to report. */ + if (!width) + return; + + fputc ('\n', out); + width += 2; + + /* Report lookahead tokens (or $default) and reductions. */ + if (reds->lookahead_tokens) + for (i = 0; i < ntokens; i++) + { + bool defaulted = false; + bool count = bitset_test (no_reduce_set, i); + if (count) + default_reduction_only = false; + + for (j = 0; j < reds->num; ++j) + if (bitset_test (reds->lookahead_tokens[j], i)) + { + if (! count) + { + if (reds->rules[j] != default_reduction) + { + default_reduction_only = false; + print_reduction (out, width, + symbols[i]->tag, + reds->rules[j], true); + } + else + defaulted = true; + count = true; + } + else + { + default_reduction_only = false; + if (defaulted) + print_reduction (out, width, + symbols[i]->tag, + default_reduction, true); + defaulted = false; + print_reduction (out, width, + symbols[i]->tag, + reds->rules[j], false); + } + } + } + + if (default_reduction) + { + char *default_reductions = + muscle_percent_define_get ("lr.default-reduction"); + print_reduction (out, width, _("$default"), default_reduction, true); + aver (STREQ (default_reductions, "most") + || (STREQ (default_reductions, "consistent") + && default_reduction_only) + || (reds->num == 1 && reds->rules[0]->number == 0)); + free (default_reductions); + } +} + + +/*--------------------------------------------------------------. +| Report on OUT all the actions (shifts, gotos, reductions, and | +| explicit erros from %nonassoc) of S. | +`--------------------------------------------------------------*/ + +static void +print_actions (FILE *out, state *s) +{ + /* Print shifts. */ + print_transitions (s, out, true); + print_errs (out, s); + print_reductions (out, s); + /* Print gotos. */ + print_transitions (s, out, false); +} + + +/*----------------------------------. +| Report all the data on S on OUT. | +`----------------------------------*/ + +static void +print_state (FILE *out, state *s) +{ + fputs ("\n\n", out); + fprintf (out, _("State %d"), s->number); + fputc ('\n', out); + print_core (out, s); + print_actions (out, s); + if ((report_flag & report_solved_conflicts) && s->solved_conflicts) + { + fputc ('\n', out); + fputs (s->solved_conflicts, out); + } +} + +/*-----------------------------------------. +| Print information on the whole grammar. | +`-----------------------------------------*/ + +#define END_TEST(End) \ + do { \ + if (column + strlen (buffer) > (End)) \ + { \ + fprintf (out, "%s\n ", buffer); \ + column = 3; \ + buffer[0] = 0; \ + } \ + } while (0) + + +static void +print_grammar (FILE *out) +{ + symbol_number i; + char buffer[90]; + int column = 0; + + grammar_rules_print (out); + + /* TERMINAL (type #) : rule #s terminal is on RHS */ + fprintf (out, "%s\n\n", _("Terminals, with rules where they appear")); + for (i = 0; i < max_user_token_number + 1; i++) + if (token_translations[i] != undeftoken->number) + { + const char *tag = symbols[token_translations[i]]->tag; + rule_number r; + item_number *rhsp; + + buffer[0] = 0; + column = strlen (tag); + fputs (tag, out); + END_TEST (65); + sprintf (buffer, " (%d)", i); + + for (r = 0; r < nrules; r++) + for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++) + if (item_number_as_symbol_number (*rhsp) == token_translations[i]) + { + END_TEST (65); + sprintf (buffer + strlen (buffer), " %d", r); + break; + } + fprintf (out, "%s\n", buffer); + } + fputs ("\n\n", out); + + + fprintf (out, "%s\n\n", _("Nonterminals, with rules where they appear")); + for (i = ntokens; i < nsyms; i++) + { + int left_count = 0, right_count = 0; + rule_number r; + const char *tag = symbols[i]->tag; + + for (r = 0; r < nrules; r++) + { + item_number *rhsp; + if (rules[r].lhs->number == i) + left_count++; + for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++) + if (item_number_as_symbol_number (*rhsp) == i) + { + right_count++; + break; + } + } + + buffer[0] = 0; + fputs (tag, out); + column = strlen (tag); + sprintf (buffer, " (%d)", i); + END_TEST (0); + + if (left_count > 0) + { + END_TEST (65); + sprintf (buffer + strlen (buffer), _(" on left:")); + + for (r = 0; r < nrules; r++) + { + if (rules[r].lhs->number == i) + { + END_TEST (65); + sprintf (buffer + strlen (buffer), " %d", r); + } + } + } + + if (right_count > 0) + { + if (left_count > 0) + sprintf (buffer + strlen (buffer), ","); + END_TEST (65); + sprintf (buffer + strlen (buffer), _(" on right:")); + for (r = 0; r < nrules; r++) + { + item_number *rhsp; + for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++) + if (item_number_as_symbol_number (*rhsp) == i) + { + END_TEST (65); + sprintf (buffer + strlen (buffer), " %d", r); + break; + } + } + } + fprintf (out, "%s\n", buffer); + } +} + +void +print_results (void) +{ + state_number i; + + /* We used to use just .out if SPEC_NAME_PREFIX (-p) was used, but + that conflicts with Posix. */ + FILE *out = xfopen (spec_verbose_file, "w"); + + reduce_output (out); + grammar_rules_partial_print (out, + _("Rules useless in parser due to conflicts"), + rule_useless_in_parser_p); + conflicts_output (out); + + print_grammar (out); + + /* If the whole state item sets, not only the kernels, are wanted, + 'closure' will be run, which needs memory allocation/deallocation. */ + if (report_flag & report_itemsets) + new_closure (nritems); + /* Storage for print_reductions. */ + no_reduce_set = bitset_create (ntokens, BITSET_FIXED); + for (i = 0; i < nstates; i++) + print_state (out, states[i]); + bitset_free (no_reduce_set); + if (report_flag & report_itemsets) + free_closure (); + + xfclose (out); +} diff --git a/contrib/tools/bison/src/print.h b/contrib/tools/bison/src/print.h new file mode 100644 index 0000000000..e1e254a9bc --- /dev/null +++ b/contrib/tools/bison/src/print.h @@ -0,0 +1,25 @@ +/* Print information on generated parser, for bison, + + Copyright (C) 2000, 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef PRINT_H_ +# define PRINT_H_ + +void print_results (void); + +#endif /* !PRINT_H_ */ diff --git a/contrib/tools/bison/src/print_graph.c b/contrib/tools/bison/src/print_graph.c new file mode 100644 index 0000000000..7e429dbd10 --- /dev/null +++ b/contrib/tools/bison/src/print_graph.c @@ -0,0 +1,193 @@ +/* Output a graph of the generated parser, for Bison. + + Copyright (C) 2001-2007, 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include "LR0.h" +#include "closure.h" +#include "complain.h" +#include "conflicts.h" +#include "files.h" +#include "getargs.h" +#include "gram.h" +#include "graphviz.h" +#include "lalr.h" +#include "print_graph.h" +#include "reader.h" +#include "state.h" +#include "symtab.h" + + +/*----------------------------. +| Construct the node labels. | +`----------------------------*/ + +/* Print the lhs of a rule in such a manner that there is no vertical + repetition, like in *.output files. */ + +static void +print_core (struct obstack *oout, state *s) +{ + item_number const *sitems = s->items; + symbol *previous_lhs = NULL; + size_t i; + size_t snritems = s->nitems; + + /* Output all the items of a state, not just its kernel. */ + if (report_flag & report_itemsets) + { + closure (sitems, snritems); + sitems = itemset; + snritems = nitemset; + } + + obstack_printf (oout, _("State %d"), s->number); + obstack_sgrow (oout, "\\n\\l"); + for (i = 0; i < snritems; i++) + { + item_number const *sp1 = ritem + sitems[i]; + item_number const *sp = sp1; + rule *r; + + while (0 <= *sp) + sp++; + + r = &rules[item_number_as_rule_number (*sp)]; + + obstack_printf (oout, "%3d ", r->number); + if (previous_lhs && UNIQSTR_EQ (previous_lhs->tag, r->lhs->tag)) + obstack_printf (oout, "%*s| ", + (int) strlen (previous_lhs->tag), ""); + else + obstack_printf (oout, "%s: ", escape (r->lhs->tag)); + previous_lhs = r->lhs; + + for (sp = r->rhs; sp < sp1; sp++) + obstack_printf (oout, "%s ", escape (symbols[*sp]->tag)); + + obstack_1grow (oout, '.'); + + for (/* Nothing */; *sp >= 0; ++sp) + obstack_printf (oout, " %s", escape (symbols[*sp]->tag)); + + /* Experimental feature: display the lookahead tokens. */ + if (report_flag & report_lookahead_tokens + && item_number_is_rule_number (*sp1)) + { + /* Find the reduction we are handling. */ + reductions *reds = s->reductions; + int redno = state_reduction_find (s, r); + + /* Print them if there are. */ + if (reds->lookahead_tokens && redno != -1) + { + bitset_iterator biter; + int k; + char const *sep = ""; + obstack_sgrow (oout, " ["); + BITSET_FOR_EACH (biter, reds->lookahead_tokens[redno], k, 0) + { + obstack_sgrow (oout, sep); + obstack_sgrow (oout, escape (symbols[k]->tag)); + sep = ", "; + } + obstack_1grow (oout, ']'); + } + } + obstack_sgrow (oout, "\\l"); + } +} + + +/*---------------------------------------------------------------. +| Output in graph_obstack edges specifications in incidence with | +| current node. | +`---------------------------------------------------------------*/ + +static void +print_actions (state const *s, FILE *fgraph) +{ + transitions const *trans = s->transitions; + int i; + + if (!trans->num && !s->reductions) + return; + + for (i = 0; i < trans->num; i++) + if (!TRANSITION_IS_DISABLED (trans, i)) + { + state *s1 = trans->states[i]; + symbol_number sym = s1->accessing_symbol; + + /* Shifts are solid, gotos are dashed, and error is dotted. */ + char const *style = + (TRANSITION_IS_ERROR (trans, i) ? "dotted" + : TRANSITION_IS_SHIFT (trans, i) ? "solid" + : "dashed"); + + if (TRANSITION_IS_ERROR (trans, i) + && STRNEQ (symbols[sym]->tag, "error")) + abort (); + output_edge (s->number, s1->number, + TRANSITION_IS_ERROR (trans, i) ? NULL : symbols[sym]->tag, + style, fgraph); + } + /* Display reductions. */ + output_red (s, s->reductions, fgraph); +} + + +/*-------------------------------------------------------------. +| Output in FGRAPH the current node specifications and exiting | +| edges. | +`-------------------------------------------------------------*/ + +static void +print_state (state *s, FILE *fgraph) +{ + struct obstack node_obstack; + + /* A node's label contains its items. */ + obstack_init (&node_obstack); + print_core (&node_obstack, s); + output_node (s->number, obstack_finish0 (&node_obstack), fgraph); + obstack_free (&node_obstack, 0); + + /* Output the edges. */ + print_actions (s, fgraph); +} + + +void +print_graph (void) +{ + state_number i; + FILE *fgraph = xfopen (spec_graph_file, "w"); + start_graph (fgraph); + + /* Output nodes and edges. */ + new_closure (nritems); + for (i = 0; i < nstates; i++) + print_state (states[i], fgraph); + free_closure (); + + finish_graph (fgraph); + xfclose (fgraph); +} diff --git a/contrib/tools/bison/src/print_graph.h b/contrib/tools/bison/src/print_graph.h new file mode 100644 index 0000000000..073ae988b6 --- /dev/null +++ b/contrib/tools/bison/src/print_graph.h @@ -0,0 +1,25 @@ +/* Output a graph of the generated parser, for Bison. + + Copyright (C) 2000, 2006, 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef PRINT_GRAPH_H_ +# define PRINT_GRAPH_H_ + +void print_graph (void); + +#endif /* !PRINT_GRAPH_H_ */ diff --git a/contrib/tools/bison/src/reader.c b/contrib/tools/bison/src/reader.c new file mode 100644 index 0000000000..95c595ed4e --- /dev/null +++ b/contrib/tools/bison/src/reader.c @@ -0,0 +1,796 @@ +/* Input parser for Bison + + Copyright (C) 1984, 1986, 1989, 1992, 1998, 2000-2003, 2005-2007, + 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include <quote.h> + +#include "complain.h" +#include "conflicts.h" +#include "files.h" +#include "getargs.h" +#include "gram.h" +#include "muscle-tab.h" +#include "reader.h" +#include "symlist.h" +#include "symtab.h" +#include "scan-gram.h" +#include "scan-code.h" + +static void prepare_percent_define_front_end_variables (void); +static void check_and_convert_grammar (void); + +static symbol_list *grammar = NULL; +static bool start_flag = false; +merger_list *merge_functions; + +/* Was %union seen? */ +bool union_seen = false; + +/* Was a tag seen? */ +bool tag_seen = false; + +/* Should rules have a default precedence? */ +bool default_prec = true; + +/*-----------------------. +| Set the start symbol. | +`-----------------------*/ + +void +grammar_start_symbol_set (symbol *sym, location loc) +{ + if (start_flag) + complain (&loc, complaint, _("multiple %s declarations"), "%start"); + else + { + start_flag = true; + startsymbol = sym; + startsymbol_location = loc; + } +} + + + +/*------------------------------------------------------------------------. +| Return the merger index for a merging function named NAME. Records the | +| function, if new, in MERGER_LIST. | +`------------------------------------------------------------------------*/ + +static int +get_merge_function (uniqstr name) +{ + merger_list *syms; + merger_list head; + int n; + + if (! glr_parser) + return 0; + + head.next = merge_functions; + for (syms = &head, n = 1; syms->next; syms = syms->next, n += 1) + if (UNIQSTR_EQ (name, syms->next->name)) + break; + if (syms->next == NULL) + { + syms->next = xmalloc (sizeof syms->next[0]); + syms->next->name = uniqstr_new (name); + /* After all symbol type declarations have been parsed, packgram invokes + record_merge_function_type to set the type. */ + syms->next->type = NULL; + syms->next->next = NULL; + merge_functions = head.next; + } + return n; +} + +/*-------------------------------------------------------------------------. +| For the existing merging function with index MERGER, record the result | +| type as TYPE as required by the lhs of the rule whose %merge declaration | +| is at DECLARATION_LOC. | +`-------------------------------------------------------------------------*/ + +static void +record_merge_function_type (int merger, uniqstr type, location declaration_loc) +{ + int merger_find; + merger_list *merge_function; + + if (merger <= 0) + return; + + if (type == NULL) + type = uniqstr_new (""); + + merger_find = 1; + for (merge_function = merge_functions; + merge_function != NULL && merger_find != merger; + merge_function = merge_function->next) + merger_find += 1; + aver (merge_function != NULL && merger_find == merger); + if (merge_function->type != NULL && !UNIQSTR_EQ (merge_function->type, type)) + { + unsigned indent = 0; + complain_indent (&declaration_loc, complaint, &indent, + _("result type clash on merge function %s: " + "<%s> != <%s>"), + quote (merge_function->name), type, + merge_function->type); + indent += SUB_INDENT; + complain_indent (&merge_function->type_declaration_location, complaint, + &indent, + _("previous declaration")); + } + merge_function->type = uniqstr_new (type); + merge_function->type_declaration_location = declaration_loc; +} + +/*--------------------------------------. +| Free all merge-function definitions. | +`--------------------------------------*/ + +void +free_merger_functions (void) +{ + merger_list *L0 = merge_functions; + while (L0) + { + merger_list *L1 = L0->next; + free (L0); + L0 = L1; + } +} + + +/*-------------------------------------------------------------------. +| Parse the input grammar into a one symbol_list structure. Each | +| rule is represented by a sequence of symbols: the left hand side | +| followed by the contents of the right hand side, followed by a | +| null pointer instead of a symbol to terminate the rule. The next | +| symbol is the lhs of the following rule. | +| | +| All actions are copied out, labelled by the rule number they apply | +| to. | +`-------------------------------------------------------------------*/ + +/* The (currently) last symbol of GRAMMAR. */ +static symbol_list *grammar_end = NULL; + +/* Append SYM to the grammar. */ +static symbol_list * +grammar_symbol_append (symbol *sym, location loc) +{ + symbol_list *p = symbol_list_sym_new (sym, loc); + + if (grammar_end) + grammar_end->next = p; + else + grammar = p; + + grammar_end = p; + + /* A null SYM stands for an end of rule; it is not an actual + part of it. */ + if (sym) + ++nritems; + + return p; +} + +static void +assign_named_ref (symbol_list *p, named_ref *name) +{ + symbol *sym = p->content.sym; + + if (name->id == sym->tag) + { + complain (&name->loc, Wother, + _("duplicated symbol name for %s ignored"), + quote (sym->tag)); + named_ref_free (name); + } + else + p->named_ref = name; +} + + +/* The rule currently being defined, and the previous rule. + CURRENT_RULE points to the first LHS of the current rule, while + PREVIOUS_RULE_END points to the *end* of the previous rule (NULL). */ +static symbol_list *current_rule = NULL; +static symbol_list *previous_rule_end = NULL; + + +/*----------------------------------------------. +| Create a new rule for LHS in to the GRAMMAR. | +`----------------------------------------------*/ + +void +grammar_current_rule_begin (symbol *lhs, location loc, + named_ref *lhs_name) +{ + symbol_list* p; + + /* Start a new rule and record its lhs. */ + ++nrules; + previous_rule_end = grammar_end; + + p = grammar_symbol_append (lhs, loc); + if (lhs_name) + assign_named_ref (p, named_ref_copy (lhs_name)); + + current_rule = grammar_end; + + /* Mark the rule's lhs as a nonterminal if not already so. */ + if (lhs->class == unknown_sym) + { + lhs->class = nterm_sym; + lhs->number = nvars; + ++nvars; + } + else if (lhs->class == token_sym) + complain (&loc, complaint, _("rule given for %s, which is a token"), + lhs->tag); +} + + +/*----------------------------------------------------------------------. +| A symbol should be used if either: | +| 1. It has a destructor. | +| 2. The symbol is a mid-rule symbol (i.e., the generated LHS | +| replacing a mid-rule action) that was assigned to or used, as in | +| "exp: { $$ = 1; } { $$ = $1; }". | +`----------------------------------------------------------------------*/ + +static bool +symbol_should_be_used (symbol_list const *s, bool *midrule_warning) +{ + if (symbol_code_props_get (s->content.sym, destructor)->code) + return true; + if ((s->midrule && s->midrule->action_props.is_value_used) + || (s->midrule_parent_rule + && (symbol_list_n_get (s->midrule_parent_rule, + s->midrule_parent_rhs_index) + ->action_props.is_value_used))) + { + *midrule_warning = true; + return true; + } + return false; +} + +/*----------------------------------------------------------------. +| Check that the rule R is properly defined. For instance, there | +| should be no type clash on the default action. | +`----------------------------------------------------------------*/ + +static void +grammar_rule_check (const symbol_list *r) +{ + /* Type check. + + If there is an action, then there is nothing we can do: the user + is allowed to shoot herself in the foot. + + Don't worry about the default action if $$ is untyped, since $$'s + value can't be used. */ + if (!r->action_props.code && r->content.sym->type_name) + { + symbol *first_rhs = r->next->content.sym; + /* If $$ is being set in default way, report if any type mismatch. */ + if (first_rhs) + { + char const *lhs_type = r->content.sym->type_name; + const char *rhs_type = + first_rhs->type_name ? first_rhs->type_name : ""; + if (!UNIQSTR_EQ (lhs_type, rhs_type)) + complain (&r->location, Wother, + _("type clash on default action: <%s> != <%s>"), + lhs_type, rhs_type); + } + /* Warn if there is no default for $$ but we need one. */ + else + complain (&r->location, Wother, + _("empty rule for typed nonterminal, and no action")); + } + + /* Check that symbol values that should be used are in fact used. */ + { + symbol_list const *l = r; + int n = 0; + for (; l && l->content.sym; l = l->next, ++n) + { + bool midrule_warning = false; + if (!l->action_props.is_value_used + && symbol_should_be_used (l, &midrule_warning) + /* The default action, $$ = $1, 'uses' both. */ + && (r->action_props.code || (n != 0 && n != 1))) + { + warnings warn_flag = midrule_warning ? Wmidrule_values : Wother; + if (n) + complain (&l->location, warn_flag, _("unused value: $%d"), n); + else + complain (&l->location, warn_flag, _("unset value: $$")); + } + } + } + + /* Check that %empty => empty rule. */ + if (r->percent_empty_loc.start.file + && r->next && r->next->content.sym) + complain (&r->percent_empty_loc, complaint, + _("%%empty on non-empty rule")); + + /* Check that empty rule => %empty. */ + if (!(r->next && r->next->content.sym) + && !r->midrule_parent_rule + && !r->percent_empty_loc.start.file) + complain (&r->location, Wempty_rule, _("empty rule without %%empty")); + + /* See comments in grammar_current_rule_prec_set for how POSIX + mandates this complaint. It's only for identifiers, so skip + it for char literals and strings, which are always tokens. */ + if (r->ruleprec + && r->ruleprec->tag[0] != '\'' && r->ruleprec->tag[0] != '"' + && r->ruleprec->status != declared && !r->ruleprec->prec) + complain (&r->location, Wother, + _("token for %%prec is not defined: %s"), r->ruleprec->tag); +} + + +/*-------------------------------------. +| End the currently being grown rule. | +`-------------------------------------*/ + +void +grammar_current_rule_end (location loc) +{ + /* Put an empty link in the list to mark the end of this rule */ + grammar_symbol_append (NULL, grammar_end->location); + current_rule->location = loc; +} + + +/*-------------------------------------------------------------------. +| The previous action turns out the be a mid-rule action. Attach it | +| to the current rule, i.e., create a dummy symbol, attach it this | +| mid-rule action, and append this dummy nonterminal to the current | +| rule. | +`-------------------------------------------------------------------*/ + +void +grammar_midrule_action (void) +{ + /* Since the action was written out with this rule's number, we must + give the new rule this number by inserting the new rule before + it. */ + + /* Make a DUMMY nonterminal, whose location is that of the midrule + action. Create the MIDRULE. */ + location dummy_location = current_rule->action_props.location; + symbol *dummy = dummy_symbol_get (dummy_location); + symbol_list *midrule = symbol_list_sym_new (dummy, dummy_location); + + /* Remember named_ref of previous action. */ + named_ref *action_name = current_rule->action_props.named_ref; + + /* Make a new rule, whose body is empty, before the current one, so + that the action just read can belong to it. */ + ++nrules; + ++nritems; + /* Attach its location and actions to that of the DUMMY. */ + midrule->location = dummy_location; + code_props_rule_action_init (&midrule->action_props, + current_rule->action_props.code, + current_rule->action_props.location, + midrule, 0, + current_rule->action_props.is_predicate); + code_props_none_init (¤t_rule->action_props); + + if (previous_rule_end) + previous_rule_end->next = midrule; + else + grammar = midrule; + + /* End the dummy's rule. */ + midrule->next = symbol_list_sym_new (NULL, dummy_location); + midrule->next->next = current_rule; + + previous_rule_end = midrule->next; + + /* Insert the dummy nonterminal replacing the midrule action into + the current rule. Bind it to its dedicated rule. */ + grammar_current_rule_symbol_append (dummy, dummy_location, + action_name); + grammar_end->midrule = midrule; + midrule->midrule_parent_rule = current_rule; + midrule->midrule_parent_rhs_index = symbol_list_length (current_rule->next); +} + +/* Set the precedence symbol of the current rule to PRECSYM. */ + +void +grammar_current_rule_prec_set (symbol *precsym, location loc) +{ + /* POSIX says that any identifier is a nonterminal if it does not + appear on the LHS of a grammar rule and is not defined by %token + or by one of the directives that assigns precedence to a token. We + ignore this here because the only kind of identifier that POSIX + allows to follow a %prec is a token and because assuming it's a + token now can produce more logical error messages. Nevertheless, + grammar_rule_check does obey what we believe is the real intent of + POSIX here: that an error be reported for any identifier that + appears after %prec but that is not defined separately as a + token. */ + symbol_class_set (precsym, token_sym, loc, false); + if (current_rule->ruleprec) + duplicate_directive ("%prec", + current_rule->ruleprec->location, loc); + else + current_rule->ruleprec = precsym; +} + +/* Set %empty for the current rule. */ + +void +grammar_current_rule_empty_set (location loc) +{ + /* If %empty is used and -Wno-empty-rule is not, then enable + -Wempty-rule. */ + if (warning_is_unset (Wempty_rule)) + warning_argmatch ("empty-rule", 0, 0); + if (current_rule->percent_empty_loc.start.file) + duplicate_directive ("%empty", + current_rule->percent_empty_loc, loc); + else + current_rule->percent_empty_loc = loc; +} + +/* Attach dynamic precedence DPREC to the current rule. */ + +void +grammar_current_rule_dprec_set (int dprec, location loc) +{ + if (! glr_parser) + complain (&loc, Wother, _("%s affects only GLR parsers"), + "%dprec"); + if (dprec <= 0) + complain (&loc, complaint, _("%s must be followed by positive number"), + "%dprec"); + else if (current_rule->dprec != 0) + duplicate_directive ("%dprec", + current_rule->dprec_location, loc); + else + { + current_rule->dprec = dprec; + current_rule->dprec_location = loc; + } +} + +/* Attach a merge function NAME with argument type TYPE to current + rule. */ + +void +grammar_current_rule_merge_set (uniqstr name, location loc) +{ + if (! glr_parser) + complain (&loc, Wother, _("%s affects only GLR parsers"), + "%merge"); + if (current_rule->merger != 0) + duplicate_directive ("%merge", + current_rule->merger_declaration_location, loc); + else + { + current_rule->merger = get_merge_function (name); + current_rule->merger_declaration_location = loc; + } +} + +/* Attach SYM to the current rule. If needed, move the previous + action as a mid-rule action. */ + +void +grammar_current_rule_symbol_append (symbol *sym, location loc, + named_ref *name) +{ + symbol_list *p; + if (current_rule->action_props.code) + grammar_midrule_action (); + p = grammar_symbol_append (sym, loc); + if (name) + assign_named_ref (p, name); + if (sym->status == undeclared || sym->status == used) + sym->status = needed; +} + +/* Attach an ACTION to the current rule. */ + +void +grammar_current_rule_action_append (const char *action, location loc, + named_ref *name, bool is_predicate) +{ + if (current_rule->action_props.code) + grammar_midrule_action (); + /* After all symbol declarations have been parsed, packgram invokes + code_props_translate_code. */ + code_props_rule_action_init (¤t_rule->action_props, action, loc, + current_rule, name, is_predicate); +} + + +/*---------------------------------------------------------------. +| Convert the rules into the representation using RRHS, RLHS and | +| RITEM. | +`---------------------------------------------------------------*/ + +static void +packgram (void) +{ + unsigned int itemno = 0; + rule_number ruleno = 0; + symbol_list *p; + + ritem = xnmalloc (nritems + 1, sizeof *ritem); + + /* This sentinel is used by build_relations in gram.c. */ + *ritem++ = 0; + + rules = xnmalloc (nrules, sizeof *rules); + + for (p = grammar; p; p = p->next) + { + symbol *ruleprec = p->ruleprec; + record_merge_function_type (p->merger, p->content.sym->type_name, + p->merger_declaration_location); + rules[ruleno].user_number = ruleno; + rules[ruleno].number = ruleno; + rules[ruleno].lhs = p->content.sym; + rules[ruleno].rhs = ritem + itemno; + rules[ruleno].prec = NULL; + rules[ruleno].dprec = p->dprec; + rules[ruleno].merger = p->merger; + rules[ruleno].precsym = NULL; + rules[ruleno].location = p->location; + rules[ruleno].useful = true; + rules[ruleno].action = p->action_props.code; + rules[ruleno].action_location = p->action_props.location; + rules[ruleno].is_predicate = p->action_props.is_predicate; + + /* If the midrule's $$ is set or its $n is used, remove the '$' from the + symbol name so that it's a user-defined symbol so that the default + %destructor and %printer apply. */ + if (p->midrule_parent_rule + && (p->action_props.is_value_used + || (symbol_list_n_get (p->midrule_parent_rule, + p->midrule_parent_rhs_index) + ->action_props.is_value_used))) + p->content.sym->tag += 1; + + /* Don't check the generated rule 0. It has no action, so some rhs + symbols may appear unused, but the parsing algorithm ensures that + %destructor's are invoked appropriately. */ + if (p != grammar) + grammar_rule_check (p); + + { + size_t rule_length = 0; + for (p = p->next; p->content.sym; p = p->next) + { + ++rule_length; + + /* Don't allow rule_length == INT_MAX, since that might + cause confusion with strtol if INT_MAX == LONG_MAX. */ + if (rule_length == INT_MAX) + complain (&rules[ruleno].location, fatal, _("rule is too long")); + + /* item_number = symbol_number. + But the former needs to contain more: negative rule numbers. */ + ritem[itemno++] = + symbol_number_as_item_number (p->content.sym->number); + /* A rule gets by default the precedence and associativity + of its last token. */ + if (p->content.sym->class == token_sym && default_prec) + rules[ruleno].prec = p->content.sym; + } + } + + /* If this rule has a %prec, + the specified symbol's precedence replaces the default. */ + if (ruleprec) + { + rules[ruleno].precsym = ruleprec; + rules[ruleno].prec = ruleprec; + } + /* An item ends by the rule number (negated). */ + ritem[itemno++] = rule_number_as_item_number (ruleno); + aver (itemno < ITEM_NUMBER_MAX); + ++ruleno; + aver (ruleno < RULE_NUMBER_MAX); + } + + aver (itemno == nritems); + + if (trace_flag & trace_sets) + ritem_print (stderr); +} + +/*------------------------------------------------------------------. +| Read in the grammar specification and record it in the format | +| described in gram.h. All actions are copied into ACTION_OBSTACK, | +| in each case forming the body of a C function (YYACTION) which | +| contains a switch statement to decide which action to execute. | +`------------------------------------------------------------------*/ + +void +reader (void) +{ + /* Initialize the symbol table. */ + symbols_new (); + + /* Construct the accept symbol. */ + accept = symbol_get ("$accept", empty_location); + accept->class = nterm_sym; + accept->number = nvars++; + + /* Construct the error token */ + errtoken = symbol_get ("error", empty_location); + errtoken->class = token_sym; + errtoken->number = ntokens++; + + /* Construct a token that represents all undefined literal tokens. + It is always token number 2. */ + undeftoken = symbol_get ("$undefined", empty_location); + undeftoken->class = token_sym; + undeftoken->number = ntokens++; + + gram_in = xfopen (grammar_file, "r"); + + gram__flex_debug = trace_flag & trace_scan; + gram_debug = trace_flag & trace_parse; + gram_scanner_initialize (); + gram_parse (); + prepare_percent_define_front_end_variables (); + + if (complaint_status < status_complaint) + check_and_convert_grammar (); + + xfclose (gram_in); +} + +static void +prepare_percent_define_front_end_variables (void) +{ + /* Set %define front-end variable defaults. */ + muscle_percent_define_default ("lr.keep-unreachable-state", "false"); + { + char *lr_type; + /* IELR would be a better default, but LALR is historically the + default. */ + muscle_percent_define_default ("lr.type", "lalr"); + lr_type = muscle_percent_define_get ("lr.type"); + if (STRNEQ (lr_type, "canonical-lr")) + muscle_percent_define_default ("lr.default-reduction", "most"); + else + muscle_percent_define_default ("lr.default-reduction", "accepting"); + free (lr_type); + } + + /* Check %define front-end variables. */ + { + static char const * const values[] = { + "lr.type", "lalr", "ielr", "canonical-lr", NULL, + "lr.default-reduction", "most", "consistent", "accepting", NULL, + NULL + }; + muscle_percent_define_check_values (values); + } +} + + +/*-------------------------------------------------------------. +| Check the grammar that has just been read, and convert it to | +| internal form. | +`-------------------------------------------------------------*/ + +static void +check_and_convert_grammar (void) +{ + /* Grammar has been read. Do some checking. */ + if (nrules == 0) + complain (NULL, fatal, _("no rules in the input grammar")); + + /* If the user did not define her ENDTOKEN, do it now. */ + if (!endtoken) + { + endtoken = symbol_get ("$end", empty_location); + endtoken->class = token_sym; + endtoken->number = 0; + /* Value specified by POSIX. */ + endtoken->user_token_number = 0; + } + + /* Report any undefined symbols and consider them nonterminals. */ + symbols_check_defined (); + + /* Find the start symbol if no %start. */ + if (!start_flag) + { + symbol_list *node; + for (node = grammar; + node != NULL && symbol_is_dummy (node->content.sym); + node = node->next) + { + for (node = node->next; + node != NULL && node->content.sym != NULL; + node = node->next) + ; + } + aver (node != NULL); + grammar_start_symbol_set (node->content.sym, + node->content.sym->location); + } + + /* Insert the initial rule, whose line is that of the first rule + (not that of the start symbol): + + $accept: %start $end. */ + { + symbol_list *p = symbol_list_sym_new (accept, empty_location); + p->location = grammar->location; + p->next = symbol_list_sym_new (startsymbol, empty_location); + p->next->next = symbol_list_sym_new (endtoken, empty_location); + p->next->next->next = symbol_list_sym_new (NULL, empty_location); + p->next->next->next->next = grammar; + nrules += 1; + nritems += 3; + grammar = p; + } + + aver (nsyms <= SYMBOL_NUMBER_MAXIMUM); + aver (nsyms == ntokens + nvars); + + /* Assign the symbols their symbol numbers. Write #defines for the + token symbols into FDEFINES if requested. */ + symbols_pack (); + + /* Scan rule actions after invoking symbol_check_alias_consistency (in + symbols_pack above) so that token types are set correctly before the rule + action type checking. + + Before invoking grammar_rule_check (in packgram below) on any rule, make + sure all actions have already been scanned in order to set 'used' flags. + Otherwise, checking that a midrule's $$ should be set will not always work + properly because the check must forward-reference the midrule's parent + rule. For the same reason, all the 'used' flags must be set before + checking whether to remove '$' from any midrule symbol name (also in + packgram). */ + { + symbol_list *sym; + for (sym = grammar; sym; sym = sym->next) + code_props_translate_code (&sym->action_props); + } + + /* Convert the grammar into the format described in gram.h. */ + packgram (); + + /* The grammar as a symbol_list is no longer needed. */ + symbol_list_free (grammar); +} diff --git a/contrib/tools/bison/src/reader.h b/contrib/tools/bison/src/reader.h new file mode 100644 index 0000000000..ba6ffe6edc --- /dev/null +++ b/contrib/tools/bison/src/reader.h @@ -0,0 +1,73 @@ +/* Input parser for Bison + + Copyright (C) 2000-2003, 2005-2007, 2009-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef READER_H_ +# define READER_H_ + +# include "location.h" +# include "symlist.h" +# include "named-ref.h" + +# include "parse-gram.h" + +typedef struct merger_list +{ + struct merger_list* next; + uniqstr name; + uniqstr type; + location type_declaration_location; +} merger_list; + +/* From the parser. */ +extern int gram_debug; +int gram_parse (void); +char const *token_name (int type); + + +/* From reader.c. */ +void grammar_start_symbol_set (symbol *sym, location loc); +void grammar_current_rule_begin (symbol *lhs, location loc, + named_ref *lhs_named_ref); +void grammar_current_rule_end (location loc); +void grammar_midrule_action (void); +/* Apply %empty to the current rule. */ +void grammar_current_rule_empty_set (location loc); +void grammar_current_rule_prec_set (symbol *precsym, location loc); +void grammar_current_rule_dprec_set (int dprec, location loc); +void grammar_current_rule_merge_set (uniqstr name, location loc); +void grammar_current_rule_symbol_append (symbol *sym, location loc, + named_ref *nref); +void grammar_current_rule_action_append (const char *action, location loc, + named_ref *nref, bool); +void reader (void); +void free_merger_functions (void); + +extern merger_list *merge_functions; + +/* Was %union seen? */ +extern bool union_seen; + +/* Was a tag seen? */ +extern bool tag_seen; + +/* Should rules have a default precedence? */ +extern bool default_prec; + +#endif /* !READER_H_ */ diff --git a/contrib/tools/bison/src/reduce.c b/contrib/tools/bison/src/reduce.c new file mode 100644 index 0000000000..eea11b1e20 --- /dev/null +++ b/contrib/tools/bison/src/reduce.c @@ -0,0 +1,466 @@ +/* Grammar reduction for Bison. + + Copyright (C) 1988-1989, 2000-2003, 2005-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + + +/* Reduce the grammar: Find and eliminate unreachable terminals, + nonterminals, and productions. David S. Bakin. */ + +/* Don't eliminate unreachable terminals: They may be used by the + user's parser. */ + +#include <config.h> +#include "system.h" + +#include <bitset.h> + +#include "complain.h" +#include "files.h" +#include "getargs.h" +#include "gram.h" +#include "print-xml.h" +#include "reader.h" +#include "reduce.h" +#include "symtab.h" + +/* Set of all nonterminals which are not useless. */ +static bitset N; + +/* Set of all rules which have no useless nonterminals in their RHS. */ +static bitset P; + +/* Set of all accessible symbols. */ +static bitset V; + +/* Set of symbols used to define rule precedence (so they are + 'useless', but no warning should be issued). */ +static bitset V1; + +static rule_number nuseful_productions; +rule_number nuseless_productions; +static int nuseful_nonterminals; +symbol_number nuseless_nonterminals; + +/*-------------------------------------------------------------------. +| Another way to do this would be with a set for each production and | +| then do subset tests against N0, but even for the C grammar the | +| whole reducing process takes only 2 seconds on my 8Mhz AT. | +`-------------------------------------------------------------------*/ + +static bool +useful_production (rule_number r, bitset N0) +{ + item_number *rhsp; + + /* A production is useful if all of the nonterminals in its appear + in the set of useful nonterminals. */ + + for (rhsp = rules[r].rhs; *rhsp >= 0; ++rhsp) + if (ISVAR (*rhsp) && !bitset_test (N0, *rhsp - ntokens)) + return false; + return true; +} + + +/*---------------------------------------------------------. +| Remember that rules are 1-origin, symbols are 0-origin. | +`---------------------------------------------------------*/ + +static void +useless_nonterminals (void) +{ + bitset Np, Ns; + rule_number r; + + /* N is set as built. Np is set being built this iteration. P is + set of all productions which have a RHS all in N. */ + + Np = bitset_create (nvars, BITSET_FIXED); + + + /* The set being computed is a set of nonterminals which can derive + the empty string or strings consisting of all terminals. At each + iteration a nonterminal is added to the set if there is a + production with that nonterminal as its LHS for which all the + nonterminals in its RHS are already in the set. Iterate until + the set being computed remains unchanged. Any nonterminals not + in the set at that point are useless in that they will never be + used in deriving a sentence of the language. + + This iteration doesn't use any special traversal over the + productions. A set is kept of all productions for which all the + nonterminals in the RHS are in useful. Only productions not in + this set are scanned on each iteration. At the end, this set is + saved to be used when finding useful productions: only + productions in this set will appear in the final grammar. */ + + while (1) + { + bitset_copy (Np, N); + for (r = 0; r < nrules; r++) + if (!bitset_test (P, r) + && useful_production (r, N)) + { + bitset_set (Np, rules[r].lhs->number - ntokens); + bitset_set (P, r); + } + if (bitset_equal_p (N, Np)) + break; + Ns = Np; + Np = N; + N = Ns; + } + bitset_free (N); + N = Np; +} + + +static void +inaccessable_symbols (void) +{ + bitset Vp, Vs, Pp; + + /* Find out which productions are reachable and which symbols are + used. Starting with an empty set of productions and a set of + symbols which only has the start symbol in it, iterate over all + productions until the set of productions remains unchanged for an + iteration. For each production which has a LHS in the set of + reachable symbols, add the production to the set of reachable + productions, and add all of the nonterminals in the RHS of the + production to the set of reachable symbols. + + Consider only the (partially) reduced grammar which has only + nonterminals in N and productions in P. + + The result is the set P of productions in the reduced grammar, + and the set V of symbols in the reduced grammar. + + Although this algorithm also computes the set of terminals which + are reachable, no terminal will be deleted from the grammar. Some + terminals might not be in the grammar but might be generated by + semantic routines, and so the user might want them available with + specified numbers. (Is this true?) However, the nonreachable + terminals are printed (if running in verbose mode) so that the + user can know. */ + + Vp = bitset_create (nsyms, BITSET_FIXED); + Pp = bitset_create (nrules, BITSET_FIXED); + + /* If the start symbol isn't useful, then nothing will be useful. */ + if (bitset_test (N, accept->number - ntokens)) + { + bitset_set (V, accept->number); + + while (1) + { + rule_number r; + bitset_copy (Vp, V); + for (r = 0; r < nrules; r++) + { + if (!bitset_test (Pp, r) + && bitset_test (P, r) + && bitset_test (V, rules[r].lhs->number)) + { + item_number *rhsp; + for (rhsp = rules[r].rhs; *rhsp >= 0; rhsp++) + if (ISTOKEN (*rhsp) || bitset_test (N, *rhsp - ntokens)) + bitset_set (Vp, *rhsp); + bitset_set (Pp, r); + } + } + if (bitset_equal_p (V, Vp)) + break; + Vs = Vp; + Vp = V; + V = Vs; + } + } + + bitset_free (V); + V = Vp; + + /* Tokens 0, 1, and 2 are internal to Bison. Consider them useful. */ + bitset_set (V, endtoken->number); /* end-of-input token */ + bitset_set (V, errtoken->number); /* error token */ + bitset_set (V, undeftoken->number); /* some undefined token */ + + bitset_free (P); + P = Pp; + + nuseful_productions = bitset_count (P); + nuseless_productions = nrules - nuseful_productions; + + nuseful_nonterminals = 0; + { + symbol_number i; + for (i = ntokens; i < nsyms; i++) + if (bitset_test (V, i)) + nuseful_nonterminals++; + } + nuseless_nonterminals = nvars - nuseful_nonterminals; + + /* A token that was used in %prec should not be warned about. */ + { + rule_number r; + for (r = 0; r < nrules; ++r) + if (rules[r].precsym != 0) + bitset_set (V1, rules[r].precsym->number); + } +} + + +/*-------------------------------------------------------------------. +| Put the useless productions at the end of RULES, and adjust NRULES | +| accordingly. | +`-------------------------------------------------------------------*/ + +static void +reduce_grammar_tables (void) +{ + /* Report and flag useless productions. */ + { + rule_number r; + for (r = 0; r < nrules; r++) + rules[r].useful = bitset_test (P, r); + grammar_rules_useless_report (_("rule useless in grammar")); + } + + /* Map the nonterminals to their new index: useful first, useless + afterwards. Kept for later report. */ + { + int useful = 0; + int useless = nrules - nuseless_productions; + rule *rules_sorted = xnmalloc (nrules, sizeof *rules_sorted); + rule_number r; + for (r = 0; r < nrules; ++r) + rules_sorted[rules[r].useful ? useful++ : useless++] = rules[r]; + free (rules); + rules = rules_sorted; + + /* Renumber the rules markers in RITEMS. */ + for (r = 0; r < nrules; ++r) + { + item_number *rhsp = rules[r].rhs; + for (/* Nothing. */; *rhsp >= 0; ++rhsp) + /* Nothing. */; + *rhsp = rule_number_as_item_number (r); + rules[r].number = r; + } + nrules -= nuseless_productions; + } + + /* Adjust NRITEMS. */ + { + rule_number r; + int length; + for (r = nrules; r < nrules + nuseless_productions; ++r) + { + length = rule_rhs_length (&rules[r]); + nritems -= length + 1; + } + } +} + + +/*------------------------------. +| Remove useless nonterminals. | +`------------------------------*/ + +static void +nonterminals_reduce (void) +{ + /* Map the nonterminals to their new index: useful first, useless + afterwards. Kept for later report. */ + + symbol_number *nontermmap = xnmalloc (nvars, sizeof *nontermmap); + symbol_number n = ntokens; + symbol_number i; + for (i = ntokens; i < nsyms; i++) + if (bitset_test (V, i)) + nontermmap[i - ntokens] = n++; + for (i = ntokens; i < nsyms; i++) + if (!bitset_test (V, i)) + { + nontermmap[i - ntokens] = n++; + if (symbols[i]->status != used) + complain (&symbols[i]->location, Wother, + _("nonterminal useless in grammar: %s"), + symbols[i]->tag); + } + + + /* Shuffle elements of tables indexed by symbol number. */ + { + symbol **symbols_sorted = xnmalloc (nvars, sizeof *symbols_sorted); + + for (i = ntokens; i < nsyms; i++) + symbols[i]->number = nontermmap[i - ntokens]; + for (i = ntokens; i < nsyms; i++) + symbols_sorted[nontermmap[i - ntokens] - ntokens] = symbols[i]; + for (i = ntokens; i < nsyms; i++) + symbols[i] = symbols_sorted[i - ntokens]; + free (symbols_sorted); + } + + { + rule_number r; + for (r = 0; r < nrules; ++r) + { + item_number *rhsp; + for (rhsp = rules[r].rhs; *rhsp >= 0; ++rhsp) + if (ISVAR (*rhsp)) + *rhsp = symbol_number_as_item_number (nontermmap[*rhsp + - ntokens]); + } + accept->number = nontermmap[accept->number - ntokens]; + } + + nsyms -= nuseless_nonterminals; + nvars -= nuseless_nonterminals; + + free (nontermmap); +} + + +/*------------------------------------------------------------------. +| Output the detailed results of the reductions. For FILE.output. | +`------------------------------------------------------------------*/ + +void +reduce_output (FILE *out) +{ + if (nuseless_nonterminals > 0) + { + int i; + fprintf (out, "%s\n\n", _("Nonterminals useless in grammar")); + for (i = 0; i < nuseless_nonterminals; ++i) + fprintf (out, " %s\n", symbols[nsyms + i]->tag); + fputs ("\n\n", out); + } + + { + bool b = false; + int i; + for (i = 0; i < ntokens; i++) + if (reduce_token_unused_in_grammar (i)) + { + if (!b) + fprintf (out, "%s\n\n", _("Terminals unused in grammar")); + b = true; + fprintf (out, " %s\n", symbols[i]->tag); + } + if (b) + fputs ("\n\n", out); + } + + if (nuseless_productions > 0) + grammar_rules_partial_print (out, _("Rules useless in grammar"), + rule_useless_in_grammar_p); +} + + +/*-------------------------------. +| Report the results to STDERR. | +`-------------------------------*/ + +static void +reduce_print (void) +{ + if (nuseless_nonterminals > 0) + complain (NULL, Wother, ngettext ("%d nonterminal useless in grammar", + "%d nonterminals useless in grammar", + nuseless_nonterminals), + nuseless_nonterminals); + if (nuseless_productions > 0) + complain (NULL, Wother, ngettext ("%d rule useless in grammar", + "%d rules useless in grammar", + nuseless_productions), + nuseless_productions); +} + +void +reduce_grammar (void) +{ + bool reduced; + + /* Allocate the global sets used to compute the reduced grammar */ + + N = bitset_create (nvars, BITSET_FIXED); + P = bitset_create (nrules, BITSET_FIXED); + V = bitset_create (nsyms, BITSET_FIXED); + V1 = bitset_create (nsyms, BITSET_FIXED); + + useless_nonterminals (); + inaccessable_symbols (); + + reduced = (nuseless_nonterminals + nuseless_productions > 0); + if (!reduced) + return; + + reduce_print (); + + if (!bitset_test (N, accept->number - ntokens)) + complain (&startsymbol_location, fatal, + _("start symbol %s does not derive any sentence"), + startsymbol->tag); + + /* First reduce the nonterminals, as they renumber themselves in the + whole grammar. If you change the order, nonterms would be + renumbered only in the reduced grammar. */ + if (nuseless_nonterminals > 0) + nonterminals_reduce (); + if (nuseless_productions > 0) + reduce_grammar_tables (); + + if (trace_flag & trace_grammar) + { + grammar_dump (stderr, "Reduced Grammar"); + + fprintf (stderr, "reduced %s defines %d terminals, %d nonterminals" + ", and %d productions.\n", + grammar_file, ntokens, nvars, nrules); + } +} + +bool +reduce_token_unused_in_grammar (symbol_number i) +{ + aver (i < ntokens); + return !bitset_test (V, i) && !bitset_test (V1, i); +} + +bool +reduce_nonterminal_useless_in_grammar (symbol_number i) +{ + aver (ntokens <= i && i < nsyms + nuseless_nonterminals); + return nsyms <= i; +} + +/*-----------------------------------------------------------. +| Free the global sets used to compute the reduced grammar. | +`-----------------------------------------------------------*/ + +void +reduce_free (void) +{ + bitset_free (N); + bitset_free (V); + bitset_free (V1); + bitset_free (P); +} diff --git a/contrib/tools/bison/src/reduce.h b/contrib/tools/bison/src/reduce.h new file mode 100644 index 0000000000..bc12ed0e50 --- /dev/null +++ b/contrib/tools/bison/src/reduce.h @@ -0,0 +1,32 @@ +/* Grammar reduction for Bison. + + Copyright (C) 2000-2002, 2007, 2009-2013 Free Software Foundation, + Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef REDUCE_H_ +# define REDUCE_H_ + +void reduce_grammar (void); +void reduce_output (FILE *out); +bool reduce_token_unused_in_grammar (symbol_number i); +bool reduce_nonterminal_useless_in_grammar (symbol_number i); +void reduce_free (void); + +extern symbol_number nuseless_nonterminals; +extern rule_number nuseless_productions; +#endif /* !REDUCE_H_ */ diff --git a/contrib/tools/bison/src/relation.c b/contrib/tools/bison/src/relation.c new file mode 100644 index 0000000000..5746eca704 --- /dev/null +++ b/contrib/tools/bison/src/relation.c @@ -0,0 +1,183 @@ +/* Binary relations. + + Copyright (C) 2002, 2004-2005, 2009-2013 Free Software Foundation, + Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include <bitsetv.h> + +#include "getargs.h" +#include "relation.h" + +void +relation_print (relation r, relation_node size, FILE *out) +{ + relation_node i; + relation_node j; + + for (i = 0; i < size; ++i) + { + fprintf (out, "%3lu: ", (unsigned long int) i); + if (r[i]) + for (j = 0; r[i][j] != END_NODE; ++j) + fprintf (out, "%3lu ", (unsigned long int) r[i][j]); + fputc ('\n', out); + } + fputc ('\n', out); +} + + +/*---------------------------------------------------------------. +| digraph & traverse. | +| | +| The following variables are used as common storage between the | +| two. | +`---------------------------------------------------------------*/ + +static relation R; +static relation_nodes INDEX; +static relation_nodes VERTICES; +static relation_node top; +static relation_node infinity; +static bitsetv F; + +static void +traverse (relation_node i) +{ + relation_node j; + relation_node height; + + VERTICES[++top] = i; + INDEX[i] = height = top; + + if (R[i]) + for (j = 0; R[i][j] != END_NODE; ++j) + { + if (INDEX[R[i][j]] == 0) + traverse (R[i][j]); + + if (INDEX[i] > INDEX[R[i][j]]) + INDEX[i] = INDEX[R[i][j]]; + + bitset_or (F[i], F[i], F[R[i][j]]); + } + + if (INDEX[i] == height) + for (;;) + { + j = VERTICES[top--]; + INDEX[j] = infinity; + + if (i == j) + break; + + bitset_copy (F[j], F[i]); + } +} + + +void +relation_digraph (relation r, relation_node size, bitsetv *function) +{ + relation_node i; + + infinity = size + 2; + INDEX = xcalloc (size + 1, sizeof *INDEX); + VERTICES = xnmalloc (size + 1, sizeof *VERTICES); + top = 0; + + R = r; + F = *function; + + for (i = 0; i < size; i++) + if (INDEX[i] == 0 && R[i]) + traverse (i); + + free (INDEX); + free (VERTICES); + + *function = F; +} + + +/*-------------------------------------------. +| Destructively transpose R_ARG, of size N. | +`-------------------------------------------*/ + +void +relation_transpose (relation *R_arg, relation_node n) +{ + relation r = *R_arg; + /* The result. */ + relation new_R = xnmalloc (n, sizeof *new_R); + /* END_R[I] -- next entry of NEW_R[I]. */ + relation end_R = xnmalloc (n, sizeof *end_R); + /* NEDGES[I] -- total size of NEW_R[I]. */ + size_t *nedges = xcalloc (n, sizeof *nedges); + relation_node i; + relation_node j; + + if (trace_flag & trace_sets) + { + fputs ("relation_transpose: input\n", stderr); + relation_print (r, n, stderr); + } + + /* Count. */ + for (i = 0; i < n; i++) + if (r[i]) + for (j = 0; r[i][j] != END_NODE; ++j) + ++nedges[r[i][j]]; + + /* Allocate. */ + for (i = 0; i < n; i++) + { + relation_node *sp = NULL; + if (nedges[i] > 0) + { + sp = xnmalloc (nedges[i] + 1, sizeof *sp); + sp[nedges[i]] = END_NODE; + } + new_R[i] = sp; + end_R[i] = sp; + } + + /* Store. */ + for (i = 0; i < n; i++) + if (r[i]) + for (j = 0; r[i][j] != END_NODE; ++j) + *end_R[r[i][j]]++ = i; + + free (nedges); + free (end_R); + + /* Free the input: it is replaced with the result. */ + for (i = 0; i < n; i++) + free (r[i]); + free (r); + + if (trace_flag & trace_sets) + { + fputs ("relation_transpose: output\n", stderr); + relation_print (new_R, n, stderr); + } + + *R_arg = new_R; +} diff --git a/contrib/tools/bison/src/relation.h b/contrib/tools/bison/src/relation.h new file mode 100644 index 0000000000..b44e1a7f98 --- /dev/null +++ b/contrib/tools/bison/src/relation.h @@ -0,0 +1,49 @@ +/* Binary relations. + + Copyright (C) 2002, 2004, 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + + +#ifndef RELATION_H_ +# define RELATION_H_ + +/* Performing operations on graphs coded as list of adjacency. + + If GRAPH is a relation, then GRAPH[Node] is a list of adjacent + nodes, ended with END_NODE. */ + +# define END_NODE ((relation_node) -1) + +typedef size_t relation_node; +typedef relation_node *relation_nodes; +typedef relation_nodes *relation; + + +/* Report a relation R that has SIZE vertices. */ +void relation_print (relation r, relation_node size, FILE *out); + +/* Compute the transitive closure of the FUNCTION on the relation R + with SIZE vertices. + + If R (NODE-1, NODE-2) then on exit FUNCTION[NODE - 1] was extended + (unioned) with FUNCTION[NODE - 2]. */ +void relation_digraph (relation r, relation_node size, bitsetv *function); + +/* Destructively transpose *R_ARG, of size N. */ +void relation_transpose (relation *R_arg, relation_node n); + +#endif /* ! RELATION_H_ */ diff --git a/contrib/tools/bison/src/scan-code-c.c b/contrib/tools/bison/src/scan-code-c.c new file mode 100644 index 0000000000..7d37b766b5 --- /dev/null +++ b/contrib/tools/bison/src/scan-code-c.c @@ -0,0 +1,3 @@ +#include <config.h> +#include "system.h" +#include "src/scan-code.c" diff --git a/contrib/tools/bison/src/scan-code.c b/contrib/tools/bison/src/scan-code.c new file mode 100644 index 0000000000..971f30241f --- /dev/null +++ b/contrib/tools/bison/src/scan-code.c @@ -0,0 +1,2990 @@ +#line 2 "src/scan-code.c" + +#line 4 "src/scan-code.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +/* %not-for-header */ + +/* %if-c-only */ +/* %if-not-reentrant */ +#define yy_create_buffer code__create_buffer +#define yy_delete_buffer code__delete_buffer +#define yy_flex_debug code__flex_debug +#define yy_init_buffer code__init_buffer +#define yy_flush_buffer code__flush_buffer +#define yy_load_buffer_state code__load_buffer_state +#define yy_switch_to_buffer code__switch_to_buffer +#define yyin code_in +#define yyleng code_leng +#define yylex code_lex +#define yylineno code_lineno +#define yyout code_out +#define yyrestart code_restart +#define yytext code_text +#define yywrap code_wrap +#define yyalloc code_alloc +#define yyrealloc code_realloc +#define yyfree code_free + +/* %endif */ +/* %endif */ +/* %ok-for-header */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 37 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* %if-c++-only */ +/* %endif */ + +/* %if-c-only */ + +/* %endif */ + +/* %if-c-only */ + +/* %endif */ + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +/* %if-c-only */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +/* %endif */ + +/* %if-tables-serialization */ +/* %endif */ +/* end standard C headers. */ + +/* %if-c-or-c++ */ +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* %endif */ + +/* %if-c++-only */ +/* %endif */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* %not-for-header */ + +/* Returned upon end-of-file. */ +#define YY_NULL 0 +/* %ok-for-header */ + +/* %not-for-header */ + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) +/* %ok-for-header */ + +/* %if-reentrant */ +/* %endif */ + +/* %if-not-reentrant */ + +/* %endif */ + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE code_restart(code_in ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +/* %if-not-reentrant */ +extern yy_size_t code_leng; +/* %endif */ + +/* %if-c-only */ +/* %if-not-reentrant */ +extern FILE *code_in, *code_out; +/* %endif */ +/* %endif */ + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up code_text. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up code_text again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { +/* %if-c-only */ + FILE *yy_input_file; +/* %endif */ + +/* %if-c++-only */ +/* %endif */ + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + yy_size_t yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via code_restart()), so that the user can continue scanning by + * just pointing code_in at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* %if-c-only Standard (non-C++) definition */ +/* %not-for-header */ + +/* %if-not-reentrant */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ +/* %endif */ +/* %ok-for-header */ + +/* %endif */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* %if-c-only Standard (non-C++) definition */ + +/* %if-not-reentrant */ +/* %not-for-header */ + +/* yy_hold_char holds the character lost when code_text is formed. */ +static char yy_hold_char; +static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ +yy_size_t code_leng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow code_wrap()'s to do buffer switches + * instead of setting up a fresh code_in. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; +/* %ok-for-header */ + +/* %endif */ + +void code_restart (FILE *input_file ); +void code__switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE code__create_buffer (FILE *file,int size ); +void code__delete_buffer (YY_BUFFER_STATE b ); +void code__flush_buffer (YY_BUFFER_STATE b ); +void code_push_buffer_state (YY_BUFFER_STATE new_buffer ); +void code_pop_buffer_state (void ); + +static void code_ensure_buffer_stack (void ); +static void code__load_buffer_state (void ); +static void code__init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER code__flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE code__scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE code__scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE code__scan_bytes (yyconst char *bytes,yy_size_t len ); + +/* %endif */ + +void *code_alloc (yy_size_t ); +void *code_realloc (void *,yy_size_t ); +void code_free (void * ); + +#define yy_new_buffer code__create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + code_ensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + code__create_buffer(code_in,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + code_ensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + code__create_buffer(code_in,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* %% [1.0] code_text/code_in/code_out/yy_state_type/code_lineno etc. def's & init go here */ +/* Begin user sect3 */ + +#define code_wrap() 1 +#define YY_SKIP_YYWRAP + +#define FLEX_DEBUG + +typedef unsigned char YY_CHAR; + +FILE *code_in = (FILE *) 0, *code_out = (FILE *) 0; + +typedef int yy_state_type; + +extern int code_lineno; + +int code_lineno = 1; + +extern char *code_text; +#define yytext_ptr code_text + +/* %if-c-only Standard (non-C++) definition */ + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* %endif */ + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up code_text. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ +/* %% [2.0] code to fiddle code_text and code_leng for yymore() goes here \ */\ + code_leng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ +/* %% [3.0] code to copy yytext_ptr to code_text[] goes here, if %array \ */\ + (yy_c_buf_p) = yy_cp; + +/* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */ +#define YY_NUM_RULES 18 +#define YY_END_OF_BUFFER 19 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[91] = + { 0, + 0, 0, 0, 0, 3, 3, 4, 4, 4, 4, + 0, 0, 0, 0, 19, 17, 16, 17, 2, 17, + 6, 17, 5, 8, 11, 7, 17, 11, 11, 11, + 1, 0, 0, 3, 4, 4, 4, 4, 12, 0, + 12, 12, 0, 0, 9, 10, 0, 13, 0, 13, + 13, 0, 14, 0, 15, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 0, 0, 0, 0, 13, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, + 12, 12, 0, 14, 12, 12, 0, 0, 0, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 4, 1, 5, 1, 1, 6, 1, + 1, 7, 1, 1, 8, 9, 10, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 1, 1, 12, + 1, 13, 1, 14, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 15, 16, 17, 1, 9, 1, 9, 9, 9, 9, + + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[19] = + { 0, + 1, 1, 2, 1, 1, 1, 1, 3, 3, 1, + 3, 1, 2, 1, 1, 1, 1, 2 + } ; + +static yyconst flex_int16_t yy_base[97] = + { 0, + 0, 13, 121, 120, 0, 3, 4, 5, 6, 7, + 27, 0, 20, 21, 125, 178, 178, 26, 178, 8, + 178, 41, 178, 178, 53, 178, 62, 74, 33, 119, + 178, 37, 44, 105, 178, 46, 101, 48, 178, 99, + 0, 96, 98, 91, 178, 178, 50, 178, 87, 0, + 86, 87, 178, 76, 178, 52, 50, 68, 71, 73, + 78, 74, 0, 16, 78, 84, 85, 0, 0, 94, + 86, 96, 55, 107, 0, 0, 58, 118, 100, 124, + 130, 136, 142, 106, 46, 0, 148, 43, 0, 178, + 165, 168, 4, 171, 1, 174 + + } ; + +static yyconst flex_int16_t yy_def[97] = + { 0, + 91, 91, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 11, 11, 11, 90, 90, 90, 90, 90, 90, + 90, 92, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 93, 90, 94, 90, 90, 90, 90, 90, 90, 95, + 90, 90, 90, 96, 90, 90, 90, 90, 90, 90, + 90, 92, 93, 94, 94, 90, 90, 27, 95, 90, + 96, 96, 25, 94, 66, 70, 90, 96, 94, 94, + 94, 94, 94, 96, 81, 81, 81, 87, 87, 0, + 90, 90, 90, 90, 90, 90 + + } ; + +static yyconst flex_int16_t yy_nxt[197] = + { 0, + 90, 90, 19, 69, 17, 19, 63, 21, 21, 33, + 34, 23, 23, 17, 17, 20, 17, 17, 20, 22, + 22, 22, 22, 65, 29, 29, 17, 17, 73, 17, + 24, 25, 26, 30, 30, 31, 27, 53, 56, 57, + 28, 32, 36, 37, 54, 33, 34, 59, 37, 61, + 62, 67, 68, 56, 57, 74, 38, 39, 74, 31, + 40, 41, 53, 42, 43, 32, 90, 44, 45, 33, + 34, 46, 59, 37, 59, 37, 90, 47, 48, 61, + 62, 49, 50, 72, 51, 65, 67, 68, 52, 38, + 74, 75, 75, 72, 75, 70, 51, 51, 77, 66, + + 39, 76, 76, 72, 76, 65, 42, 65, 78, 42, + 48, 79, 73, 72, 80, 81, 60, 82, 77, 73, + 58, 83, 84, 55, 90, 72, 18, 18, 90, 90, + 77, 65, 90, 90, 82, 90, 74, 85, 86, 90, + 86, 90, 73, 65, 90, 90, 82, 90, 73, 65, + 87, 90, 90, 90, 73, 88, 89, 90, 89, 90, + 90, 90, 90, 90, 79, 16, 16, 16, 35, 35, + 35, 64, 90, 64, 71, 90, 71, 15, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90 + + } ; + +static yyconst flex_int16_t yy_chk[197] = + { 0, + 0, 0, 5, 95, 1, 6, 93, 7, 8, 20, + 20, 9, 10, 1, 1, 5, 1, 2, 6, 7, + 8, 9, 10, 64, 13, 14, 2, 2, 64, 2, + 11, 11, 11, 13, 14, 18, 11, 29, 32, 32, + 11, 18, 22, 22, 29, 33, 33, 36, 36, 38, + 38, 47, 47, 56, 56, 88, 22, 25, 85, 57, + 25, 25, 77, 25, 25, 57, 73, 25, 27, 58, + 58, 27, 59, 59, 60, 60, 62, 27, 28, 61, + 61, 28, 28, 54, 28, 65, 67, 67, 28, 62, + 65, 66, 66, 71, 66, 52, 51, 49, 71, 44, + + 66, 70, 70, 72, 70, 43, 42, 79, 72, 40, + 70, 74, 79, 84, 74, 74, 37, 74, 84, 74, + 34, 74, 78, 30, 15, 78, 4, 3, 0, 0, + 78, 80, 0, 0, 80, 0, 80, 81, 81, 0, + 81, 0, 81, 82, 0, 0, 82, 0, 82, 83, + 83, 0, 0, 0, 83, 87, 87, 0, 87, 0, + 0, 0, 0, 0, 87, 91, 91, 91, 92, 92, + 92, 94, 0, 94, 96, 0, 96, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90 + + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int code__flex_debug; +int code__flex_debug = 1; + +static yyconst flex_int16_t yy_rule_linenum[18] = + { 0, + 114, 124, 125, 135, 140, 145, 151, 152, 153, 154, + 156, 164, 170, 180, 188, 198, 201 + } ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *code_text; +#line 1 "../../src/scan-code.l" +/* Bison Action Scanner -*- C -*- + + Copyright (C) 2006-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#define YY_NO_INPUT 1 +#line 24 "../../src/scan-code.l" +/* Work around a bug in flex 2.5.31. See Debian bug 333231 + <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>. */ +#undef code_wrap +#define code_wrap() 1 + +#define FLEX_PREFIX(Id) code_ ## Id +#include <src/flex-scanner.h> + +#include <src/complain.h> +#include <src/reader.h> +#include <src/getargs.h> +#include <src/muscle-tab.h> +#include <src/scan-code.h> +#include <src/symlist.h> + +#include <c-ctype.h> +#include <get-errno.h> +#include <quote.h> + +/* The current calling start condition: SC_RULE_ACTION or + SC_SYMBOL_ACTION. */ +# define YY_DECL static char *code_lex (code_props *self, int sc_context) +YY_DECL; + +#define YY_USER_ACTION location_compute (loc, &loc->end, code_text, code_leng); + +static char *fetch_type_name (char *cp, char const **type_name, + location dollar_loc); + +static void handle_action_dollar (symbol_list *rule, char *cp, + location dollar_loc); +static void handle_action_at (symbol_list *rule, char *cp, location at_loc); + +/* A string to be pushed to obstack after dollar/at has been handled. */ +static char *ref_tail_fields; + +static location the_location; +static location *loc = &the_location; + +/* A string representing the most recent translation. */ +static char *last_string; + +/* True if an untyped $$ or $n was seen. */ +static bool untyped_var_seen; + +/* C and C++ comments in code. */ + +/* Strings and characters in code. */ + +/* Whether in a rule or symbol action. Specifies the translation +of $ and @. */ + +/* POSIX says that a tag must be both an id and a C union member, but + historically almost any character is allowed in a tag. We disallow + NUL and newline, as this simplifies our implementation. We allow + "->" as a means to dereference a pointer. */ +/* Zero or more instances of backslash-newline. Following GCC, allow + white space between the backslash and the newline. */ +/* C style identifier. Must start with letter. Will be used for + named symbol references. Shall be kept synchronized with + scan-gram.l "letter" and "id". */ +#line 713 "src/scan-code.c" + +#define INITIAL 0 +#define SC_COMMENT 1 +#define SC_LINE_COMMENT 2 +#define SC_STRING 3 +#define SC_CHARACTER 4 +#define SC_RULE_ACTION 5 +#define SC_SYMBOL_ACTION 6 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +/* %if-c-only */ +#include <unistd.h> +/* %endif */ +/* %if-c++-only */ +/* %endif */ +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* %if-c-only Reentrant structure and macros (non-C++). */ +/* %if-reentrant */ +/* %if-c-only */ + +static int yy_init_globals (void ); + +/* %endif */ +/* %if-reentrant */ +/* %endif */ +/* %endif End reentrant structures and macros. */ + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int code_lex_destroy (void ); + +int code_get_debug (void ); + +void code_set_debug (int debug_flag ); + +YY_EXTRA_TYPE code_get_extra (void ); + +void code_set_extra (YY_EXTRA_TYPE user_defined ); + +FILE *code_get_in (void ); + +void code_set_in (FILE * in_str ); + +FILE *code_get_out (void ); + +void code_set_out (FILE * out_str ); + +yy_size_t code_get_leng (void ); + +char *code_get_text (void ); + +int code_get_lineno (void ); + +void code_set_lineno (int line_number ); + +/* %if-bison-bridge */ +/* %endif */ + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int code_wrap (void ); +#else +extern int code_wrap (void ); +#endif +#endif + +/* %not-for-header */ + +/* %ok-for-header */ + +/* %endif */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT +/* %if-c-only Standard (non-C++) definition */ +/* %not-for-header */ + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif +/* %ok-for-header */ + +/* %endif */ +#endif + +/* %if-c-only */ + +/* %endif */ + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* %if-c-only Standard (non-C++) definition */ +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( code_text, code_leng, 1, code_out )) {} } while (0) +/* %endif */ +/* %if-c++-only C++ definition */ +/* %endif */ +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ +/* %% [5.0] fread()/read() definition of YY_INPUT goes here unless we're doing C++ \ */\ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( code_in )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( code_in ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, code_in))==0 && ferror(code_in)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(code_in); \ + } \ + }\ +\ +/* %if-c++-only C++ definition \ */\ +/* %endif */ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +/* %if-c-only */ +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +#endif + +/* %if-tables-serialization structures and prototypes */ +/* %not-for-header */ + +/* %ok-for-header */ + +/* %not-for-header */ + +/* %tables-yydmap generated elements */ +/* %endif */ +/* end tables serialization structures and prototypes */ + +/* %ok-for-header */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 +/* %if-c-only Standard (non-C++) definition */ + +extern int code_lex (void); + +#define YY_DECL int code_lex (void) +/* %endif */ +/* %if-c++-only C++ definition */ +/* %endif */ +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after code_text and code_leng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +/* %% [6.0] YY_RULE_SETUP definition goes here */ +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/* %not-for-header */ + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +/* %% [7.0] user's declarations go here */ +#line 96 "../../src/scan-code.l" + + + + /* This scanner is special: it is invoked only once, henceforth + is expected to return only once. This initialization is + therefore done once per action to translate. */ + aver (sc_context == SC_SYMBOL_ACTION + || sc_context == SC_RULE_ACTION + || sc_context == INITIAL); + BEGIN sc_context; + + + /*------------------------------------------------------------. + | Scanning a C comment. The initial '/ *' is already eaten. | + `------------------------------------------------------------*/ + +#line 976 "src/scan-code.c" + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! code_in ) +/* %if-c-only */ + code_in = stdin; +/* %endif */ +/* %if-c++-only */ +/* %endif */ + + if ( ! code_out ) +/* %if-c-only */ + code_out = stdout; +/* %endif */ +/* %if-c++-only */ +/* %endif */ + + if ( ! YY_CURRENT_BUFFER ) { + code_ensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + code__create_buffer(code_in,YY_BUF_SIZE ); + } + + code__load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { +/* %% [8.0] yymore()-related code goes here */ + yy_cp = (yy_c_buf_p); + + /* Support of code_text. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + +/* %% [9.0] code to set up and find next match goes here */ + yy_current_state = (yy_start); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 91 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_current_state != 90 ); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + +yy_find_action: +/* %% [10.0] code to find the action number goes here */ + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +/* %% [11.0] code for code_lineno update goes here */ + +do_action: /* This label is used only to access EOF actions. */ + +/* %% [12.0] debug code goes here */ + if ( code__flex_debug ) + { + if ( yy_act == 0 ) + fprintf( stderr, "--scanner backing up\n" ); + else if ( yy_act < 18 ) + fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n", + (long)yy_rule_linenum[yy_act], code_text ); + else if ( yy_act == 18 ) + fprintf( stderr, "--accepting default rule (\"%s\")\n", + code_text ); + else if ( yy_act == 19 ) + fprintf( stderr, "--(end of buffer or a NUL)\n" ); + else + fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); + } + + switch ( yy_act ) + { /* beginning of action switch */ +/* %% [13.0] actions go here */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +/* rule 1 can match eol */ +YY_RULE_SETUP +#line 114 "../../src/scan-code.l" +STRING_GROW; BEGIN sc_context; + YY_BREAK + +/*--------------------------------------------------------------. + | Scanning a line comment. The initial '//' is already eaten. | + `--------------------------------------------------------------*/ + + +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +#line 124 "../../src/scan-code.l" +STRING_GROW; BEGIN sc_context; + YY_BREAK +case 3: +/* rule 3 can match eol */ +YY_RULE_SETUP +#line 125 "../../src/scan-code.l" +STRING_GROW; + YY_BREAK + +/*--------------------------------------------. + | Scanning user-code characters and strings. | + `--------------------------------------------*/ + + +case 4: +/* rule 4 can match eol */ +YY_RULE_SETUP +#line 135 "../../src/scan-code.l" +STRING_GROW; + YY_BREAK + + + +case 5: +YY_RULE_SETUP +#line 140 "../../src/scan-code.l" +STRING_GROW; BEGIN sc_context; + YY_BREAK + + + +case 6: +YY_RULE_SETUP +#line 145 "../../src/scan-code.l" +STRING_GROW; BEGIN sc_context; + YY_BREAK + + + +case 7: +YY_RULE_SETUP +#line 151 "../../src/scan-code.l" +STRING_GROW; BEGIN SC_CHARACTER; + YY_BREAK +case 8: +YY_RULE_SETUP +#line 152 "../../src/scan-code.l" +STRING_GROW; BEGIN SC_STRING; + YY_BREAK +case 9: +/* rule 9 can match eol */ +YY_RULE_SETUP +#line 153 "../../src/scan-code.l" +STRING_GROW; BEGIN SC_COMMENT; + YY_BREAK +case 10: +/* rule 10 can match eol */ +YY_RULE_SETUP +#line 154 "../../src/scan-code.l" +STRING_GROW; BEGIN SC_LINE_COMMENT; + YY_BREAK +case 11: +YY_RULE_SETUP +#line 156 "../../src/scan-code.l" +{ + complain (loc, Wother, _("stray '%s'"), code_text); + obstack_escape (&obstack_for_string, code_text); + } + YY_BREAK + + + +case 12: +YY_RULE_SETUP +#line 164 "../../src/scan-code.l" +{ + ref_tail_fields = NULL; + handle_action_dollar (self->rule, code_text, *loc); + if (ref_tail_fields) + obstack_sgrow (&obstack_for_string, ref_tail_fields); + } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 170 "../../src/scan-code.l" +{ + ref_tail_fields = NULL; + handle_action_at (self->rule, code_text, *loc); + if (ref_tail_fields) + obstack_sgrow (&obstack_for_string, ref_tail_fields); + } + YY_BREAK + + + +case 14: +YY_RULE_SETUP +#line 180 "../../src/scan-code.l" +{ + const char *type_name = NULL; + fetch_type_name (code_text + 1, &type_name, *loc)[-1] = 0; + obstack_sgrow (&obstack_for_string, "]b4_dollar_dollar("); + obstack_quote (&obstack_for_string, type_name); + obstack_sgrow (&obstack_for_string, ")["); + self->is_value_used = true; + } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 188 "../../src/scan-code.l" +{ + obstack_sgrow (&obstack_for_string, "]b4_at_dollar["); + muscle_percent_define_ensure("locations", the_location, true); + } + YY_BREAK + + + +/* Escape M4 quoting characters in C code. */ +case 16: +YY_RULE_SETUP +#line 198 "../../src/scan-code.l" +obstack_escape (&obstack_for_string, code_text); + YY_BREAK +/* By default, grow the string obstack with the input. */ +case 17: +/* rule 17 can match eol */ +YY_RULE_SETUP +#line 201 "../../src/scan-code.l" +STRING_GROW; + YY_BREAK +/* End of processing. */ +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(SC_COMMENT): +case YY_STATE_EOF(SC_LINE_COMMENT): +case YY_STATE_EOF(SC_STRING): +case YY_STATE_EOF(SC_CHARACTER): +case YY_STATE_EOF(SC_RULE_ACTION): +case YY_STATE_EOF(SC_SYMBOL_ACTION): +#line 204 "../../src/scan-code.l" +STRING_FINISH; return last_string; + YY_BREAK + +case 18: +YY_RULE_SETUP +#line 207 "../../src/scan-code.l" +YY_FATAL_ERROR( "flex scanner jammed" ); + YY_BREAK +#line 1250 "src/scan-code.c" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed code_in at a new source and called + * code_lex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = code_in; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { +/* %% [14.0] code to do back-up for compressed tables and set up yy_cp goes here */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( code_wrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * code_text, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of code_lex */ +/* %ok-for-header */ + +/* %if-c++-only */ +/* %not-for-header */ + +/* %ok-for-header */ + +/* %endif */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +/* %if-c-only */ +static int yy_get_next_buffer (void) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + yy_size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + yy_size_t new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + code_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + code_restart(code_in ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) code_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +/* %if-c-only */ +/* %not-for-header */ + + static yy_state_type yy_get_previous_state (void) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + register yy_state_type yy_current_state; + register char *yy_cp; + +/* %% [15.0] code to get the start state into yy_current_state goes here */ + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { +/* %% [16.0] code to find the next state goes here */ + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 18); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 91 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ +/* %if-c-only */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + register int yy_is_jam; + /* %% [17.0] code to find the next state, and perhaps do backing up, goes here */ + register char *yy_cp = (yy_c_buf_p); + + register YY_CHAR yy_c = 18; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 91 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 90); + + return yy_is_jam ? 0 : yy_current_state; +} + +/* %if-c-only */ + +/* %endif */ + +/* %if-c-only */ +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + code_restart(code_in ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( code_wrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve code_text */ + (yy_hold_char) = *++(yy_c_buf_p); + +/* %% [19.0] update BOL and code_lineno */ + + return c; +} +/* %if-c-only */ +#endif /* ifndef YY_NO_INPUT */ +/* %endif */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ +/* %if-c-only */ + void code_restart (FILE * input_file ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + + if ( ! YY_CURRENT_BUFFER ){ + code_ensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + code__create_buffer(code_in,YY_BUF_SIZE ); + } + + code__init_buffer(YY_CURRENT_BUFFER,input_file ); + code__load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ +/* %if-c-only */ + void code__switch_to_buffer (YY_BUFFER_STATE new_buffer ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + + /* TODO. We should be able to replace this entire function body + * with + * code_pop_buffer_state(); + * code_push_buffer_state(new_buffer); + */ + code_ensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + code__load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (code_wrap()) processing, but the only time this flag + * is looked at is after code_wrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +/* %if-c-only */ +static void code__load_buffer_state (void) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + code_in = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ +/* %if-c-only */ + YY_BUFFER_STATE code__create_buffer (FILE * file, int size ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) code_alloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in code__create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) code_alloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in code__create_buffer()" ); + + b->yy_is_our_buffer = 1; + + code__init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with code__create_buffer() + * + */ +/* %if-c-only */ + void code__delete_buffer (YY_BUFFER_STATE b ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + code_free((void *) b->yy_ch_buf ); + + code_free((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a code_restart() or at EOF. + */ +/* %if-c-only */ + static void code__init_buffer (YY_BUFFER_STATE b, FILE * file ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ + +{ + int oerrno = errno; + + code__flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then code__init_buffer was _probably_ + * called from code_restart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + +/* %if-c-only */ + + b->yy_is_interactive = 0; + +/* %endif */ +/* %if-c++-only */ +/* %endif */ + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ +/* %if-c-only */ + void code__flush_buffer (YY_BUFFER_STATE b ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + code__load_buffer_state( ); +} + +/* %if-c-or-c++ */ +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +/* %if-c-only */ +void code_push_buffer_state (YY_BUFFER_STATE new_buffer ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + if (new_buffer == NULL) + return; + + code_ensure_buffer_stack(); + + /* This block is copied from code__switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from code__switch_to_buffer. */ + code__load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} +/* %endif */ + +/* %if-c-or-c++ */ +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +/* %if-c-only */ +void code_pop_buffer_state (void) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + if (!YY_CURRENT_BUFFER) + return; + + code__delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + code__load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} +/* %endif */ + +/* %if-c-or-c++ */ +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +/* %if-c-only */ +static void code_ensure_buffer_stack (void) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + yy_size_t num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)code_alloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in code_ensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)code_realloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in code_ensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} +/* %endif */ + +/* %if-c-only */ +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE code__scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) code_alloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in code__scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + code__switch_to_buffer(b ); + + return b; +} +/* %endif */ + +/* %if-c-only */ +/** Setup the input buffer state to scan a string. The next call to code_lex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * code__scan_bytes() instead. + */ +YY_BUFFER_STATE code__scan_string (yyconst char * yystr ) +{ + + return code__scan_bytes(yystr,strlen(yystr) ); +} +/* %endif */ + +/* %if-c-only */ +/** Setup the input buffer state to scan the given bytes. The next call to code_lex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE code__scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) code_alloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in code__scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = code__scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in code__scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} +/* %endif */ + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +/* %if-c-only */ +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} +/* %endif */ +/* %if-c++-only */ +/* %endif */ + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up code_text. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + code_text[code_leng] = (yy_hold_char); \ + (yy_c_buf_p) = code_text + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + code_leng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/* %if-c-only */ +/* %if-reentrant */ +/* %endif */ + +/** Get the current line number. + * + */ +int code_get_lineno (void) +{ + + return code_lineno; +} + +/** Get the input stream. + * + */ +FILE *code_get_in (void) +{ + return code_in; +} + +/** Get the output stream. + * + */ +FILE *code_get_out (void) +{ + return code_out; +} + +/** Get the length of the current token. + * + */ +yy_size_t code_get_leng (void) +{ + return code_leng; +} + +/** Get the current token. + * + */ + +char *code_get_text (void) +{ + return code_text; +} + +/* %if-reentrant */ +/* %endif */ + +/** Set the current line number. + * @param line_number + * + */ +void code_set_lineno (int line_number ) +{ + + code_lineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see code__switch_to_buffer + */ +void code_set_in (FILE * in_str ) +{ + code_in = in_str ; +} + +void code_set_out (FILE * out_str ) +{ + code_out = out_str ; +} + +int code_get_debug (void) +{ + return code__flex_debug; +} + +void code_set_debug (int bdebug ) +{ + code__flex_debug = bdebug ; +} + +/* %endif */ + +/* %if-reentrant */ +/* %if-bison-bridge */ +/* %endif */ +/* %endif if-c-only */ + +/* %if-c-only */ +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from code_lex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + code_in = stdin; + code_out = stdout; +#else + code_in = (FILE *) 0; + code_out = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * code_lex_init() + */ + return 0; +} +/* %endif */ + +/* %if-c-only SNIP! this currently causes conflicts with the c++ scanner */ +/* code_lex_destroy is for both reentrant and non-reentrant scanners. */ +int code_lex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + code__delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + code_pop_buffer_state(); + } + + /* Destroy the stack itself. */ + code_free((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * code_lex() is called, initialization will occur. */ + yy_init_globals( ); + +/* %if-reentrant */ +/* %endif */ + return 0; +} +/* %endif */ + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *code_alloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *code_realloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void code_free (void * ptr ) +{ + free( (char *) ptr ); /* see code_realloc() for (char *) cast */ +} + +/* %if-tables-serialization definitions */ +/* %define-yytables The name for this specific scanner's tables. */ +#define YYTABLES_NAME "yytables" +/* %endif */ + +/* %ok-for-header */ + +#line 207 "../../src/scan-code.l" + + + +static inline bool +is_dot_or_dash (char ch) +{ + return ch == '.' || ch == '-'; +} + +static inline bool +contains_dot_or_dash (const char* p) +{ + for (; *p; ++p) + if (is_dot_or_dash (*p)) + return true; + return false; +} + +/* Defines a variant of a symbolic name resolution. */ +typedef struct +{ + /* Index in symbol list. */ + unsigned symbol_index; + + /* Matched symbol id and loc. */ + uniqstr id; + location loc; + + /* Hiding named reference. */ + named_ref* hidden_by; + + /* Error flags. May contain zero (no errors) or + a combination of VARIANT_* values. */ + unsigned err; +} variant; + +/* Set when the variant refers to a symbol hidden + by an explicit symbol reference. */ +#define VARIANT_HIDDEN (1 << 0) + +/* Set when the variant refers to a symbol containing + dots or dashes. Will require explicit bracketing. */ +#define VARIANT_BAD_BRACKETING (1 << 1) + +/* Set when the variant refers to a symbol which is + not visible from current midrule. */ +#define VARIANT_NOT_VISIBLE_FROM_MIDRULE (1 << 2) + +static variant *variant_table = NULL; +static unsigned variant_table_size = 0; +static unsigned variant_count = 0; + +static variant * +variant_table_grow (void) +{ + ++variant_count; + if (variant_count > variant_table_size) + { + while (variant_count > variant_table_size) + variant_table_size = 2 * variant_table_size + 3; + variant_table = xnrealloc (variant_table, variant_table_size, + sizeof *variant_table); + } + return &variant_table[variant_count - 1]; +} + +static void +variant_table_free (void) +{ + free (variant_table); + variant_table = NULL; + variant_table_size = variant_count = 0; +} + +static char * +find_prefix_end (const char *prefix, char *begin, char *end) +{ + char *ptr = begin; + + for (; *prefix && ptr != end; ++prefix, ++ptr) + if (*prefix != *ptr) + return 0; + + if (*prefix) + return 0; + + return ptr; +} + +static variant * +variant_add (uniqstr id, location id_loc, unsigned symbol_index, + char *cp, char *cp_end, bool explicit_bracketing) +{ + char *prefix_end; + + prefix_end = find_prefix_end (id, cp, cp_end); + if (prefix_end && + (prefix_end == cp_end || + (!explicit_bracketing && is_dot_or_dash (*prefix_end)))) + { + variant *r = variant_table_grow (); + r->symbol_index = symbol_index; + r->id = id; + r->loc = id_loc; + r->hidden_by = NULL; + r->err = 0; + return r; + } + else + return NULL; +} + +static const char * +get_at_spec(unsigned symbol_index) +{ + static char at_buf[20]; + if (symbol_index == 0) + strcpy (at_buf, "$$"); + else + snprintf (at_buf, sizeof at_buf, "$%u", symbol_index); + return at_buf; +} + +static void +show_sub_message (warnings warning, + const char* cp, bool explicit_bracketing, + int midrule_rhs_index, char dollar_or_at, + unsigned indent, const variant *var) +{ + const char *at_spec = get_at_spec (var->symbol_index); + + if (var->err == 0) + complain_indent (&var->loc, warning, &indent, + _("refers to: %c%s at %s"), dollar_or_at, + var->id, at_spec); + else + { + static struct obstack msg_buf; + const char *tail = explicit_bracketing ? "" : cp + strlen (var->id); + const char *id = var->hidden_by ? var->hidden_by->id : var->id; + location id_loc = var->hidden_by ? var->hidden_by->loc : var->loc; + + /* Create the explanation message. */ + obstack_init (&msg_buf); + + obstack_printf (&msg_buf, _("possibly meant: %c"), dollar_or_at); + if (contains_dot_or_dash (id)) + obstack_printf (&msg_buf, "[%s]", id); + else + obstack_sgrow (&msg_buf, id); + obstack_sgrow (&msg_buf, tail); + + if (var->err & VARIANT_HIDDEN) + { + obstack_printf (&msg_buf, _(", hiding %c"), dollar_or_at); + if (contains_dot_or_dash (var->id)) + obstack_printf (&msg_buf, "[%s]", var->id); + else + obstack_sgrow (&msg_buf, var->id); + obstack_sgrow (&msg_buf, tail); + } + + obstack_printf (&msg_buf, _(" at %s"), at_spec); + + if (var->err & VARIANT_NOT_VISIBLE_FROM_MIDRULE) + obstack_printf (&msg_buf, + _(", cannot be accessed from mid-rule action at $%d"), + midrule_rhs_index); + + complain_indent (&id_loc, warning, &indent, "%s", + obstack_finish0 (&msg_buf)); + obstack_free (&msg_buf, 0); + } +} + +static void +show_sub_messages (warnings warning, + const char* cp, bool explicit_bracketing, + int midrule_rhs_index, char dollar_or_at, + unsigned indent) +{ + unsigned i; + + for (i = 0; i < variant_count; ++i) + show_sub_message (warning | silent, + cp, explicit_bracketing, + midrule_rhs_index, dollar_or_at, + indent, &variant_table[i]); +} + +/* Returned from "parse_ref" when the reference + is inappropriate. */ +#define INVALID_REF (INT_MIN) + +/* Returned from "parse_ref" when the reference + points to LHS ($$) of the current rule or midrule. */ +#define LHS_REF (INT_MIN + 1) + +/* Parse named or positional reference. In case of positional + references, can return negative values for $-n "deep" stack + accesses. */ +static long int +parse_ref (char *cp, symbol_list *rule, int rule_length, + int midrule_rhs_index, char *text, location text_loc, + char dollar_or_at) +{ + symbol_list *l; + char *cp_end; + bool explicit_bracketing; + unsigned i; + unsigned valid_variants = 0; + unsigned valid_variant_index = 0; + + if ('$' == *cp) + return LHS_REF; + + if (c_isdigit (*cp) || (*cp == '-' && c_isdigit (* (cp + 1)))) + { + long int num = strtol (cp, &cp, 10); + if (1 - INT_MAX + rule_length <= num && num <= rule_length) + return num; + else + { + complain (&text_loc, complaint, _("integer out of range: %s"), + quote (text)); + return INVALID_REF; + } + } + + if ('[' == *cp) + { + /* Ignore the brackets. */ + char *p; + for (p = ++cp; *p != ']'; ++p) + continue; + cp_end = p; + + explicit_bracketing = true; + } + else + { + /* Take all characters of the name. */ + char* p; + for (p = cp; *p; ++p) + if (is_dot_or_dash (*p)) + { + ref_tail_fields = p; + break; + } + for (p = cp; *p; ++p) + continue; + cp_end = p; + + explicit_bracketing = false; + } + + /* Add all relevant variants. */ + { + unsigned symbol_index; + variant_count = 0; + for (symbol_index = 0, l = rule; !symbol_list_null (l); + ++symbol_index, l = l->next) + { + variant *var; + if (l->content_type != SYMLIST_SYMBOL) + continue; + + var = variant_add (l->content.sym->tag, l->sym_loc, + symbol_index, cp, cp_end, explicit_bracketing); + if (var && l->named_ref) + var->hidden_by = l->named_ref; + + if (l->named_ref) + variant_add (l->named_ref->id, l->named_ref->loc, + symbol_index, cp, cp_end, explicit_bracketing); + } + } + + /* Check errors. */ + for (i = 0; i < variant_count; ++i) + { + variant *var = &variant_table[i]; + unsigned symbol_index = var->symbol_index; + + /* Check visibility from mid-rule actions. */ + if (midrule_rhs_index != 0 + && (symbol_index == 0 || midrule_rhs_index < symbol_index)) + var->err |= VARIANT_NOT_VISIBLE_FROM_MIDRULE; + + /* Check correct bracketing. */ + if (!explicit_bracketing && contains_dot_or_dash (var->id)) + var->err |= VARIANT_BAD_BRACKETING; + + /* Check using of hidden symbols. */ + if (var->hidden_by) + var->err |= VARIANT_HIDDEN; + + if (!var->err) + { + valid_variant_index = i; + ++valid_variants; + } + } + + switch (valid_variants) + { + case 0: + { + unsigned len = (explicit_bracketing || !ref_tail_fields) ? + cp_end - cp : ref_tail_fields - cp; + unsigned indent = 0; + + complain_indent (&text_loc, complaint, &indent, + _("invalid reference: %s"), quote (text)); + indent += SUB_INDENT; + if (len == 0) + { + location sym_loc = text_loc; + sym_loc.start.column += 1; + sym_loc.end = sym_loc.start; + complain_indent (&sym_loc, complaint, &indent, + _("syntax error after '%c', expecting integer, " + "letter, '_', '[', or '$'"), + dollar_or_at); + } + else if (midrule_rhs_index) + complain_indent (&rule->location, complaint, &indent, + _("symbol not found in production before $%d: " + "%.*s"), + midrule_rhs_index, len, cp); + else + complain_indent (&rule->location, complaint, &indent, + _("symbol not found in production: %.*s"), + len, cp); + + if (variant_count > 0) + show_sub_messages (complaint, + cp, explicit_bracketing, midrule_rhs_index, + dollar_or_at, indent); + return INVALID_REF; + } + case 1: + { + unsigned indent = 0; + if (variant_count > 1) + { + complain_indent (&text_loc, Wother, &indent, + _("misleading reference: %s"), quote (text)); + show_sub_messages (Wother, + cp, explicit_bracketing, midrule_rhs_index, + dollar_or_at, indent + SUB_INDENT); + } + { + unsigned symbol_index = + variant_table[valid_variant_index].symbol_index; + return (symbol_index == midrule_rhs_index) ? LHS_REF : symbol_index; + } + } + case 2: + default: + { + unsigned indent = 0; + complain_indent (&text_loc, complaint, &indent, + _("ambiguous reference: %s"), quote (text)); + show_sub_messages (complaint, + cp, explicit_bracketing, midrule_rhs_index, + dollar_or_at, indent + SUB_INDENT); + return INVALID_REF; + } + } + + /* Not reachable. */ + return INVALID_REF; +} + +/* Keeps track of the maximum number of semantic values to the left of + a handle (those referenced by $0, $-1, etc.) are required by the + semantic actions of this grammar. */ +int max_left_semantic_context = 0; + + +/* If CP points to a typename (i.e., <.*?>), set TYPE_NAME to its + beginning (i.e., after the opening "<", and return the pointer + immediately after it. */ + +static +char * +fetch_type_name (char *cp, char const **type_name, + location dollar_loc) +{ + if (*cp == '<') + { + *type_name = ++cp; + /* Series of non-'>' or "->". */ + while (*cp != '>' || cp[-1] == '-') + ++cp; + + /* The '>' symbol will be later replaced by '\0'. Original + 'text' is needed for error messages. */ + ++cp; + if (untyped_var_seen) + complain (&dollar_loc, complaint, + _("explicit type given in untyped grammar")); + tag_seen = true; + } + return cp; +} + +/*------------------------------------------------------------------. +| TEXT is pointing to a wannabee semantic value (i.e., a '$'). | +| | +| Possible inputs: $[<TYPENAME>]($|integer) | +| | +| Output to OBSTACK_FOR_STRING a reference to this semantic value. | +`------------------------------------------------------------------*/ + +static void +handle_action_dollar (symbol_list *rule, char *text, location dollar_loc) +{ + char const *type_name = NULL; + char *cp = text + 1; + symbol_list *effective_rule; + int effective_rule_length; + int n; + + if (rule->midrule_parent_rule) + { + effective_rule = rule->midrule_parent_rule; + effective_rule_length = rule->midrule_parent_rhs_index - 1; + } + else + { + effective_rule = rule; + effective_rule_length = symbol_list_length (rule->next); + } + + /* Get the type name if explicit. */ + cp = fetch_type_name (cp, &type_name, dollar_loc); + + n = parse_ref (cp, effective_rule, effective_rule_length, + rule->midrule_parent_rhs_index, text, dollar_loc, '$'); + + /* End type_name. */ + if (type_name) + cp[-1] = '\0'; + + switch (n) + { + case INVALID_REF: + break; + + case LHS_REF: + if (!type_name) + type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0); + + if (!type_name) + { + if (union_seen | tag_seen) + { + if (rule->midrule_parent_rule) + complain (&dollar_loc, complaint, + _("$$ for the midrule at $%d of %s" + " has no declared type"), + rule->midrule_parent_rhs_index, + quote (effective_rule->content.sym->tag)); + else + complain (&dollar_loc, complaint, + _("$$ of %s has no declared type"), + quote (rule->content.sym->tag)); + } + else + untyped_var_seen = true; + } + + obstack_sgrow (&obstack_for_string, "]b4_lhs_value("); + obstack_quote (&obstack_for_string, type_name); + obstack_sgrow (&obstack_for_string, ")["); + rule->action_props.is_value_used = true; + break; + + default: + if (max_left_semantic_context < 1 - n) + max_left_semantic_context = 1 - n; + if (!type_name && 0 < n) + type_name = + symbol_list_n_type_name_get (effective_rule, dollar_loc, n); + if (!type_name) + { + if (union_seen | tag_seen) + complain (&dollar_loc, complaint, + _("$%s of %s has no declared type"), cp, + quote (effective_rule->content.sym->tag)); + else + untyped_var_seen = true; + } + + obstack_printf (&obstack_for_string, + "]b4_rhs_value(%d, %d, ", effective_rule_length, n); + obstack_quote (&obstack_for_string, type_name); + obstack_sgrow (&obstack_for_string, ")["); + if (n > 0) + symbol_list_n_get (effective_rule, n)->action_props.is_value_used = + true; + break; + } +} + + +/*------------------------------------------------------. +| TEXT is a location token (i.e., a '@...'). Output to | +| OBSTACK_FOR_STRING a reference to this location. | +`------------------------------------------------------*/ + +static void +handle_action_at (symbol_list *rule, char *text, location at_loc) +{ + char *cp = text + 1; + symbol_list *effective_rule; + int effective_rule_length; + int n; + + if (rule->midrule_parent_rule) + { + effective_rule = rule->midrule_parent_rule; + effective_rule_length = rule->midrule_parent_rhs_index - 1; + } + else + { + effective_rule = rule; + effective_rule_length = symbol_list_length (rule->next); + } + + muscle_percent_define_ensure("locations", at_loc, true); + + n = parse_ref (cp, effective_rule, effective_rule_length, + rule->midrule_parent_rhs_index, text, at_loc, '@'); + switch (n) + { + case INVALID_REF: + break; + + case LHS_REF: + obstack_sgrow (&obstack_for_string, "]b4_lhs_location["); + break; + + default: + obstack_printf (&obstack_for_string, "]b4_rhs_location(%d, %d)[", + effective_rule_length, n); + break; + } +} + + +/*-------------------------. +| Initialize the scanner. | +`-------------------------*/ + +/* Translate the dollars and ats in \a self, in the context \a sc_context + (SC_RULE_ACTION, SC_SYMBOL_ACTION, INITIAL). */ + +static char const * +translate_action (code_props *self, int sc_context) +{ + char *res; + static bool initialized = false; + if (!initialized) + { + obstack_init (&obstack_for_string); + code__flex_debug = 0; + initialized = true; + } + + loc->start = loc->end = self->location.start; + code__switch_to_buffer (code__scan_string (self->code)); + res = code_lex (self, sc_context); + code__delete_buffer (YY_CURRENT_BUFFER); + + return res; +} + +/*------------------------------------------------------------------------. +| Implementation of the public interface as documented in "scan-code.h". | +`------------------------------------------------------------------------*/ + +void +code_props_none_init (code_props *self) +{ + *self = code_props_none; +} + +code_props code_props_none = CODE_PROPS_NONE_INIT; + +void +code_props_plain_init (code_props *self, char const *code, + location code_loc) +{ + code_props_none_init (self); + self->kind = CODE_PROPS_PLAIN; + self->code = code; + self->location = code_loc; +} + +void +code_props_symbol_action_init (code_props *self, char const *code, + location code_loc) +{ + code_props_none_init (self); + self->kind = CODE_PROPS_SYMBOL_ACTION; + self->code = code; + self->location = code_loc; +} + +void +code_props_rule_action_init (code_props *self, char const *code, + location code_loc, symbol_list *rule, + named_ref *name, bool is_predicate) +{ + code_props_none_init (self); + self->kind = CODE_PROPS_RULE_ACTION; + self->code = code; + self->location = code_loc; + self->rule = rule; + self->named_ref = name; + self->is_predicate = is_predicate; +} + +void +code_props_translate_code (code_props *self) +{ + switch (self->kind) + { + case CODE_PROPS_NONE: + break; + case CODE_PROPS_PLAIN: + self->code = translate_action (self, INITIAL); + break; + case CODE_PROPS_SYMBOL_ACTION: + self->code = translate_action (self, SC_SYMBOL_ACTION); + break; + case CODE_PROPS_RULE_ACTION: + self->code = translate_action (self, SC_RULE_ACTION); + break; + } +} + +void +code_scanner_last_string_free (void) +{ + STRING_FREE; +} + +void +code_scanner_free (void) +{ + obstack_free (&obstack_for_string, 0); + variant_table_free (); + + /* Reclaim Flex's buffers. */ + code_lex_destroy (); +} + diff --git a/contrib/tools/bison/src/scan-code.h b/contrib/tools/bison/src/scan-code.h new file mode 100644 index 0000000000..d5a15c1a1c --- /dev/null +++ b/contrib/tools/bison/src/scan-code.h @@ -0,0 +1,196 @@ +/* Bison code properties structure and scanner. + + Copyright (C) 2006-2007, 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef SCAN_CODE_H_ +# define SCAN_CODE_H_ + +# include "location.h" +# include "named-ref.h" + +struct symbol_list; + +/** + * Keeps track of the maximum number of semantic values to the left of a handle + * (those referenced by $0, $-1, etc.) that are required by the semantic + * actions of this grammar. + */ +extern int max_left_semantic_context; + +/** + * A code passage captured from the grammar file and possibly translated, + * and/or properties associated with such a code passage. Don't break + * encapsulation by modifying the fields directly. Use the provided interface + * functions. + */ +typedef struct code_props { + /** Set by the init functions. */ + enum { + CODE_PROPS_NONE, CODE_PROPS_PLAIN, + CODE_PROPS_SYMBOL_ACTION, CODE_PROPS_RULE_ACTION + } kind; + + /** + * \c NULL iff \c code_props::kind is \c CODE_PROPS_NONE. + * Memory is allocated in an obstack freed elsewhere. + */ + char const *code; + /** Undefined iff \c code_props::code is \c NULL. */ + location location; + + /** + * \c false iff either: + * - \c code_props_translate_code has never previously been invoked for + * the \c code_props that would contain the code passage associated + * with \c self. (That \c code_props is not the same as this one if this + * one is for a RHS \c symbol_list node. Instead, it's the \c code_props + * for the LHS symbol of the same rule.) + * - \c code_props_translate_code has been invoked for that \c code_props, + * but the symbol value associated with this \c code_props was not + * referenced in the code passage. + */ + bool is_value_used; + + /** + * \c true iff this code is an action that is not to be deferred in + * a non-deterministic parser. + */ + bool is_predicate; + + /** + * Whether this is actually used (i.e., not completely masked by + * other code props). */ + bool is_used; + + /** \c NULL iff \c code_props::kind is not \c CODE_PROPS_RULE_ACTION. */ + struct symbol_list *rule; + + /* Named reference. */ + named_ref *named_ref; +} code_props; + +/** + * \pre + * - <tt>self != NULL</tt>. + * \post + * - \c self has been overwritten to contain no code. + */ +void code_props_none_init (code_props *self); + +/** Equivalent to \c code_props_none_init. */ +# define CODE_PROPS_NONE_INIT \ + { \ + /* .kind = */ CODE_PROPS_NONE, \ + /* .code = */ NULL, \ + /* .location = */ EMPTY_LOCATION_INIT, \ + /* .is_value_used = */ false, \ + /* .is_predicate = */ false, \ + /* .is_used = */ false, \ + /* .rule = */ NULL, \ + /* .named_ref = */ NULL \ + } + +/** Initialized by \c CODE_PROPS_NONE_INIT with no further modification. */ +extern code_props code_props_none; + +/** + * \pre + * - <tt>self != NULL</tt>. + * - <tt>code != NULL</tt>. + * - \c code is an untranslated code passage containing no Bison escapes. + * - \c code was extracted from the grammar file at \c code_loc. + * \post + * - \c self has been overwritten to represent the specified plain code + * passage. + * - \c self will become invalid if the caller frees \c code before invoking + * \c code_props_translate_code on \c self. + */ +void code_props_plain_init (code_props *self, char const *code, + location code_loc); + +/** + * \pre + * - <tt>self != NULL</tt>. + * - <tt>code != NULL</tt>. + * - \c code is an untranslated code passage. The only Bison escapes it + * might contain are $$ and \@$, referring to a single symbol. + * - \c code was extracted from the grammar file at \c code_loc. + * \post + * - \c self has been overwritten to represent the specified symbol action. + * - \c self will become invalid if the caller frees \c code before invoking + * \c code_props_translate_code on \c self. + */ +void code_props_symbol_action_init (code_props *self, char const *code, + location code_loc); + +/** + * \pre + * - <tt>self != NULL</tt>. + * - <tt>code != NULL</tt>. + * - <tt>rule != NULL</tt>. + * - \c code is the untranslated action of the rule for which \c rule is the + * LHS node. Thus, \c code possibly contains Bison escapes such as $$, $1, + * $2, etc referring to the values of the rule. + * - \c code was extracted from the grammar file at \c code_loc. + * \post + * - \c self has been overwritten to represent the specified rule action. + * - \c self does not claim responsibility for the memory of \c rule. + * - \c self will become invalid if: + * - The caller frees \c code before invoking \c code_props_translate_code + * on \c self. + * - The caller frees \c rule. + */ +void code_props_rule_action_init (code_props *self, char const *code, + location code_loc, struct symbol_list *rule, + named_ref *name, bool is_predicate); + +/** + * \pre + * - If there's a code passage contained in \c self and it contains Bison + * escapes, all grammar declarations have already been parsed as they may + * affect warnings and complaints issued here. + * \post + * - All M4-special symbols and Bison escapes have been translated in + * \c self->code. + * - <tt>self->code != self->code\@pre</tt> unless + * <tt>self->code\@pre = NULL</tt>. + */ +void code_props_translate_code (code_props *self); + +/** + * \pre + * - None. + * \post + * - The dynamic memory allocated by the previous invocation of + * \c code_props_translate_code (if any) was freed. The \c code_props + * instance for which \c code_props_translate_code was invoked is now + * invalid. + */ +void code_scanner_last_string_free (void); + +/** + * \pre + * - None. + * \post + * - All dynamic memory allocated during invocations of + * \c code_props_translate_code (if any) has been freed. All \c code_props + * instances may now be invalid. + */ +void code_scanner_free (void); + +#endif /* !SCAN_CODE_H_ */ diff --git a/contrib/tools/bison/src/scan-gram-c.c b/contrib/tools/bison/src/scan-gram-c.c new file mode 100644 index 0000000000..2b4fc67b48 --- /dev/null +++ b/contrib/tools/bison/src/scan-gram-c.c @@ -0,0 +1,3 @@ +#include <config.h> +#include "system.h" +#include "src/scan-gram.c" diff --git a/contrib/tools/bison/src/scan-gram.c b/contrib/tools/bison/src/scan-gram.c new file mode 100644 index 0000000000..3c74a56bea --- /dev/null +++ b/contrib/tools/bison/src/scan-gram.c @@ -0,0 +1,4018 @@ +#line 2 "src/scan-gram.c" + +#line 4 "src/scan-gram.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +/* %not-for-header */ + +/* %if-c-only */ +/* %if-not-reentrant */ +#define yy_create_buffer gram__create_buffer +#define yy_delete_buffer gram__delete_buffer +#define yy_flex_debug gram__flex_debug +#define yy_init_buffer gram__init_buffer +#define yy_flush_buffer gram__flush_buffer +#define yy_load_buffer_state gram__load_buffer_state +#define yy_switch_to_buffer gram__switch_to_buffer +#define yyin gram_in +#define yyleng gram_leng +#define yylex gram_lex +#define yylineno gram_lineno +#define yyout gram_out +#define yyrestart gram_restart +#define yytext gram_text +#define yywrap gram_wrap +#define yyalloc gram_alloc +#define yyrealloc gram_realloc +#define yyfree gram_free + +/* %endif */ +/* %endif */ +/* %ok-for-header */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 37 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* %if-c++-only */ +/* %endif */ + +/* %if-c-only */ + +/* %endif */ + +/* %if-c-only */ + +/* %endif */ + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +/* %if-c-only */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +/* %endif */ + +/* %if-tables-serialization */ +/* %endif */ +/* end standard C headers. */ + +/* %if-c-or-c++ */ +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* %endif */ + +/* %if-c++-only */ +/* %endif */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* %not-for-header */ + +/* Returned upon end-of-file. */ +#define YY_NULL 0 +/* %ok-for-header */ + +/* %not-for-header */ + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) +/* %ok-for-header */ + +/* %if-reentrant */ +/* %endif */ + +/* %if-not-reentrant */ + +/* %endif */ + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE gram_restart(gram_in ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +/* %if-not-reentrant */ +extern yy_size_t gram_leng; +/* %endif */ + +/* %if-c-only */ +/* %if-not-reentrant */ +extern FILE *gram_in, *gram_out; +/* %endif */ +/* %endif */ + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up gram_text. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up gram_text again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { +/* %if-c-only */ + FILE *yy_input_file; +/* %endif */ + +/* %if-c++-only */ +/* %endif */ + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + yy_size_t yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via gram_restart()), so that the user can continue scanning by + * just pointing gram_in at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* %if-c-only Standard (non-C++) definition */ +/* %not-for-header */ + +/* %if-not-reentrant */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ +/* %endif */ +/* %ok-for-header */ + +/* %endif */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* %if-c-only Standard (non-C++) definition */ + +/* %if-not-reentrant */ +/* %not-for-header */ + +/* yy_hold_char holds the character lost when gram_text is formed. */ +static char yy_hold_char; +static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ +yy_size_t gram_leng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow gram_wrap()'s to do buffer switches + * instead of setting up a fresh gram_in. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; +/* %ok-for-header */ + +/* %endif */ + +void gram_restart (FILE *input_file ); +void gram__switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE gram__create_buffer (FILE *file,int size ); +void gram__delete_buffer (YY_BUFFER_STATE b ); +void gram__flush_buffer (YY_BUFFER_STATE b ); +void gram_push_buffer_state (YY_BUFFER_STATE new_buffer ); +void gram_pop_buffer_state (void ); + +static void gram_ensure_buffer_stack (void ); +static void gram__load_buffer_state (void ); +static void gram__init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER gram__flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE gram__scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE gram__scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE gram__scan_bytes (yyconst char *bytes,yy_size_t len ); + +/* %endif */ + +void *gram_alloc (yy_size_t ); +void *gram_realloc (void *,yy_size_t ); +void gram_free (void * ); + +#define yy_new_buffer gram__create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + gram_ensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + gram__create_buffer(gram_in,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + gram_ensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + gram__create_buffer(gram_in,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* %% [1.0] gram_text/gram_in/gram_out/yy_state_type/gram_lineno etc. def's & init go here */ +/* Begin user sect3 */ + +#define gram_wrap() 1 +#define YY_SKIP_YYWRAP + +#define FLEX_DEBUG + +typedef unsigned char YY_CHAR; + +FILE *gram_in = (FILE *) 0, *gram_out = (FILE *) 0; + +typedef int yy_state_type; + +extern int gram_lineno; + +int gram_lineno = 1; + +extern char *gram_text; +#define yytext_ptr gram_text + +/* %if-c-only Standard (non-C++) definition */ + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* %endif */ + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up gram_text. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ +/* %% [2.0] code to fiddle gram_text and gram_leng for yymore() goes here \ */\ + gram_leng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ +/* %% [3.0] code to copy yytext_ptr to gram_text[] goes here, if %array \ */\ + (yy_c_buf_p) = yy_cp; + +/* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */ +#define YY_NUM_RULES 130 +#define YY_END_OF_BUFFER 131 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[582] = + { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 93, 93, 113, 113, 113, 113, 0, 0, + 0, 0, 131, 80, 2, 2, 71, 80, 70, 80, + 1, 66, 80, 67, 67, 65, 77, 63, 66, 79, + 73, 64, 80, 90, 90, 128, 95, 94, 128, 81, + 97, 96, 84, 2, 1, 84, 83, 82, 84, 99, + 99, 100, 98, 81, 129, 119, 128, 118, 128, 128, + 128, 122, 125, 126, 128, 92, 128, 117, 116, 128, + 115, 114, 87, 2, 1, 85, 87, 87, 86, 87, + + 88, 2, 1, 88, 88, 80, 0, 78, 62, 0, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 72, 66, + 66, 4, 3, 69, 67, 69, 0, 76, 0, 89, + 112, 110, 101, 112, 103, 104, 105, 106, 107, 108, + 112, 109, 112, 99, 99, 100, 127, 120, 121, 0, + 123, 0, 122, 124, 0, 91, 0, 0, 93, 113, + 113, 113, 113, 87, 85, 62, 62, 0, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 3, 69, 68, 75, 0, 101, 0, 0, 102, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 74, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 0, 101, 0, 0, 62, 7, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 23, 62, 62, 62, 62, 62, 62, 62, 62, 62, + + 62, 62, 62, 62, 62, 36, 62, 62, 62, 62, + 62, 62, 44, 62, 47, 62, 62, 50, 0, 0, + 0, 62, 8, 62, 62, 62, 13, 14, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 26, 62, 62, + 62, 62, 62, 62, 62, 62, 32, 62, 34, 62, + 62, 62, 62, 62, 62, 41, 62, 43, 45, 48, + 62, 0, 0, 111, 6, 62, 10, 62, 62, 62, + 16, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 33, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 0, 62, + + 11, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 0, 59, 62, 62, 38, 62, 62, 40, + 62, 62, 62, 49, 5, 0, 62, 62, 62, 62, + 62, 62, 62, 62, 62, 62, 62, 62, 22, 62, + 62, 62, 62, 62, 29, 62, 58, 30, 62, 62, + 62, 62, 62, 42, 62, 62, 0, 62, 62, 62, + 62, 62, 17, 53, 62, 62, 62, 62, 62, 24, + 25, 62, 62, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 0, 0, 62, 62, 12, 62, 62, 62, + + 62, 62, 21, 62, 62, 62, 62, 62, 62, 62, + 37, 62, 62, 62, 62, 62, 62, 62, 62, 18, + 62, 62, 62, 27, 56, 62, 62, 62, 35, 39, + 60, 46, 61, 9, 51, 62, 62, 0, 54, 62, + 62, 62, 0, 56, 62, 62, 62, 15, 52, 62, + 62, 62, 62, 62, 62, 62, 62, 20, 62, 62, + 62, 62, 62, 28, 57, 62, 62, 62, 62, 62, + 62, 62, 19, 55, 62, 62, 62, 62, 62, 31, + 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 5, 6, 7, 8, 6, 9, 6, 10, 6, + 6, 11, 6, 12, 13, 14, 15, 16, 17, 17, + 17, 17, 17, 17, 17, 18, 18, 19, 20, 21, + 22, 23, 24, 6, 25, 25, 25, 25, 25, 25, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 27, 26, 26, 28, 26, 26, + 29, 30, 31, 6, 32, 6, 33, 34, 35, 36, + + 37, 38, 39, 40, 41, 26, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 26, 54, + 55, 26, 56, 57, 58, 6, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[60] = + { 0, + 1, 2, 3, 1, 2, 4, 5, 4, 5, 5, + 5, 5, 6, 7, 8, 9, 9, 9, 4, 5, + 10, 5, 10, 4, 9, 11, 11, 11, 12, 4, + 13, 11, 9, 9, 9, 9, 9, 9, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 5, 5, 5, 1 + } ; + +static yyconst flex_int16_t yy_base[609] = + { 0, + 0, 1065, 1061, 1060, 57, 58, 59, 60, 79, 94, + 53, 62, 117, 126, 135, 144, 100, 145, 154, 163, + 68, 69, 65, 70, 98, 155, 101, 164, 221, 1062, + 174, 193, 1069, 0, 1074, 1074, 1074, 280, 1074, 1074, + 1074, 339, 119, 164, 197, 1074, 114, 1074, 398, 1074, + 1074, 1074, 1025, 1074, 1052, 1074, 1074, 1074, 451, 1074, + 1074, 1074, 1074, 1074, 1074, 128, 1074, 1074, 1023, 1052, + 54, 1043, 1074, 1050, 1074, 1074, 1004, 1074, 331, 63, + 190, 1074, 1074, 1074, 153, 1074, 185, 1074, 1074, 346, + 1074, 1074, 0, 1074, 0, 0, 192, 1074, 1074, 1018, + + 1074, 1074, 1074, 339, 1017, 0, 0, 1074, 0, 354, + 1018, 1012, 169, 311, 1016, 1013, 1010, 329, 1017, 331, + 1001, 334, 331, 98, 334, 1007, 1014, 1017, 1074, 505, + 0, 1074, 0, 0, 374, 549, 1026, 1074, 1007, 1074, + 1074, 1074, 357, 0, 1074, 1074, 1074, 1074, 1074, 1074, + 0, 1074, 0, 1034, 365, 1025, 1074, 1074, 1074, 382, + 1074, 391, 1074, 1074, 398, 1074, 406, 410, 1015, 1074, + 416, 1014, 421, 0, 0, 0, 0, 430, 0, 998, + 1006, 393, 992, 993, 990, 991, 362, 988, 995, 990, + 341, 999, 984, 988, 407, 994, 979, 980, 393, 979, + + 979, 987, 988, 991, 974, 980, 974, 979, 970, 983, + 0, 0, 0, 1074, 972, 420, 0, 0, 0, 439, + 434, 445, 174, 451, 442, 457, 410, 468, 474, 485, + 489, 435, 1074, 983, 978, 962, 81, 962, 975, 960, + 964, 972, 971, 970, 993, 954, 965, 952, 989, 968, + 961, 962, 371, 465, 308, 949, 950, 433, 961, 950, + 957, 941, 952, 948, 941, 945, 951, 950, 940, 951, + 949, 946, 1074, 0, 0, 933, 0, 942, 928, 934, + 929, 942, 921, 926, 939, 960, 936, 924, 929, 917, + 0, 921, 916, 929, 442, 928, 923, 926, 921, 911, + + 923, 915, 906, 913, 919, 918, 903, 467, 912, 901, + 914, 899, 0, 904, 0, 903, 901, 0, 941, 0, + 0, 890, 0, 901, 906, 890, 0, 0, 480, 890, + 893, 482, 906, 905, 904, 903, 894, 0, 887, 886, + 894, 886, 892, 884, 878, 876, 0, 875, 0, 912, + 888, 886, 875, 874, 871, 0, 868, 0, 484, 0, + 868, 504, 0, 1074, 0, 866, 866, 880, 861, 860, + 485, 863, 865, 864, 860, 865, 868, 857, 859, 855, + 854, 869, 864, 867, 862, 852, 860, 523, 849, 858, + 845, 860, 859, 854, 844, 838, 837, 850, 534, 502, + + 0, 835, 848, 847, 834, 833, 844, 828, 827, 828, + 864, 839, 842, 829, 836, 835, 819, 820, 817, 818, + 832, 817, 538, 1074, 832, 819, 0, 814, 813, 0, + 816, 827, 826, 0, 1074, 851, 810, 809, 809, 805, + 804, 803, 802, 812, 798, 797, 810, 813, 0, 801, + 794, 805, 804, 798, 0, 797, 0, 0, 795, 789, + 802, 786, 785, 0, 800, 799, 825, 782, 781, 780, + 794, 793, 0, 0, 785, 778, 777, 774, 787, 0, + 0, 780, 779, 768, 767, 776, 783, 768, 764, 762, + 743, 739, 773, 541, 729, 727, 0, 714, 712, 703, + + 704, 700, 0, 700, 681, 657, 517, 525, 664, 662, + 0, 655, 653, 662, 660, 661, 658, 642, 641, 551, + 639, 638, 645, 566, 573, 637, 636, 574, 0, 0, + 0, 0, 0, 0, 0, 577, 576, 587, 1074, 548, + 549, 566, 594, 1074, 562, 561, 558, 0, 0, 569, + 568, 560, 567, 566, 551, 560, 559, 0, 559, 558, + 538, 529, 520, 0, 0, 524, 521, 510, 533, 483, + 482, 484, 0, 0, 490, 461, 457, 445, 420, 0, + 1074, 616, 629, 642, 655, 668, 681, 694, 701, 712, + 725, 738, 749, 756, 764, 772, 783, 791, 437, 388, + + 372, 208, 200, 162, 137, 83, 69, 802 + } ; + +static yyconst flex_int16_t yy_def[609] = + { 0, + 581, 1, 582, 582, 583, 583, 583, 583, 584, 584, + 585, 585, 583, 583, 583, 583, 583, 583, 583, 583, + 583, 583, 583, 583, 583, 583, 583, 583, 581, 29, + 586, 586, 581, 587, 581, 581, 581, 581, 581, 581, + 581, 588, 581, 589, 589, 581, 581, 581, 588, 581, + 581, 581, 587, 581, 581, 581, 581, 581, 590, 581, + 581, 581, 581, 581, 581, 581, 581, 581, 581, 591, + 591, 581, 581, 591, 581, 581, 581, 581, 581, 581, + 581, 581, 581, 581, 581, 581, 581, 581, 581, 592, + 581, 581, 593, 581, 593, 594, 581, 581, 581, 593, + + 581, 581, 581, 581, 581, 587, 595, 581, 596, 595, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 581, 588, + 49, 581, 597, 598, 589, 598, 581, 581, 581, 581, + 581, 581, 581, 599, 581, 581, 581, 581, 581, 581, + 600, 581, 601, 591, 591, 581, 581, 581, 581, 581, + 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, + 581, 581, 581, 593, 594, 595, 596, 581, 595, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 597, 598, 136, 581, 581, 581, 602, 603, 601, 581, + 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, + 581, 592, 581, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 581, 581, 604, 605, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 581, 606, + 607, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 581, 600, 581, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 581, 596, + + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 581, 581, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 581, 581, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 608, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 608, 608, 596, 596, 596, 596, 596, 596, + + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 581, 581, 596, + 596, 596, 581, 581, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 596, 596, 596, 596, 596, 596, 596, 596, 596, 596, + 0, 581, 581, 581, 581, 581, 581, 581, 581, 581, + 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, + + 581, 581, 581, 581, 581, 581, 581, 581 + } ; + +static yyconst flex_int16_t yy_nxt[1134] = + { 0, + 34, 35, 36, 34, 35, 34, 37, 34, 38, 39, + 40, 41, 34, 42, 43, 44, 45, 45, 34, 46, + 47, 48, 40, 34, 49, 49, 49, 49, 50, 34, + 34, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 51, 52, 40, 34, 57, + 57, 61, 61, 58, 58, 71, 155, 86, 62, 62, + 75, 75, 86, 72, 71, 73, 154, 364, 85, 85, + 64, 36, 72, 64, 73, 161, 59, 59, 59, 59, + 65, 363, 162, 66, 87, 64, 36, 67, 64, 87, + + 88, 69, 75, 91, 89, 65, 76, 68, 66, 78, + 92, 74, 67, 279, 79, 60, 60, 60, 60, 75, + 74, 280, 68, 76, 137, 77, 78, 90, 75, 132, + 90, 79, 76, 133, 77, 78, 138, 75, 132, 203, + 79, 76, 133, 80, 78, 321, 75, 75, 204, 79, + 76, 76, 80, 78, 78, 81, 75, 88, 79, 79, + 76, 89, 80, 78, 81, 75, 91, 166, 79, 76, + 320, 80, 78, 92, 81, 102, 36, 79, 102, 135, + 135, 135, 167, 81, 90, 103, 168, 169, 104, 168, + 82, 136, 83, 90, 102, 36, 161, 102, 163, 82, + + 105, 83, 132, 162, 103, 182, 133, 104, 275, 82, + 164, 84, 135, 135, 135, 183, 274, 136, 82, 165, + 84, 93, 94, 36, 93, 94, 93, 93, 93, 93, + 93, 93, 95, 93, 96, 97, 98, 98, 98, 93, + 93, 93, 93, 93, 93, 96, 96, 96, 96, 93, + 93, 99, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 93, 93, 93, 93, + 107, 107, 107, 107, 107, 107, 107, 107, 108, 107, + 107, 107, 107, 109, 107, 107, 107, 107, 107, 107, + + 107, 107, 107, 110, 109, 109, 109, 109, 107, 107, + 107, 109, 109, 111, 112, 113, 114, 115, 116, 109, + 117, 109, 118, 119, 120, 121, 122, 109, 123, 124, + 125, 126, 127, 109, 128, 129, 107, 107, 107, 106, + 300, 158, 106, 301, 106, 159, 106, 171, 172, 132, + 171, 130, 130, 133, 184, 178, 178, 106, 178, 185, + 160, 190, 106, 194, 186, 191, 198, 201, 106, 106, + 205, 202, 216, 216, 192, 173, 195, 155, 248, 206, + 219, 196, 199, 220, 221, 200, 220, 154, 207, 135, + 135, 135, 222, 223, 249, 222, 218, 106, 581, 224, + + 225, 581, 224, 581, 243, 581, 296, 226, 227, 179, + 226, 168, 169, 297, 168, 244, 581, 229, 172, 253, + 229, 581, 231, 232, 166, 231, 236, 581, 581, 259, + 237, 178, 178, 260, 178, 273, 273, 581, 254, 167, + 220, 221, 238, 220, 158, 217, 222, 223, 159, 222, + 163, 255, 224, 225, 339, 224, 581, 142, 226, 227, + 142, 226, 164, 160, 173, 304, 143, 143, 580, 168, + 169, 165, 168, 340, 142, 229, 172, 144, 229, 353, + 142, 579, 305, 145, 146, 233, 229, 172, 147, 229, + 231, 232, 369, 231, 373, 148, 396, 405, 354, 149, + + 298, 150, 151, 152, 153, 106, 578, 299, 106, 577, + 106, 370, 106, 374, 437, 397, 406, 130, 130, 399, + 399, 399, 576, 106, 423, 423, 423, 423, 106, 526, + 575, 574, 573, 438, 106, 106, 435, 527, 436, 423, + 423, 423, 423, 435, 424, 572, 571, 494, 527, 399, + 399, 399, 538, 538, 538, 538, 527, 570, 569, 424, + 550, 551, 568, 106, 213, 213, 213, 543, 543, 543, + 543, 567, 539, 213, 543, 543, 543, 543, 566, 551, + 551, 213, 213, 213, 213, 213, 213, 544, 538, 538, + 538, 538, 565, 564, 544, 543, 543, 543, 543, 563, + + 562, 561, 560, 559, 558, 557, 556, 555, 539, 554, + 553, 552, 549, 548, 547, 544, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 56, + 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 70, 70, 70, 70, 70, + 70, 70, 70, 70, 70, 70, 70, 70, 101, 101, + 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, + 101, 106, 546, 545, 106, 542, 106, 106, 541, 540, + 537, 536, 535, 106, 131, 534, 533, 131, 532, 131, + + 131, 531, 131, 530, 131, 529, 131, 134, 528, 134, + 525, 134, 141, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 154, 154, 154, 154, 154, + 154, 154, 154, 154, 524, 154, 154, 154, 170, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 174, + 523, 522, 174, 174, 174, 521, 520, 519, 174, 518, + 174, 175, 175, 517, 175, 516, 175, 176, 176, 176, + 176, 176, 176, 176, 176, 176, 176, 177, 177, 494, + 177, 515, 177, 211, 211, 514, 211, 211, 211, 211, + 211, 211, 211, 211, 211, 211, 212, 212, 513, 212, + + 512, 212, 493, 493, 511, 493, 493, 493, 493, 493, + 493, 493, 493, 493, 493, 510, 509, 508, 507, 506, + 505, 504, 503, 502, 501, 500, 499, 498, 497, 496, + 495, 494, 492, 491, 490, 489, 488, 487, 486, 485, + 484, 483, 482, 481, 480, 479, 478, 477, 476, 475, + 474, 473, 472, 471, 470, 469, 468, 467, 466, 465, + 464, 463, 462, 461, 460, 459, 458, 457, 456, 455, + 454, 453, 452, 451, 450, 449, 448, 447, 446, 445, + 444, 443, 442, 441, 440, 439, 434, 433, 432, 431, + 430, 429, 428, 427, 426, 425, 422, 421, 420, 419, + + 418, 417, 416, 415, 414, 413, 412, 411, 410, 409, + 408, 407, 404, 403, 402, 401, 400, 398, 395, 394, + 393, 392, 391, 390, 389, 388, 387, 386, 385, 384, + 383, 382, 381, 380, 379, 378, 377, 376, 375, 372, + 371, 368, 367, 366, 365, 362, 361, 360, 359, 358, + 357, 356, 355, 352, 351, 350, 349, 348, 347, 346, + 345, 344, 343, 342, 341, 338, 337, 336, 335, 334, + 333, 332, 331, 330, 329, 328, 327, 326, 325, 324, + 323, 322, 319, 318, 317, 316, 315, 314, 313, 312, + 311, 310, 309, 308, 307, 306, 303, 302, 295, 294, + + 293, 292, 291, 290, 289, 288, 287, 286, 285, 284, + 283, 282, 281, 278, 277, 276, 272, 271, 270, 269, + 268, 267, 266, 265, 264, 263, 262, 261, 258, 257, + 256, 252, 251, 250, 247, 246, 245, 242, 241, 240, + 239, 235, 234, 230, 228, 156, 155, 215, 214, 210, + 209, 208, 197, 193, 189, 188, 187, 181, 180, 139, + 139, 157, 155, 156, 155, 139, 140, 139, 581, 100, + 55, 55, 53, 33, 581, 581, 581, 581, 581, 581, + 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, + 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, + + 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, + 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, + 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, + 581, 581, 581 + } ; + +static yyconst flex_int16_t yy_chk[1134] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, + 6, 7, 8, 5, 6, 11, 71, 23, 7, 8, + 21, 22, 24, 11, 12, 11, 71, 607, 21, 22, + 9, 9, 12, 9, 12, 80, 5, 6, 7, 8, + 9, 606, 80, 9, 23, 10, 10, 9, 10, 24, + + 25, 10, 17, 27, 25, 10, 17, 9, 10, 17, + 27, 11, 10, 237, 17, 5, 6, 7, 8, 13, + 12, 237, 10, 13, 47, 13, 13, 25, 14, 43, + 27, 13, 14, 43, 14, 14, 47, 15, 66, 124, + 14, 15, 66, 15, 15, 605, 16, 18, 124, 15, + 16, 18, 16, 16, 18, 15, 19, 26, 16, 18, + 19, 26, 19, 19, 16, 20, 28, 85, 19, 20, + 604, 20, 20, 28, 19, 31, 31, 20, 31, 44, + 44, 44, 85, 20, 26, 31, 87, 87, 31, 87, + 15, 44, 15, 28, 32, 32, 223, 32, 81, 16, + + 32, 16, 97, 223, 32, 113, 97, 32, 603, 19, + 81, 19, 45, 45, 45, 113, 602, 44, 20, 81, + 20, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 42, + 255, 79, 42, 255, 42, 79, 42, 90, 90, 104, + 90, 42, 42, 104, 114, 110, 110, 42, 110, 114, + 79, 118, 42, 120, 114, 118, 122, 123, 42, 42, + 125, 123, 143, 143, 118, 90, 120, 155, 191, 125, + 601, 120, 122, 160, 160, 122, 160, 155, 125, 135, + 135, 135, 162, 162, 191, 162, 600, 42, 49, 165, + + 165, 49, 165, 49, 187, 49, 253, 167, 167, 110, + 167, 168, 168, 253, 168, 187, 49, 171, 171, 195, + 171, 49, 173, 173, 227, 173, 182, 49, 49, 199, + 182, 178, 178, 199, 178, 216, 216, 232, 195, 227, + 220, 220, 182, 220, 221, 599, 222, 222, 221, 222, + 225, 195, 224, 224, 295, 224, 49, 59, 226, 226, + 59, 226, 225, 221, 232, 258, 59, 59, 579, 228, + 228, 225, 228, 295, 59, 229, 229, 59, 229, 308, + 59, 578, 258, 59, 59, 178, 230, 230, 59, 230, + 231, 231, 329, 231, 332, 59, 359, 371, 308, 59, + + 254, 59, 59, 59, 59, 130, 577, 254, 130, 576, + 130, 329, 130, 332, 400, 359, 371, 130, 130, 362, + 362, 362, 575, 130, 388, 388, 388, 388, 130, 507, + 572, 571, 570, 400, 130, 130, 399, 508, 399, 423, + 423, 423, 423, 494, 388, 569, 568, 494, 507, 399, + 399, 399, 520, 520, 520, 520, 508, 567, 566, 423, + 540, 541, 563, 130, 136, 136, 136, 524, 524, 524, + 524, 562, 520, 136, 525, 525, 525, 525, 561, 540, + 541, 136, 136, 136, 136, 136, 136, 524, 538, 538, + 538, 538, 560, 559, 525, 543, 543, 543, 543, 557, + + 556, 555, 554, 553, 552, 551, 550, 547, 538, 546, + 545, 542, 537, 536, 528, 543, 582, 582, 582, 582, + 582, 582, 582, 582, 582, 582, 582, 582, 582, 583, + 583, 583, 583, 583, 583, 583, 583, 583, 583, 583, + 583, 583, 584, 584, 584, 584, 584, 584, 584, 584, + 584, 584, 584, 584, 584, 585, 585, 585, 585, 585, + 585, 585, 585, 585, 585, 585, 585, 585, 586, 586, + 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, + 586, 587, 527, 526, 587, 523, 587, 587, 522, 521, + 519, 518, 517, 587, 588, 516, 515, 588, 514, 588, + + 588, 513, 588, 512, 588, 510, 588, 589, 509, 589, + 506, 589, 590, 590, 590, 590, 590, 590, 590, 590, + 590, 590, 590, 590, 590, 591, 591, 591, 591, 591, + 591, 591, 591, 591, 505, 591, 591, 591, 592, 592, + 592, 592, 592, 592, 592, 592, 592, 592, 592, 593, + 504, 502, 593, 593, 593, 501, 500, 499, 593, 498, + 593, 594, 594, 496, 594, 495, 594, 595, 595, 595, + 595, 595, 595, 595, 595, 595, 595, 596, 596, 493, + 596, 492, 596, 597, 597, 491, 597, 597, 597, 597, + 597, 597, 597, 597, 597, 597, 598, 598, 490, 598, + + 489, 598, 608, 608, 488, 608, 608, 608, 608, 608, + 608, 608, 608, 608, 608, 487, 486, 485, 484, 483, + 482, 479, 478, 477, 476, 475, 472, 471, 470, 469, + 468, 467, 466, 465, 463, 462, 461, 460, 459, 456, + 454, 453, 452, 451, 450, 448, 447, 446, 445, 444, + 443, 442, 441, 440, 439, 438, 437, 436, 433, 432, + 431, 429, 428, 426, 425, 422, 421, 420, 419, 418, + 417, 416, 415, 414, 413, 412, 411, 410, 409, 408, + 407, 406, 405, 404, 403, 402, 398, 397, 396, 395, + 394, 393, 392, 391, 390, 389, 387, 386, 385, 384, + + 383, 382, 381, 380, 379, 378, 377, 376, 375, 374, + 373, 372, 370, 369, 368, 367, 366, 361, 357, 355, + 354, 353, 352, 351, 350, 348, 346, 345, 344, 343, + 342, 341, 340, 339, 337, 336, 335, 334, 333, 331, + 330, 326, 325, 324, 322, 319, 317, 316, 314, 312, + 311, 310, 309, 307, 306, 305, 304, 303, 302, 301, + 300, 299, 298, 297, 296, 294, 293, 292, 290, 289, + 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, + 278, 276, 272, 271, 270, 269, 268, 267, 266, 265, + 264, 263, 262, 261, 260, 259, 257, 256, 252, 251, + + 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, + 240, 239, 238, 236, 235, 234, 215, 210, 209, 208, + 207, 206, 205, 204, 203, 202, 201, 200, 198, 197, + 196, 194, 193, 192, 190, 189, 188, 186, 185, 184, + 183, 181, 180, 172, 169, 156, 154, 139, 137, 128, + 127, 126, 121, 119, 117, 116, 115, 112, 111, 105, + 100, 77, 74, 72, 70, 69, 55, 53, 33, 30, + 4, 3, 2, 581, 581, 581, 581, 581, 581, 581, + 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, + 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, + + 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, + 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, + 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, + 581, 581, 581 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int gram__flex_debug; +int gram__flex_debug = 1; + +static yyconst flex_int16_t yy_rule_linenum[130] = + { 0, + 179, 182, 183, 184, 192, 210, 211, 212, 213, 214, + 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, + 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 269, 273, 274, 275, 277, 284, 288, 295, 300, + 303, 306, 309, 317, 324, 325, 326, 332, 339, 346, + 366, 376, 391, 396, 415, 428, 444, 459, 476, 477, + 488, 499, 500, 512, 520, 530, 549, 561, 575, 576, + + 587, 596, 606, 607, 608, 609, 610, 611, 612, 615, + 617, 625, 643, 648, 649, 655, 656, 667, 673, 679, + 685, 701, 702, 706, 713, 730, 751, 784, 785 + } ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *gram_text; +#line 1 "../../src/scan-gram.l" +/* Bison Grammar Scanner -*- C -*- + + Copyright (C) 2002-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#define YY_NO_INPUT 1 +#line 24 "../../src/scan-gram.l" +/* Work around a bug in flex 2.5.31. See Debian bug 333231 + <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>. */ +#undef gram_wrap +#define gram_wrap() 1 + +#define FLEX_PREFIX(Id) gram_ ## Id +#include <src/flex-scanner.h> + +#include <src/complain.h> +#include <src/files.h> +#include <src/getargs.h> +#include <src/gram.h> +#include <quotearg.h> +#include <src/reader.h> +#include <src/uniqstr.h> + +#include <c-ctype.h> +#include <mbswidth.h> +#include <quote.h> + +#include <src/scan-gram.h> + +#define YY_DECL GRAM_LEX_DECL + +#define YY_USER_INIT \ + code_start = scanner_cursor = loc->start; \ + +/* Location of scanner cursor. */ +static boundary scanner_cursor; + +#define YY_USER_ACTION location_compute (loc, &scanner_cursor, gram_text, gram_leng); + +static size_t no_cr_read (FILE *, char *, size_t); +#define YY_INPUT(buf, result, size) ((result) = no_cr_read (gram_in, buf, size)) + +#define RETURN_PERCENT_PARAM(Value) \ + RETURN_VALUE(PERCENT_PARAM, param, param_ ## Value) + +#define RETURN_PERCENT_FLAG(Value) \ + RETURN_VALUE(PERCENT_FLAG, uniqstr, uniqstr_new (Value)) + +#define RETURN_VALUE(Token, Field, Value) \ + do { \ + val->Field = Value; \ + return Token; \ + } while (0) + +#define ROLLBACK_CURRENT_TOKEN \ + do { \ + scanner_cursor.column -= mbsnwidth (gram_text, gram_leng, 0); \ + yyless (0); \ + } while (0) + +#define DEPRECATED(Msg) \ + do { \ + size_t i; \ + deprecated_directive (loc, gram_text, Msg); \ + scanner_cursor.column -= mbsnwidth (Msg, strlen (Msg), 0); \ + for (i = strlen (Msg); i != 0; --i) \ + unput (Msg[i - 1]); \ + } while (0) + +/* A string representing the most recently saved token. */ +static char *last_string; + +/* Bracketed identifier. */ +static uniqstr bracketed_id_str = 0; +static location bracketed_id_loc; +static boundary bracketed_id_start; +static int bracketed_id_context_state = 0; + +void +gram_scanner_last_string_free (void) +{ + STRING_FREE; +} + +static void handle_syncline (char *, location); +static unsigned long int scan_integer (char const *p, int base, location loc); +static int convert_ucn_to_byte (char const *hex_text); +static void unexpected_eof (boundary, char const *); +static void unexpected_newline (boundary, char const *); + +/* A C-like comment in directives/rules. */ + +/* Strings and characters in directives/rules. */ + +/* A identifier was just read in directives/rules. Special state +to capture the sequence 'identifier :'. */ + +/* POSIX says that a tag must be both an id and a C union member, but +historically almost any character is allowed in a tag. We +disallow NUL, as this simplifies our implementation. We match +angle brackets in nested pairs: several languages use them for +generics/template types. */ + +/* Four types of user code: +- prologue (code between '%{' '%}' in the first section, before %%); +- actions, printers, union, etc, (between braced in the middle section); +- epilogue (everything after the second %%). +- predicate (code between '%?{' and '{' in middle section); */ + +/* C and C++ comments in code. */ + +/* Strings and characters in code. */ + +/* Bracketed identifiers support. */ + +/* Zero or more instances of backslash-newline. Following GCC, allow + white space between the backslash and the newline. */ +/* An equal sign, with optional leading whitespaces. This is used in some + deprecated constructs. */ +#line 1153 "src/scan-gram.c" + +#define INITIAL 0 +#define SC_YACC_COMMENT 1 +#define SC_ESCAPED_STRING 2 +#define SC_ESCAPED_CHARACTER 3 +#define SC_AFTER_IDENTIFIER 4 +#define SC_TAG 5 +#define SC_PROLOGUE 6 +#define SC_BRACED_CODE 7 +#define SC_EPILOGUE 8 +#define SC_PREDICATE 9 +#define SC_COMMENT 10 +#define SC_LINE_COMMENT 11 +#define SC_STRING 12 +#define SC_CHARACTER 13 +#define SC_BRACKETED_ID 14 +#define SC_RETURN_BRACKETED_ID 15 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +/* %if-c-only */ +#include <unistd.h> +/* %endif */ +/* %if-c++-only */ +/* %endif */ +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* %if-c-only Reentrant structure and macros (non-C++). */ +/* %if-reentrant */ +/* %if-c-only */ + +static int yy_init_globals (void ); + +/* %endif */ +/* %if-reentrant */ +/* %endif */ +/* %endif End reentrant structures and macros. */ + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int gram_lex_destroy (void ); + +int gram_get_debug (void ); + +void gram_set_debug (int debug_flag ); + +YY_EXTRA_TYPE gram_get_extra (void ); + +void gram_set_extra (YY_EXTRA_TYPE user_defined ); + +FILE *gram_get_in (void ); + +void gram_set_in (FILE * in_str ); + +FILE *gram_get_out (void ); + +void gram_set_out (FILE * out_str ); + +yy_size_t gram_get_leng (void ); + +char *gram_get_text (void ); + +int gram_get_lineno (void ); + +void gram_set_lineno (int line_number ); + +/* %if-bison-bridge */ +/* %endif */ + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int gram_wrap (void ); +#else +extern int gram_wrap (void ); +#endif +#endif + +/* %not-for-header */ + + static void yyunput (int c,char *buf_ptr ); + +/* %ok-for-header */ + +/* %endif */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT +/* %if-c-only Standard (non-C++) definition */ +/* %not-for-header */ + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif +/* %ok-for-header */ + +/* %endif */ +#endif + +/* %if-c-only */ + +/* %endif */ + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* %if-c-only Standard (non-C++) definition */ +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( gram_text, gram_leng, 1, gram_out )) {} } while (0) +/* %endif */ +/* %if-c++-only C++ definition */ +/* %endif */ +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ +/* %% [5.0] fread()/read() definition of YY_INPUT goes here unless we're doing C++ \ */\ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( gram_in )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( gram_in ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, gram_in))==0 && ferror(gram_in)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(gram_in); \ + } \ + }\ +\ +/* %if-c++-only C++ definition \ */\ +/* %endif */ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +/* %if-c-only */ +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +#endif + +/* %if-tables-serialization structures and prototypes */ +/* %not-for-header */ + +/* %ok-for-header */ + +/* %not-for-header */ + +/* %tables-yydmap generated elements */ +/* %endif */ +/* end tables serialization structures and prototypes */ + +/* %ok-for-header */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 +/* %if-c-only Standard (non-C++) definition */ + +extern int gram_lex (void); + +#define YY_DECL int gram_lex (void) +/* %endif */ +/* %if-c++-only C++ definition */ +/* %endif */ +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after gram_text and gram_leng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +/* %% [6.0] YY_RULE_SETUP definition goes here */ +#define YY_RULE_SETUP \ + if ( gram_leng > 0 ) \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \ + (gram_text[gram_leng - 1] == '\n'); \ + YY_USER_ACTION + +/* %not-for-header */ + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +/* %% [7.0] user's declarations go here */ +#line 149 "../../src/scan-gram.l" + + + /* Nesting level. Either for nested braces, or nested angle brackets + (but not mixed). */ + int nesting PACIFY_CC (= 0); + + /* Parent context state, when applicable. */ + int context_state PACIFY_CC (= 0); + + /* Location of most recent identifier, when applicable. */ + location id_loc PACIFY_CC (= empty_location); + + /* Where containing code started, when applicable. Its initial + value is relevant only when gram_lex is invoked in the SC_EPILOGUE + start condition. */ + boundary code_start = scanner_cursor; + + /* Where containing comment or string or character literal started, + when applicable. */ + boundary token_start PACIFY_CC (= scanner_cursor); + + + + /*-----------------------. + | Scanning white space. | + `-----------------------*/ + +#line 1441 "src/scan-gram.c" + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! gram_in ) +/* %if-c-only */ + gram_in = stdin; +/* %endif */ +/* %if-c++-only */ +/* %endif */ + + if ( ! gram_out ) +/* %if-c-only */ + gram_out = stdout; +/* %endif */ +/* %if-c++-only */ +/* %endif */ + + if ( ! YY_CURRENT_BUFFER ) { + gram_ensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + gram__create_buffer(gram_in,YY_BUF_SIZE ); + } + + gram__load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { +/* %% [8.0] yymore()-related code goes here */ + yy_cp = (yy_c_buf_p); + + /* Support of gram_text. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + +/* %% [9.0] code to set up and find next match goes here */ + yy_current_state = (yy_start); + yy_current_state += YY_AT_BOL(); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 582 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_current_state != 581 ); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + +yy_find_action: +/* %% [10.0] code to find the action number goes here */ + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +/* %% [11.0] code for gram_lineno update goes here */ + +do_action: /* This label is used only to access EOF actions. */ + +/* %% [12.0] debug code goes here */ + if ( gram__flex_debug ) + { + if ( yy_act == 0 ) + fprintf( stderr, "--scanner backing up\n" ); + else if ( yy_act < 130 ) + fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n", + (long)yy_rule_linenum[yy_act], gram_text ); + else if ( yy_act == 130 ) + fprintf( stderr, "--accepting default rule (\"%s\")\n", + gram_text ); + else if ( yy_act == 131 ) + fprintf( stderr, "--(end of buffer or a NUL)\n" ); + else + fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); + } + + switch ( yy_act ) + { /* beginning of action switch */ +/* %% [13.0] actions go here */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +/* Comments and white space. */ +case 1: +YY_RULE_SETUP +#line 179 "../../src/scan-gram.l" +{ + complain (loc, Wother, _("stray ',' treated as white space")); + } + YY_BREAK +case 2: +/* rule 2 can match eol */ +#line 183 "../../src/scan-gram.l" +case 3: +/* rule 3 can match eol */ +YY_RULE_SETUP +#line 183 "../../src/scan-gram.l" +continue; + YY_BREAK +case 4: +YY_RULE_SETUP +#line 184 "../../src/scan-gram.l" +{ + token_start = loc->start; + context_state = YY_START; + BEGIN SC_YACC_COMMENT; + } + YY_BREAK +/* #line directives are not documented, and may be withdrawn or + modified in future versions of Bison. */ +case 5: +/* rule 5 can match eol */ +YY_RULE_SETUP +#line 192 "../../src/scan-gram.l" +{ + handle_syncline (gram_text + sizeof "#line " - 1, *loc); + } + YY_BREAK + +/*----------------------------. + | Scanning Bison directives. | + `----------------------------*/ +/* For directives that are also command line options, the regex must be + "%..." + after "[-_]"s are removed, and the directive must match the --long + option name, with a single string argument. Otherwise, add exceptions + to ../build-aux/cross-options.pl. */ + + +case 6: +YY_RULE_SETUP +#line 210 "../../src/scan-gram.l" +return PERCENT_NONASSOC; + YY_BREAK +case 7: +YY_RULE_SETUP +#line 211 "../../src/scan-gram.l" +return PERCENT_CODE; + YY_BREAK +case 8: +YY_RULE_SETUP +#line 212 "../../src/scan-gram.l" +RETURN_PERCENT_FLAG("parse.trace"); + YY_BREAK +case 9: +YY_RULE_SETUP +#line 213 "../../src/scan-gram.l" +return PERCENT_DEFAULT_PREC; + YY_BREAK +case 10: +YY_RULE_SETUP +#line 214 "../../src/scan-gram.l" +return PERCENT_DEFINE; + YY_BREAK +case 11: +YY_RULE_SETUP +#line 215 "../../src/scan-gram.l" +return PERCENT_DEFINES; + YY_BREAK +case 12: +YY_RULE_SETUP +#line 216 "../../src/scan-gram.l" +return PERCENT_DESTRUCTOR; + YY_BREAK +case 13: +YY_RULE_SETUP +#line 217 "../../src/scan-gram.l" +return PERCENT_DPREC; + YY_BREAK +case 14: +YY_RULE_SETUP +#line 218 "../../src/scan-gram.l" +return PERCENT_EMPTY; + YY_BREAK +case 15: +YY_RULE_SETUP +#line 219 "../../src/scan-gram.l" +return PERCENT_ERROR_VERBOSE; + YY_BREAK +case 16: +YY_RULE_SETUP +#line 220 "../../src/scan-gram.l" +return PERCENT_EXPECT; + YY_BREAK +case 17: +YY_RULE_SETUP +#line 221 "../../src/scan-gram.l" +return PERCENT_EXPECT_RR; + YY_BREAK +case 18: +YY_RULE_SETUP +#line 222 "../../src/scan-gram.l" +return PERCENT_FILE_PREFIX; + YY_BREAK +case 19: +YY_RULE_SETUP +#line 223 "../../src/scan-gram.l" +return PERCENT_YACC; + YY_BREAK +case 20: +YY_RULE_SETUP +#line 224 "../../src/scan-gram.l" +return PERCENT_INITIAL_ACTION; + YY_BREAK +case 21: +YY_RULE_SETUP +#line 225 "../../src/scan-gram.l" +return PERCENT_GLR_PARSER; + YY_BREAK +case 22: +YY_RULE_SETUP +#line 226 "../../src/scan-gram.l" +return PERCENT_LANGUAGE; + YY_BREAK +case 23: +YY_RULE_SETUP +#line 227 "../../src/scan-gram.l" +return PERCENT_LEFT; + YY_BREAK +case 24: +YY_RULE_SETUP +#line 228 "../../src/scan-gram.l" +RETURN_PERCENT_PARAM(lex); + YY_BREAK +case 25: +YY_RULE_SETUP +#line 229 "../../src/scan-gram.l" +RETURN_PERCENT_FLAG("locations"); + YY_BREAK +case 26: +YY_RULE_SETUP +#line 230 "../../src/scan-gram.l" +return PERCENT_MERGE; + YY_BREAK +case 27: +YY_RULE_SETUP +#line 231 "../../src/scan-gram.l" +return PERCENT_NAME_PREFIX; + YY_BREAK +case 28: +YY_RULE_SETUP +#line 232 "../../src/scan-gram.l" +return PERCENT_NO_DEFAULT_PREC; + YY_BREAK +case 29: +YY_RULE_SETUP +#line 233 "../../src/scan-gram.l" +return PERCENT_NO_LINES; + YY_BREAK +case 30: +YY_RULE_SETUP +#line 234 "../../src/scan-gram.l" +return PERCENT_NONASSOC; + YY_BREAK +case 31: +YY_RULE_SETUP +#line 235 "../../src/scan-gram.l" +return PERCENT_NONDETERMINISTIC_PARSER; + YY_BREAK +case 32: +YY_RULE_SETUP +#line 236 "../../src/scan-gram.l" +return PERCENT_NTERM; + YY_BREAK +case 33: +YY_RULE_SETUP +#line 237 "../../src/scan-gram.l" +return PERCENT_OUTPUT; + YY_BREAK +case 34: +YY_RULE_SETUP +#line 238 "../../src/scan-gram.l" +RETURN_PERCENT_PARAM(both); + YY_BREAK +case 35: +YY_RULE_SETUP +#line 239 "../../src/scan-gram.l" +RETURN_PERCENT_PARAM(parse); + YY_BREAK +case 36: +YY_RULE_SETUP +#line 240 "../../src/scan-gram.l" +return PERCENT_PREC; + YY_BREAK +case 37: +YY_RULE_SETUP +#line 241 "../../src/scan-gram.l" +return PERCENT_PRECEDENCE; + YY_BREAK +case 38: +YY_RULE_SETUP +#line 242 "../../src/scan-gram.l" +return PERCENT_PRINTER; + YY_BREAK +case 39: +YY_RULE_SETUP +#line 243 "../../src/scan-gram.l" +RETURN_PERCENT_FLAG("api.pure"); + YY_BREAK +case 40: +YY_RULE_SETUP +#line 244 "../../src/scan-gram.l" +return PERCENT_REQUIRE; + YY_BREAK +case 41: +YY_RULE_SETUP +#line 245 "../../src/scan-gram.l" +return PERCENT_RIGHT; + YY_BREAK +case 42: +YY_RULE_SETUP +#line 246 "../../src/scan-gram.l" +return PERCENT_SKELETON; + YY_BREAK +case 43: +YY_RULE_SETUP +#line 247 "../../src/scan-gram.l" +return PERCENT_START; + YY_BREAK +case 44: +YY_RULE_SETUP +#line 248 "../../src/scan-gram.l" +return PERCENT_TOKEN; + YY_BREAK +case 45: +YY_RULE_SETUP +#line 249 "../../src/scan-gram.l" +return PERCENT_TOKEN; + YY_BREAK +case 46: +YY_RULE_SETUP +#line 250 "../../src/scan-gram.l" +return PERCENT_TOKEN_TABLE; + YY_BREAK +case 47: +YY_RULE_SETUP +#line 251 "../../src/scan-gram.l" +return PERCENT_TYPE; + YY_BREAK +case 48: +YY_RULE_SETUP +#line 252 "../../src/scan-gram.l" +return PERCENT_UNION; + YY_BREAK +case 49: +YY_RULE_SETUP +#line 253 "../../src/scan-gram.l" +return PERCENT_VERBOSE; + YY_BREAK +case 50: +YY_RULE_SETUP +#line 254 "../../src/scan-gram.l" +return PERCENT_YACC; + YY_BREAK +/* deprecated */ +case 51: +YY_RULE_SETUP +#line 257 "../../src/scan-gram.l" +DEPRECATED("%default-prec"); + YY_BREAK +case 52: +YY_RULE_SETUP +#line 258 "../../src/scan-gram.l" +DEPRECATED("%define parse.error verbose"); + YY_BREAK +case 53: +YY_RULE_SETUP +#line 259 "../../src/scan-gram.l" +DEPRECATED("%expect-rr"); + YY_BREAK +case 54: +/* rule 54 can match eol */ +YY_RULE_SETUP +#line 260 "../../src/scan-gram.l" +DEPRECATED("%file-prefix"); + YY_BREAK +case 55: +YY_RULE_SETUP +#line 261 "../../src/scan-gram.l" +DEPRECATED("%fixed-output-files"); + YY_BREAK +case 56: +/* rule 56 can match eol */ +YY_RULE_SETUP +#line 262 "../../src/scan-gram.l" +DEPRECATED("%name-prefix"); + YY_BREAK +case 57: +YY_RULE_SETUP +#line 263 "../../src/scan-gram.l" +DEPRECATED("%no-default-prec"); + YY_BREAK +case 58: +YY_RULE_SETUP +#line 264 "../../src/scan-gram.l" +DEPRECATED("%no-lines"); + YY_BREAK +case 59: +/* rule 59 can match eol */ +YY_RULE_SETUP +#line 265 "../../src/scan-gram.l" +DEPRECATED("%output"); + YY_BREAK +case 60: +YY_RULE_SETUP +#line 266 "../../src/scan-gram.l" +DEPRECATED("%pure-parser"); + YY_BREAK +case 61: +YY_RULE_SETUP +#line 267 "../../src/scan-gram.l" +DEPRECATED("%token-table"); + YY_BREAK +case 62: +/* rule 62 can match eol */ +YY_RULE_SETUP +#line 269 "../../src/scan-gram.l" +{ + complain (loc, complaint, _("invalid directive: %s"), quote (gram_text)); + } + YY_BREAK +case 63: +YY_RULE_SETUP +#line 273 "../../src/scan-gram.l" +return EQUAL; + YY_BREAK +case 64: +YY_RULE_SETUP +#line 274 "../../src/scan-gram.l" +return PIPE; + YY_BREAK +case 65: +YY_RULE_SETUP +#line 275 "../../src/scan-gram.l" +return SEMICOLON; + YY_BREAK +case 66: +YY_RULE_SETUP +#line 277 "../../src/scan-gram.l" +{ + val->uniqstr = uniqstr_new (gram_text); + id_loc = *loc; + bracketed_id_str = NULL; + BEGIN SC_AFTER_IDENTIFIER; + } + YY_BREAK +case 67: +YY_RULE_SETUP +#line 284 "../../src/scan-gram.l" +{ + val->integer = scan_integer (gram_text, 10, *loc); + return INT; + } + YY_BREAK +case 68: +YY_RULE_SETUP +#line 288 "../../src/scan-gram.l" +{ + val->integer = scan_integer (gram_text, 16, *loc); + return INT; + } + YY_BREAK +/* Identifiers may not start with a digit. Yet, don't silently + accept "1FOO" as "1 FOO". */ +case 69: +YY_RULE_SETUP +#line 295 "../../src/scan-gram.l" +{ + complain (loc, complaint, _("invalid identifier: %s"), quote (gram_text)); + } + YY_BREAK +/* Characters. */ +case 70: +YY_RULE_SETUP +#line 300 "../../src/scan-gram.l" +token_start = loc->start; BEGIN SC_ESCAPED_CHARACTER; + YY_BREAK +/* Strings. */ +case 71: +YY_RULE_SETUP +#line 303 "../../src/scan-gram.l" +token_start = loc->start; BEGIN SC_ESCAPED_STRING; + YY_BREAK +/* Prologue. */ +case 72: +YY_RULE_SETUP +#line 306 "../../src/scan-gram.l" +code_start = loc->start; BEGIN SC_PROLOGUE; + YY_BREAK +/* Code in between braces. */ +case 73: +YY_RULE_SETUP +#line 309 "../../src/scan-gram.l" +{ + STRING_GROW; + nesting = 0; + code_start = loc->start; + BEGIN SC_BRACED_CODE; + } + YY_BREAK +/* Semantic predicate. */ +case 74: +/* rule 74 can match eol */ +YY_RULE_SETUP +#line 317 "../../src/scan-gram.l" +{ + nesting = 0; + code_start = loc->start; + BEGIN SC_PREDICATE; + } + YY_BREAK +/* A type. */ +case 75: +YY_RULE_SETUP +#line 324 "../../src/scan-gram.l" +return TAG_ANY; + YY_BREAK +case 76: +YY_RULE_SETUP +#line 325 "../../src/scan-gram.l" +return TAG_NONE; + YY_BREAK +case 77: +YY_RULE_SETUP +#line 326 "../../src/scan-gram.l" +{ + nesting = 0; + token_start = loc->start; + BEGIN SC_TAG; + } + YY_BREAK +case 78: +YY_RULE_SETUP +#line 332 "../../src/scan-gram.l" +{ + static int percent_percent_count; + if (++percent_percent_count == 2) + BEGIN SC_EPILOGUE; + return PERCENT_PERCENT; + } + YY_BREAK +case 79: +YY_RULE_SETUP +#line 339 "../../src/scan-gram.l" +{ + bracketed_id_str = NULL; + bracketed_id_start = loc->start; + bracketed_id_context_state = YY_START; + BEGIN SC_BRACKETED_ID; + } + YY_BREAK +case 80: +YY_RULE_SETUP +#line 346 "../../src/scan-gram.l" +{ + complain (loc, complaint, "%s: %s", + ngettext ("invalid character", "invalid characters", gram_leng), + quote_mem (gram_text, gram_leng)); + } + YY_BREAK +case YY_STATE_EOF(INITIAL): +#line 352 "../../src/scan-gram.l" +{ + loc->start = loc->end = scanner_cursor; + yyterminate (); + } + YY_BREAK + +/*--------------------------------------------------------------. + | Supporting \0 complexifies our implementation for no expected | + | added value. | + `--------------------------------------------------------------*/ + + +case 81: +YY_RULE_SETUP +#line 366 "../../src/scan-gram.l" +complain (loc, complaint, _("invalid null character")); + YY_BREAK + +/*-----------------------------------------------------------------. + | Scanning after an identifier, checking whether a colon is next. | + `-----------------------------------------------------------------*/ + + +case 82: +YY_RULE_SETUP +#line 376 "../../src/scan-gram.l" +{ + if (bracketed_id_str) + { + ROLLBACK_CURRENT_TOKEN; + BEGIN SC_RETURN_BRACKETED_ID; + *loc = id_loc; + return ID; + } + else + { + bracketed_id_start = loc->start; + bracketed_id_context_state = YY_START; + BEGIN SC_BRACKETED_ID; + } + } + YY_BREAK +case 83: +YY_RULE_SETUP +#line 391 "../../src/scan-gram.l" +{ + BEGIN (bracketed_id_str ? SC_RETURN_BRACKETED_ID : INITIAL); + *loc = id_loc; + return ID_COLON; + } + YY_BREAK +case 84: +YY_RULE_SETUP +#line 396 "../../src/scan-gram.l" +{ + ROLLBACK_CURRENT_TOKEN; + BEGIN (bracketed_id_str ? SC_RETURN_BRACKETED_ID : INITIAL); + *loc = id_loc; + return ID; + } + YY_BREAK +case YY_STATE_EOF(SC_AFTER_IDENTIFIER): +#line 402 "../../src/scan-gram.l" +{ + BEGIN (bracketed_id_str ? SC_RETURN_BRACKETED_ID : INITIAL); + *loc = id_loc; + return ID; + } + YY_BREAK + +/*--------------------------------. + | Scanning bracketed identifiers. | + `--------------------------------*/ + + +case 85: +YY_RULE_SETUP +#line 415 "../../src/scan-gram.l" +{ + if (bracketed_id_str) + { + complain (loc, complaint, + _("unexpected identifier in bracketed name: %s"), + quote (gram_text)); + } + else + { + bracketed_id_str = uniqstr_new (gram_text); + bracketed_id_loc = *loc; + } + } + YY_BREAK +case 86: +YY_RULE_SETUP +#line 428 "../../src/scan-gram.l" +{ + BEGIN bracketed_id_context_state; + if (bracketed_id_str) + { + if (INITIAL == bracketed_id_context_state) + { + val->uniqstr = bracketed_id_str; + bracketed_id_str = 0; + *loc = bracketed_id_loc; + return BRACKETED_ID; + } + } + else + complain (loc, complaint, _("an identifier expected")); + } + YY_BREAK +case 87: +YY_RULE_SETUP +#line 444 "../../src/scan-gram.l" +{ + complain (loc, complaint, "%s: %s", + ngettext ("invalid character in bracketed name", + "invalid characters in bracketed name", gram_leng), + quote_mem (gram_text, gram_leng)); + } + YY_BREAK +case YY_STATE_EOF(SC_BRACKETED_ID): +#line 451 "../../src/scan-gram.l" +{ + BEGIN bracketed_id_context_state; + unexpected_eof (bracketed_id_start, "]"); + } + YY_BREAK + + + +case 88: +YY_RULE_SETUP +#line 459 "../../src/scan-gram.l" +{ + ROLLBACK_CURRENT_TOKEN; + val->uniqstr = bracketed_id_str; + bracketed_id_str = 0; + *loc = bracketed_id_loc; + BEGIN INITIAL; + return BRACKETED_ID; + } + YY_BREAK + +/*---------------------------------------------------------------. + | Scanning a Yacc comment. The initial '/ *' is already eaten. | + `---------------------------------------------------------------*/ + + +case 89: +YY_RULE_SETUP +#line 476 "../../src/scan-gram.l" +BEGIN context_state; + YY_BREAK +case 90: +/* rule 90 can match eol */ +YY_RULE_SETUP +#line 477 "../../src/scan-gram.l" +continue; + YY_BREAK +case YY_STATE_EOF(SC_YACC_COMMENT): +#line 478 "../../src/scan-gram.l" +unexpected_eof (token_start, "*/"); BEGIN context_state; + YY_BREAK + +/*------------------------------------------------------------. + | Scanning a C comment. The initial '/ *' is already eaten. | + `------------------------------------------------------------*/ + + +case 91: +/* rule 91 can match eol */ +YY_RULE_SETUP +#line 488 "../../src/scan-gram.l" +STRING_GROW; BEGIN context_state; + YY_BREAK +case YY_STATE_EOF(SC_COMMENT): +#line 489 "../../src/scan-gram.l" +unexpected_eof (token_start, "*/"); BEGIN context_state; + YY_BREAK + +/*--------------------------------------------------------------. + | Scanning a line comment. The initial '//' is already eaten. | + `--------------------------------------------------------------*/ + + +case 92: +/* rule 92 can match eol */ +YY_RULE_SETUP +#line 499 "../../src/scan-gram.l" +STRING_GROW; BEGIN context_state; + YY_BREAK +case 93: +/* rule 93 can match eol */ +YY_RULE_SETUP +#line 500 "../../src/scan-gram.l" +STRING_GROW; + YY_BREAK +case YY_STATE_EOF(SC_LINE_COMMENT): +#line 501 "../../src/scan-gram.l" +BEGIN context_state; + YY_BREAK + +/*------------------------------------------------. + | Scanning a Bison string, including its escapes. | + | The initial quote is already eaten. | + `------------------------------------------------*/ + + +case 94: +YY_RULE_SETUP +#line 512 "../../src/scan-gram.l" +{ + STRING_FINISH; + loc->start = token_start; + val->code = last_string; + BEGIN INITIAL; + return STRING; + } + YY_BREAK +case YY_STATE_EOF(SC_ESCAPED_STRING): +#line 519 "../../src/scan-gram.l" +unexpected_eof (token_start, "\""); + YY_BREAK +case 95: +/* rule 95 can match eol */ +YY_RULE_SETUP +#line 520 "../../src/scan-gram.l" +unexpected_newline (token_start, "\""); + YY_BREAK + +/*----------------------------------------------------------. + | Scanning a Bison character literal, decoding its escapes. | + | The initial quote is already eaten. | + `----------------------------------------------------------*/ + + +case 96: +YY_RULE_SETUP +#line 530 "../../src/scan-gram.l" +{ + STRING_FINISH; + loc->start = token_start; + val->character = last_string[0]; + + /* FIXME: Eventually, make these errors. */ + if (last_string[0] == '\0') + { + complain (loc, Wother, _("empty character literal")); + /* '\0' seems dangerous even if we are about to complain. */ + val->character = '\''; + } + else if (last_string[1] != '\0') + complain (loc, Wother, + _("extra characters in character literal")); + STRING_FREE; + BEGIN INITIAL; + return CHAR; + } + YY_BREAK +case 97: +/* rule 97 can match eol */ +YY_RULE_SETUP +#line 549 "../../src/scan-gram.l" +unexpected_newline (token_start, "'"); + YY_BREAK +case YY_STATE_EOF(SC_ESCAPED_CHARACTER): +#line 550 "../../src/scan-gram.l" +unexpected_eof (token_start, "'"); + YY_BREAK + +/*--------------------------------------------------------------. + | Scanning a tag. The initial angle bracket is already eaten. | + `--------------------------------------------------------------*/ + + +case 98: +YY_RULE_SETUP +#line 561 "../../src/scan-gram.l" +{ + --nesting; + if (nesting < 0) + { + STRING_FINISH; + loc->start = token_start; + val->uniqstr = uniqstr_new (last_string); + STRING_FREE; + BEGIN INITIAL; + return TAG; + } + STRING_GROW; + } + YY_BREAK +case 99: +/* rule 99 can match eol */ +YY_RULE_SETUP +#line 575 "../../src/scan-gram.l" +STRING_GROW; + YY_BREAK +case 100: +YY_RULE_SETUP +#line 576 "../../src/scan-gram.l" +STRING_GROW; nesting += gram_leng; + YY_BREAK +case YY_STATE_EOF(SC_TAG): +#line 578 "../../src/scan-gram.l" +unexpected_eof (token_start, ">"); + YY_BREAK + +/*----------------------------. + | Decode escaped characters. | + `----------------------------*/ + + +case 101: +YY_RULE_SETUP +#line 587 "../../src/scan-gram.l" +{ + unsigned long int c = strtoul (gram_text + 1, NULL, 8); + if (!c || UCHAR_MAX < c) + complain (loc, complaint, _("invalid number after \\-escape: %s"), + gram_text+1); + else + obstack_1grow (&obstack_for_string, c); + } + YY_BREAK +case 102: +YY_RULE_SETUP +#line 596 "../../src/scan-gram.l" +{ + verify (UCHAR_MAX < ULONG_MAX); + unsigned long int c = strtoul (gram_text + 2, NULL, 16); + if (!c || UCHAR_MAX < c) + complain (loc, complaint, _("invalid number after \\-escape: %s"), + gram_text+1); + else + obstack_1grow (&obstack_for_string, c); + } + YY_BREAK +case 103: +YY_RULE_SETUP +#line 606 "../../src/scan-gram.l" +obstack_1grow (&obstack_for_string, '\a'); + YY_BREAK +case 104: +YY_RULE_SETUP +#line 607 "../../src/scan-gram.l" +obstack_1grow (&obstack_for_string, '\b'); + YY_BREAK +case 105: +YY_RULE_SETUP +#line 608 "../../src/scan-gram.l" +obstack_1grow (&obstack_for_string, '\f'); + YY_BREAK +case 106: +YY_RULE_SETUP +#line 609 "../../src/scan-gram.l" +obstack_1grow (&obstack_for_string, '\n'); + YY_BREAK +case 107: +YY_RULE_SETUP +#line 610 "../../src/scan-gram.l" +obstack_1grow (&obstack_for_string, '\r'); + YY_BREAK +case 108: +YY_RULE_SETUP +#line 611 "../../src/scan-gram.l" +obstack_1grow (&obstack_for_string, '\t'); + YY_BREAK +case 109: +YY_RULE_SETUP +#line 612 "../../src/scan-gram.l" +obstack_1grow (&obstack_for_string, '\v'); + YY_BREAK +/* \\[\"\'?\\] would be shorter, but it confuses xgettext. */ +case 110: +YY_RULE_SETUP +#line 615 "../../src/scan-gram.l" +obstack_1grow (&obstack_for_string, gram_text[1]); + YY_BREAK +case 111: +YY_RULE_SETUP +#line 617 "../../src/scan-gram.l" +{ + int c = convert_ucn_to_byte (gram_text); + if (c <= 0) + complain (loc, complaint, _("invalid number after \\-escape: %s"), + gram_text+1); + else + obstack_1grow (&obstack_for_string, c); + } + YY_BREAK +case 112: +/* rule 112 can match eol */ +YY_RULE_SETUP +#line 625 "../../src/scan-gram.l" +{ + char const *p = gram_text + 1; + /* Quote only if escaping won't make the character visible. */ + if (c_isspace ((unsigned char) *p) && c_isprint ((unsigned char) *p)) + p = quote (p); + else + p = quotearg_style_mem (escape_quoting_style, p, 1); + complain (loc, complaint, _("invalid character after \\-escape: %s"), + p); + } + YY_BREAK + +/*--------------------------------------------. + | Scanning user-code characters and strings. | + `--------------------------------------------*/ + + +case 113: +/* rule 113 can match eol */ +YY_RULE_SETUP +#line 643 "../../src/scan-gram.l" +STRING_GROW; + YY_BREAK + + + +case 114: +YY_RULE_SETUP +#line 648 "../../src/scan-gram.l" +STRING_GROW; BEGIN context_state; + YY_BREAK +case 115: +/* rule 115 can match eol */ +YY_RULE_SETUP +#line 649 "../../src/scan-gram.l" +unexpected_newline (token_start, "'"); + YY_BREAK +case YY_STATE_EOF(SC_CHARACTER): +#line 650 "../../src/scan-gram.l" +unexpected_eof (token_start, "'"); + YY_BREAK + + + +case 116: +YY_RULE_SETUP +#line 655 "../../src/scan-gram.l" +STRING_GROW; BEGIN context_state; + YY_BREAK +case 117: +/* rule 117 can match eol */ +YY_RULE_SETUP +#line 656 "../../src/scan-gram.l" +unexpected_newline (token_start, "\""); + YY_BREAK +case YY_STATE_EOF(SC_STRING): +#line 657 "../../src/scan-gram.l" +unexpected_eof (token_start, "\""); + YY_BREAK + +/*---------------------------------------------------. + | Strings, comments etc. can be found in user code. | + `---------------------------------------------------*/ + + +case 118: +YY_RULE_SETUP +#line 667 "../../src/scan-gram.l" +{ + STRING_GROW; + context_state = YY_START; + token_start = loc->start; + BEGIN SC_CHARACTER; + } + YY_BREAK +case 119: +YY_RULE_SETUP +#line 673 "../../src/scan-gram.l" +{ + STRING_GROW; + context_state = YY_START; + token_start = loc->start; + BEGIN SC_STRING; + } + YY_BREAK +case 120: +/* rule 120 can match eol */ +YY_RULE_SETUP +#line 679 "../../src/scan-gram.l" +{ + STRING_GROW; + context_state = YY_START; + token_start = loc->start; + BEGIN SC_COMMENT; + } + YY_BREAK +case 121: +/* rule 121 can match eol */ +YY_RULE_SETUP +#line 685 "../../src/scan-gram.l" +{ + STRING_GROW; + context_state = YY_START; + BEGIN SC_LINE_COMMENT; + } + YY_BREAK + +/*-----------------------------------------------------------. + | Scanning some code in braces (actions, predicates). The | + | initial "{" is already eaten. | + `-----------------------------------------------------------*/ + + +case 122: +/* rule 122 can match eol */ +YY_RULE_SETUP +#line 701 "../../src/scan-gram.l" +STRING_GROW; nesting++; + YY_BREAK +case 123: +/* rule 123 can match eol */ +YY_RULE_SETUP +#line 702 "../../src/scan-gram.l" +STRING_GROW; nesting--; + YY_BREAK +/* Tokenize '<<%' correctly (as '<<' '%') rather than incorrrectly + (as '<' '<%'). */ +case 124: +/* rule 124 can match eol */ +YY_RULE_SETUP +#line 706 "../../src/scan-gram.l" +STRING_GROW; + YY_BREAK +case YY_STATE_EOF(SC_BRACED_CODE): +case YY_STATE_EOF(SC_PREDICATE): +#line 708 "../../src/scan-gram.l" +unexpected_eof (code_start, "}"); + YY_BREAK + + + +case 125: +YY_RULE_SETUP +#line 713 "../../src/scan-gram.l" +{ + obstack_1grow (&obstack_for_string, '}'); + + --nesting; + if (nesting < 0) + { + STRING_FINISH; + loc->start = code_start; + val->code = last_string; + BEGIN INITIAL; + return BRACED_CODE; + } + } + YY_BREAK + + + +case 126: +YY_RULE_SETUP +#line 730 "../../src/scan-gram.l" +{ + --nesting; + if (nesting < 0) + { + STRING_FINISH; + loc->start = code_start; + val->code = last_string; + BEGIN INITIAL; + return BRACED_PREDICATE; + } + else + obstack_1grow (&obstack_for_string, '}'); + } + YY_BREAK + +/*--------------------------------------------------------------. + | Scanning some prologue: from "%{" (already scanned) to "%}". | + `--------------------------------------------------------------*/ + + +case 127: +YY_RULE_SETUP +#line 751 "../../src/scan-gram.l" +{ + STRING_FINISH; + loc->start = code_start; + val->code = last_string; + BEGIN INITIAL; + return PROLOGUE; + } + YY_BREAK +case YY_STATE_EOF(SC_PROLOGUE): +#line 759 "../../src/scan-gram.l" +unexpected_eof (code_start, "%}"); + YY_BREAK + +/*---------------------------------------------------------------. + | Scanning the epilogue (everything after the second "%%", which | + | has already been eaten). | + `---------------------------------------------------------------*/ + + +case YY_STATE_EOF(SC_EPILOGUE): +#line 770 "../../src/scan-gram.l" +{ + STRING_FINISH; + loc->start = code_start; + val->code = last_string; + BEGIN INITIAL; + return EPILOGUE; + } + YY_BREAK + +/*-----------------------------------------------------. + | By default, grow the string obstack with the input. | + `-----------------------------------------------------*/ +case 128: +#line 785 "../../src/scan-gram.l" +case 129: +/* rule 129 can match eol */ +YY_RULE_SETUP +#line 785 "../../src/scan-gram.l" +STRING_GROW; + YY_BREAK +case 130: +YY_RULE_SETUP +#line 787 "../../src/scan-gram.l" +YY_FATAL_ERROR( "flex scanner jammed" ); + YY_BREAK +#line 2661 "src/scan-gram.c" +case YY_STATE_EOF(SC_RETURN_BRACKETED_ID): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed gram_in at a new source and called + * gram_lex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = gram_in; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { +/* %% [14.0] code to do back-up for compressed tables and set up yy_cp goes here */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( gram_wrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * gram_text, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of gram_lex */ +/* %ok-for-header */ + +/* %if-c++-only */ +/* %not-for-header */ + +/* %ok-for-header */ + +/* %endif */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +/* %if-c-only */ +static int yy_get_next_buffer (void) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + yy_size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + yy_size_t new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + gram_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + gram_restart(gram_in ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) gram_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +/* %if-c-only */ +/* %not-for-header */ + + static yy_state_type yy_get_previous_state (void) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + register yy_state_type yy_current_state; + register char *yy_cp; + +/* %% [15.0] code to get the start state into yy_current_state goes here */ + yy_current_state = (yy_start); + yy_current_state += YY_AT_BOL(); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { +/* %% [16.0] code to find the next state goes here */ + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 59); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 582 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ +/* %if-c-only */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + register int yy_is_jam; + /* %% [17.0] code to find the next state, and perhaps do backing up, goes here */ + register char *yy_cp = (yy_c_buf_p); + + register YY_CHAR yy_c = 59; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 582 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 581); + + return yy_is_jam ? 0 : yy_current_state; +} + +/* %if-c-only */ + + static void yyunput (int c, register char * yy_bp ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + register char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up gram_text */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register yy_size_t number_to_move = (yy_n_chars) + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + +/* %% [18.0] update gram_lineno here */ + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} +/* %if-c-only */ + +/* %endif */ + +/* %if-c-only */ +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + gram_restart(gram_in ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( gram_wrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve gram_text */ + (yy_hold_char) = *++(yy_c_buf_p); + +/* %% [19.0] update BOL and gram_lineno */ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n'); + + return c; +} +/* %if-c-only */ +#endif /* ifndef YY_NO_INPUT */ +/* %endif */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ +/* %if-c-only */ + void gram_restart (FILE * input_file ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + + if ( ! YY_CURRENT_BUFFER ){ + gram_ensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + gram__create_buffer(gram_in,YY_BUF_SIZE ); + } + + gram__init_buffer(YY_CURRENT_BUFFER,input_file ); + gram__load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ +/* %if-c-only */ + void gram__switch_to_buffer (YY_BUFFER_STATE new_buffer ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + + /* TODO. We should be able to replace this entire function body + * with + * gram_pop_buffer_state(); + * gram_push_buffer_state(new_buffer); + */ + gram_ensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + gram__load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (gram_wrap()) processing, but the only time this flag + * is looked at is after gram_wrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +/* %if-c-only */ +static void gram__load_buffer_state (void) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + gram_in = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ +/* %if-c-only */ + YY_BUFFER_STATE gram__create_buffer (FILE * file, int size ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) gram_alloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in gram__create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) gram_alloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in gram__create_buffer()" ); + + b->yy_is_our_buffer = 1; + + gram__init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with gram__create_buffer() + * + */ +/* %if-c-only */ + void gram__delete_buffer (YY_BUFFER_STATE b ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + gram_free((void *) b->yy_ch_buf ); + + gram_free((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a gram_restart() or at EOF. + */ +/* %if-c-only */ + static void gram__init_buffer (YY_BUFFER_STATE b, FILE * file ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ + +{ + int oerrno = errno; + + gram__flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then gram__init_buffer was _probably_ + * called from gram_restart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + +/* %if-c-only */ + + b->yy_is_interactive = 0; + +/* %endif */ +/* %if-c++-only */ +/* %endif */ + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ +/* %if-c-only */ + void gram__flush_buffer (YY_BUFFER_STATE b ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + gram__load_buffer_state( ); +} + +/* %if-c-or-c++ */ +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +/* %if-c-only */ +void gram_push_buffer_state (YY_BUFFER_STATE new_buffer ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + if (new_buffer == NULL) + return; + + gram_ensure_buffer_stack(); + + /* This block is copied from gram__switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from gram__switch_to_buffer. */ + gram__load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} +/* %endif */ + +/* %if-c-or-c++ */ +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +/* %if-c-only */ +void gram_pop_buffer_state (void) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + if (!YY_CURRENT_BUFFER) + return; + + gram__delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + gram__load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} +/* %endif */ + +/* %if-c-or-c++ */ +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +/* %if-c-only */ +static void gram_ensure_buffer_stack (void) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + yy_size_t num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)gram_alloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in gram_ensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)gram_realloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in gram_ensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} +/* %endif */ + +/* %if-c-only */ +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE gram__scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) gram_alloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in gram__scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + gram__switch_to_buffer(b ); + + return b; +} +/* %endif */ + +/* %if-c-only */ +/** Setup the input buffer state to scan a string. The next call to gram_lex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * gram__scan_bytes() instead. + */ +YY_BUFFER_STATE gram__scan_string (yyconst char * yystr ) +{ + + return gram__scan_bytes(yystr,strlen(yystr) ); +} +/* %endif */ + +/* %if-c-only */ +/** Setup the input buffer state to scan the given bytes. The next call to gram_lex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE gram__scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) gram_alloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in gram__scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = gram__scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in gram__scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} +/* %endif */ + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +/* %if-c-only */ +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} +/* %endif */ +/* %if-c++-only */ +/* %endif */ + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up gram_text. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + gram_text[gram_leng] = (yy_hold_char); \ + (yy_c_buf_p) = gram_text + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + gram_leng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/* %if-c-only */ +/* %if-reentrant */ +/* %endif */ + +/** Get the current line number. + * + */ +int gram_get_lineno (void) +{ + + return gram_lineno; +} + +/** Get the input stream. + * + */ +FILE *gram_get_in (void) +{ + return gram_in; +} + +/** Get the output stream. + * + */ +FILE *gram_get_out (void) +{ + return gram_out; +} + +/** Get the length of the current token. + * + */ +yy_size_t gram_get_leng (void) +{ + return gram_leng; +} + +/** Get the current token. + * + */ + +char *gram_get_text (void) +{ + return gram_text; +} + +/* %if-reentrant */ +/* %endif */ + +/** Set the current line number. + * @param line_number + * + */ +void gram_set_lineno (int line_number ) +{ + + gram_lineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see gram__switch_to_buffer + */ +void gram_set_in (FILE * in_str ) +{ + gram_in = in_str ; +} + +void gram_set_out (FILE * out_str ) +{ + gram_out = out_str ; +} + +int gram_get_debug (void) +{ + return gram__flex_debug; +} + +void gram_set_debug (int bdebug ) +{ + gram__flex_debug = bdebug ; +} + +/* %endif */ + +/* %if-reentrant */ +/* %if-bison-bridge */ +/* %endif */ +/* %endif if-c-only */ + +/* %if-c-only */ +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from gram_lex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + gram_in = stdin; + gram_out = stdout; +#else + gram_in = (FILE *) 0; + gram_out = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * gram_lex_init() + */ + return 0; +} +/* %endif */ + +/* %if-c-only SNIP! this currently causes conflicts with the c++ scanner */ +/* gram_lex_destroy is for both reentrant and non-reentrant scanners. */ +int gram_lex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + gram__delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + gram_pop_buffer_state(); + } + + /* Destroy the stack itself. */ + gram_free((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * gram_lex() is called, initialization will occur. */ + yy_init_globals( ); + +/* %if-reentrant */ +/* %endif */ + return 0; +} +/* %endif */ + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *gram_alloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *gram_realloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void gram_free (void * ptr ) +{ + free( (char *) ptr ); /* see gram_realloc() for (char *) cast */ +} + +/* %if-tables-serialization definitions */ +/* %define-yytables The name for this specific scanner's tables. */ +#define YYTABLES_NAME "yytables" +/* %endif */ + +/* %ok-for-header */ + +#line 787 "../../src/scan-gram.l" + + + +/* Read bytes from FP into buffer BUF of size SIZE. Return the + number of bytes read. Remove '\r' from input, treating \r\n + and isolated \r as \n. */ + +static size_t +no_cr_read (FILE *fp, char *buf, size_t size) +{ + size_t bytes_read = fread (buf, 1, size, fp); + if (bytes_read) + { + char *w = memchr (buf, '\r', bytes_read); + if (w) + { + char const *r = ++w; + char const *lim = buf + bytes_read; + + for (;;) + { + /* Found an '\r'. Treat it like '\n', but ignore any + '\n' that immediately follows. */ + w[-1] = '\n'; + if (r == lim) + { + int ch = getc (fp); + if (ch != '\n' && ungetc (ch, fp) != ch) + break; + } + else if (*r == '\n') + r++; + + /* Copy until the next '\r'. */ + do + { + if (r == lim) + return w - buf; + } + while ((*w++ = *r++) != '\r'); + } + + return w - buf; + } + } + + return bytes_read; +} + + + +/*------------------------------------------------------. +| Scan NUMBER for a base-BASE integer at location LOC. | +`------------------------------------------------------*/ + +static unsigned long int +scan_integer (char const *number, int base, location loc) +{ + verify (INT_MAX < ULONG_MAX); + unsigned long int num = strtoul (number, NULL, base); + + if (INT_MAX < num) + { + complain (&loc, complaint, _("integer out of range: %s"), + quote (number)); + num = INT_MAX; + } + + return num; +} + + +/*------------------------------------------------------------------. +| Convert universal character name UCN to a single-byte character, | +| and return that character. Return -1 if UCN does not correspond | +| to a single-byte character. | +`------------------------------------------------------------------*/ + +static int +convert_ucn_to_byte (char const *ucn) +{ + verify (UCHAR_MAX <= INT_MAX); + unsigned long int code = strtoul (ucn + 2, NULL, 16); + + /* FIXME: Currently we assume Unicode-compatible unibyte characters + on ASCII hosts (i.e., Latin-1 on hosts with 8-bit bytes). On + non-ASCII hosts we support only the portable C character set. + These limitations should be removed once we add support for + multibyte characters. */ + + if (UCHAR_MAX < code) + return -1; + +#if ! ('$' == 0x24 && '@' == 0x40 && '`' == 0x60 && '~' == 0x7e) + { + /* A non-ASCII host. Use CODE to index into a table of the C + basic execution character set, which is guaranteed to exist on + all Standard C platforms. This table also includes '$', '@', + and '`', which are not in the basic execution character set but + which are unibyte characters on all the platforms that we know + about. */ + static signed char const table[] = + { + '\0', -1, -1, -1, -1, -1, -1, '\a', + '\b', '\t', '\n', '\v', '\f', '\r', -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + ' ', '!', '"', '#', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '{', '|', '}', '~' + }; + + code = code < sizeof table ? table[code] : -1; + } +#endif + + return code; +} + + +/*---------------------------------------------------------------------. +| Handle '#line INT( "FILE")?\n'. ARGS has already skipped '#line '. | +`---------------------------------------------------------------------*/ + +static void +handle_syncline (char *args, location loc) +{ + char *file; + unsigned long int lineno = strtoul (args, &file, 10); + if (INT_MAX <= lineno) + { + complain (&loc, Wother, _("line number overflow")); + lineno = INT_MAX; + } + + file = strchr (file, '"'); + if (file) + { + *strchr (file + 1, '"') = '\0'; + current_file = uniqstr_new (file + 1); + } + boundary_set (&scanner_cursor, current_file, lineno, 1); +} + + +/*----------------------------------------------------------------. +| For a token or comment starting at START, report message MSGID, | +| which should say that an end marker was found before the | +| expected TOKEN_END. Then, pretend that TOKEN_END was found. | +`----------------------------------------------------------------*/ + +static void +unexpected_end (boundary start, char const *msgid, char const *token_end) +{ + location loc; + size_t i; + loc.start = start; + loc.end = scanner_cursor; + i = strlen (token_end); + +/* Adjust scanner cursor so that any later message does not count + the characters about to be inserted. */ + scanner_cursor.column -= i; + + while (i != 0) + unput (token_end[--i]); + + token_end = quote (token_end); + /* Instead of '\'', display "'". */ + if (STREQ (token_end, "'\\''")) + token_end = "\"'\""; + complain (&loc, complaint, _(msgid), token_end); +} + + +/*------------------------------------------------------------------------. +| Report an unexpected EOF in a token or comment starting at START. | +| An end of file was encountered and the expected TOKEN_END was missing. | +| After reporting the problem, pretend that TOKEN_END was found. | +`------------------------------------------------------------------------*/ + +static void +unexpected_eof (boundary start, char const *token_end) +{ + unexpected_end (start, N_("missing %s at end of file"), token_end); +} + + +/*----------------------------------------. +| Likewise, but for unexpected newlines. | +`----------------------------------------*/ + +static void +unexpected_newline (boundary start, char const *token_end) +{ + unexpected_end (start, N_("missing %s at end of line"), token_end); +} + + +/*-------------------------. +| Initialize the scanner. | +`-------------------------*/ + +void +gram_scanner_initialize (void) +{ + obstack_init (&obstack_for_string); +} + + +/*-----------------------------------------------. +| Free all the memory allocated to the scanner. | +`-----------------------------------------------*/ + +void +gram_scanner_free (void) +{ + obstack_free (&obstack_for_string, 0); + /* Reclaim Flex's buffers. */ + gram_lex_destroy (); +} + diff --git a/contrib/tools/bison/src/scan-gram.h b/contrib/tools/bison/src/scan-gram.h new file mode 100644 index 0000000000..ee397ed2e7 --- /dev/null +++ b/contrib/tools/bison/src/scan-gram.h @@ -0,0 +1,38 @@ +/* Bison Grammar Scanner + + Copyright (C) 2006-2007, 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef SCAN_GRAM_H_ +# define SCAN_GRAM_H_ + +/* From the scanner. */ +extern FILE *gram_in; +extern int gram__flex_debug; +void gram_scanner_initialize (void); +void gram_scanner_free (void); +void gram_scanner_last_string_free (void); + +/* These are declared by the scanner, but not used. We put them here + to pacify "make syntax-check". */ +extern FILE *gram_out; +extern int gram_lineno; + +# define GRAM_LEX_DECL int gram_lex (GRAM_STYPE *val, location *loc) +GRAM_LEX_DECL; + +#endif /* !SCAN_GRAM_H_ */ diff --git a/contrib/tools/bison/src/scan-skel-c.c b/contrib/tools/bison/src/scan-skel-c.c new file mode 100644 index 0000000000..3e1e73deb0 --- /dev/null +++ b/contrib/tools/bison/src/scan-skel-c.c @@ -0,0 +1,3 @@ +#include <config.h> +#include "system.h" +#include "src/scan-skel.c" diff --git a/contrib/tools/bison/src/scan-skel.c b/contrib/tools/bison/src/scan-skel.c new file mode 100644 index 0000000000..1e116da14d --- /dev/null +++ b/contrib/tools/bison/src/scan-skel.c @@ -0,0 +1,2435 @@ +#line 2 "lex.yy.c" + +#line 4 "lex.yy.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +/* %not-for-header */ + +/* %if-c-only */ +/* %if-not-reentrant */ +#define yy_create_buffer skel__create_buffer +#define yy_delete_buffer skel__delete_buffer +#define yy_flex_debug skel__flex_debug +#define yy_init_buffer skel__init_buffer +#define yy_flush_buffer skel__flush_buffer +#define yy_load_buffer_state skel__load_buffer_state +#define yy_switch_to_buffer skel__switch_to_buffer +#define yyin skel_in +#define yyleng skel_leng +#define yylex skel_lex +#define yylineno skel_lineno +#define yyout skel_out +#define yyrestart skel_restart +#define yytext skel_text +#define yywrap skel_wrap +#define yyalloc skel_alloc +#define yyrealloc skel_realloc +#define yyfree skel_free + +/* %endif */ +/* %endif */ +/* %ok-for-header */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* %if-c++-only */ +#define BISON_FALLTHROUGH [[fallthrough]] +/* %endif */ + +/* %if-c-only */ +#define BISON_FALLTHROUGH +/* %endif */ + +/* %if-c-only */ + +/* %endif */ + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +/* %if-c-only */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> +/* %endif */ + +/* %if-tables-serialization */ +/* %endif */ +/* end standard C headers. */ + +/* %if-c-or-c++ */ +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* %endif */ + +/* %if-c++-only */ +/* %endif */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* %not-for-header */ + +/* Returned upon end-of-file. */ +#define YY_NULL 0 +/* %ok-for-header */ + +/* %not-for-header */ + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) +/* %ok-for-header */ + +/* %if-reentrant */ +/* %endif */ + +/* %if-not-reentrant */ + +/* %endif */ + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE skel_restart(skel_in ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +/* %if-not-reentrant */ +extern int skel_leng; +/* %endif */ + +/* %if-c-only */ +/* %if-not-reentrant */ +extern FILE *skel_in, *skel_out; +/* %endif */ +/* %endif */ + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up skel_text. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up skel_text again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { +/* %if-c-only */ + FILE *yy_input_file; +/* %endif */ + +/* %if-c++-only */ +/* %endif */ + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via skel_restart()), so that the user can continue scanning by + * just pointing skel_in at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* %if-c-only Standard (non-C++) definition */ +/* %not-for-header */ + +/* %if-not-reentrant */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ +/* %endif */ +/* %ok-for-header */ + +/* %endif */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* %if-c-only Standard (non-C++) definition */ + +/* %if-not-reentrant */ +/* %not-for-header */ + +/* yy_hold_char holds the character lost when skel_text is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int skel_leng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow skel_wrap()'s to do buffer switches + * instead of setting up a fresh skel_in. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; +/* %ok-for-header */ + +/* %endif */ + +void skel_restart (FILE *input_file ); +void skel__switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE skel__create_buffer (FILE *file,int size ); +void skel__delete_buffer (YY_BUFFER_STATE b ); +void skel__flush_buffer (YY_BUFFER_STATE b ); +void skel_push_buffer_state (YY_BUFFER_STATE new_buffer ); +void skel_pop_buffer_state (void ); + +static void skel_ensure_buffer_stack (void ); +static void skel__load_buffer_state (void ); +static void skel__init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER skel__flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE skel__scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE skel__scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE skel__scan_bytes (yyconst char *bytes,int len ); + +/* %endif */ + +void *skel_alloc (yy_size_t ); +void *skel_realloc (void *,yy_size_t ); +void skel_free (void * ); + +#define yy_new_buffer skel__create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + skel_ensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + skel__create_buffer(skel_in,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + skel_ensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + skel__create_buffer(skel_in,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* %% [1.0] skel_text/skel_in/skel_out/yy_state_type/skel_lineno etc. def's & init go here */ +/* Begin user sect3 */ + +#define skel_wrap(n) 1 +#define YY_SKIP_YYWRAP + +#define FLEX_DEBUG + +typedef unsigned char YY_CHAR; + +FILE *skel_in = (FILE *) 0, *skel_out = (FILE *) 0; + +typedef int yy_state_type; + +extern int skel_lineno; + +int skel_lineno = 1; + +extern char *skel_text; +#define yytext_ptr skel_text + +/* %if-c-only Standard (non-C++) definition */ + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* %endif */ + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up skel_text. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ +/* %% [2.0] code to fiddle skel_text and skel_leng for yymore() goes here \ */\ + skel_leng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ +/* %% [3.0] code to copy yytext_ptr to skel_text[] goes here, if %array \ */\ + (yy_c_buf_p) = yy_cp; + +/* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */ +#define YY_NUM_RULES 25 +#define YY_END_OF_BUFFER 26 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[72] = + { 0, + 0, 0, 0, 0, 0, 0, 26, 14, 13, 1, + 12, 15, 22, 24, 23, 23, 14, 1, 12, 6, + 12, 5, 2, 12, 12, 12, 3, 4, 15, 22, + 20, 22, 19, 21, 16, 17, 18, 12, 12, 12, + 12, 12, 0, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 8, 7, 12, 12, 12, 11, 12, 12, 9, 10, + 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 1, 5, 6, + 7, 1, 1, 7, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 8, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 9, 10, 11, 1, + + 12, 13, 1, 1, 14, 1, 1, 15, 16, 17, + 18, 19, 1, 1, 20, 21, 22, 1, 1, 1, + 1, 1, 23, 1, 24, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[25] = + { 0, + 1, 1, 2, 1, 1, 3, 1, 4, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1 + } ; + +static yyconst flex_int16_t yy_base[79] = + { 0, + 0, 2, 68, 67, 9, 12, 74, 0, 109, 69, + 14, 0, 36, 109, 109, 109, 0, 68, 58, 109, + 17, 109, 109, 62, 52, 13, 109, 109, 0, 109, + 109, 26, 109, 109, 109, 109, 109, 49, 52, 53, + 51, 43, 30, 50, 39, 42, 39, 36, 37, 38, + 40, 39, 28, 40, 39, 39, 38, 24, 26, 22, + 109, 109, 25, 15, 6, 109, 3, 1, 109, 109, + 109, 82, 86, 90, 94, 97, 101, 104 + } ; + +static yyconst flex_int16_t yy_def[79] = + { 0, + 72, 72, 73, 73, 74, 74, 71, 75, 71, 75, + 76, 77, 78, 71, 71, 71, 75, 75, 76, 71, + 19, 71, 71, 19, 19, 19, 71, 71, 77, 71, + 71, 71, 71, 71, 71, 71, 71, 19, 19, 19, + 19, 19, 71, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 71, 71, 19, 19, 19, 71, 19, 19, 71, 71, + 0, 71, 71, 71, 71, 71, 71, 71 + } ; + +static yyconst flex_int16_t yy_nxt[134] = + { 0, + 71, 71, 9, 10, 9, 10, 70, 11, 69, 11, + 15, 16, 15, 15, 16, 15, 20, 21, 22, 20, + 21, 23, 68, 24, 25, 40, 67, 41, 31, 43, + 66, 26, 31, 43, 42, 65, 27, 28, 31, 32, + 33, 64, 34, 35, 63, 62, 61, 60, 59, 58, + 57, 56, 55, 54, 53, 52, 51, 50, 36, 37, + 71, 49, 71, 48, 47, 71, 46, 45, 44, 39, + 38, 18, 18, 71, 13, 13, 71, 71, 71, 71, + 71, 71, 8, 8, 8, 8, 12, 12, 12, 12, + 14, 14, 14, 14, 17, 71, 17, 19, 19, 71, + + 19, 29, 29, 29, 30, 30, 30, 30, 7, 71, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71 + } ; + +static yyconst flex_int16_t yy_chk[134] = + { 0, + 0, 0, 1, 1, 2, 2, 68, 1, 67, 2, + 5, 5, 5, 6, 6, 6, 11, 11, 11, 21, + 21, 11, 65, 11, 11, 26, 64, 26, 32, 32, + 63, 11, 43, 43, 26, 60, 11, 11, 13, 13, + 13, 59, 13, 13, 58, 57, 56, 55, 54, 53, + 52, 51, 50, 49, 48, 47, 46, 45, 13, 13, + 19, 44, 19, 42, 41, 19, 40, 39, 38, 25, + 24, 18, 10, 7, 4, 3, 0, 0, 0, 0, + 19, 19, 72, 72, 72, 72, 73, 73, 73, 73, + 74, 74, 74, 74, 75, 0, 75, 76, 76, 0, + + 76, 77, 77, 77, 78, 78, 78, 78, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, + 71, 71, 71 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int skel__flex_debug; +int skel__flex_debug = 1; + +static yyconst flex_int16_t yy_rule_linenum[25] = + { 0, + 72, 73, 74, 75, 76, 77, 79, 80, 82, 83, + 84, 87, 88, 89, 102, 104, 105, 106, 107, 108, + 110, 129, 134, 135 + } ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *skel_text; +#line 1 "scan-skel.l" +/* Scan Bison Skeletons. -*- C -*- + + Copyright (C) 2001-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#define YY_NO_INPUT 1 +#line 24 "scan-skel.l" +/* Work around a bug in flex 2.5.31. See Debian bug 333231 + <http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=333231>. */ +#undef skel_wrap +#define skel_wrap() 1 + +#define FLEX_PREFIX(Id) skel_ ## Id +#include <src/flex-scanner.h> + +#include <dirname.h> +#include <error.h> +#include <quotearg.h> + +#include <src/complain.h> +#include <src/getargs.h> +#include <src/files.h> +#include <src/scan-skel.h> + +#define YY_DECL static int skel_lex (void) +YY_DECL; + +typedef void (*at_directive)(int, char**, char **, int*); +static void at_init (int *argc, char *argv[], at_directive *at_ptr, at_directive fun); +static void at_basename (int argc, char *argv[], char**, int*); +static void at_complain (int argc, char *argv[], char**, int*); +static void at_output (int argc, char *argv[], char **name, int *lineno); +static void fail_for_at_directive_too_many_args (char const *at_directive_name); +static void fail_for_at_directive_too_few_args (char const *at_directive_name); +static void fail_for_invalid_at (char const *at); + + +#line 671 "lex.yy.c" + +#define INITIAL 0 +#define SC_AT_DIRECTIVE_ARGS 1 +#define SC_AT_DIRECTIVE_SKIP_WS 2 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +/* %if-c-only */ +#include <unistd.h> +/* %endif */ +/* %if-c++-only */ +/* %endif */ +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* %if-c-only Reentrant structure and macros (non-C++). */ +/* %if-reentrant */ +/* %if-c-only */ + +static int yy_init_globals (void ); + +/* %endif */ +/* %if-reentrant */ +/* %endif */ +/* %endif End reentrant structures and macros. */ + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int skel_lex_destroy (void ); + +int skel_get_debug (void ); + +void skel_set_debug (int debug_flag ); + +YY_EXTRA_TYPE skel_get_extra (void ); + +void skel_set_extra (YY_EXTRA_TYPE user_defined ); + +FILE *skel_get_in (void ); + +void skel_set_in (FILE * in_str ); + +FILE *skel_get_out (void ); + +void skel_set_out (FILE * out_str ); + +int skel_get_leng (void ); + +char *skel_get_text (void ); + +int skel_get_lineno (void ); + +void skel_set_lineno (int line_number ); + +/* %if-bison-bridge */ +/* %endif */ + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int skel_wrap (void ); +#else +extern int skel_wrap (void ); +#endif +#endif + +/* %not-for-header */ + +/* %ok-for-header */ + +/* %endif */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT +/* %if-c-only Standard (non-C++) definition */ +/* %not-for-header */ + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif +/* %ok-for-header */ + +/* %endif */ +#endif + +/* %if-c-only */ + +/* %endif */ + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* %if-c-only Standard (non-C++) definition */ +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( skel_text, skel_leng, 1, skel_out )) {} } while (0) +/* %endif */ +/* %if-c++-only C++ definition */ +/* %endif */ +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ +/* %% [5.0] fread()/read() definition of YY_INPUT goes here unless we're doing C++ \ */\ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( skel_in )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( skel_in ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, skel_in))==0 && ferror(skel_in)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(skel_in); \ + } \ + }\ +\ +/* %if-c++-only C++ definition \ */\ +/* %endif */ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +/* %if-c-only */ +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +#endif + +/* %if-tables-serialization structures and prototypes */ +/* %not-for-header */ + +/* %ok-for-header */ + +/* %not-for-header */ + +/* %tables-yydmap generated elements */ +/* %endif */ +/* end tables serialization structures and prototypes */ + +/* %ok-for-header */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 +/* %if-c-only Standard (non-C++) definition */ + +extern int skel_lex (void); + +#define YY_DECL int skel_lex (void) +/* %endif */ +/* %if-c++-only C++ definition */ +/* %endif */ +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after skel_text and skel_leng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +/* %% [6.0] YY_RULE_SETUP definition goes here */ +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/* %not-for-header */ + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +/* %% [7.0] user's declarations go here */ +#line 57 "scan-skel.l" + + + + int out_lineno PACIFY_CC (= 0); + char *out_name = NULL; + + /* Currently, only the @complain directive takes multiple arguments, and + never more than 7, with argv[0] being the directive name and argv[1] + being the type of complaint to dispatch. */ +#define ARGC_MAX 9 + int argc = 0; + char *argv[ARGC_MAX]; + at_directive at_ptr = NULL; + + +#line 934 "lex.yy.c" + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! skel_in ) +/* %if-c-only */ + skel_in = stdin; +/* %endif */ +/* %if-c++-only */ +/* %endif */ + + if ( ! skel_out ) +/* %if-c-only */ + skel_out = stdout; +/* %endif */ +/* %if-c++-only */ +/* %endif */ + + if ( ! YY_CURRENT_BUFFER ) { + skel_ensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + skel__create_buffer(skel_in,YY_BUF_SIZE ); + } + + skel__load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { +/* %% [8.0] yymore()-related code goes here */ + yy_cp = (yy_c_buf_p); + + /* Support of skel_text. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + +/* %% [9.0] code to set up and find next match goes here */ + yy_current_state = (yy_start); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 72 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_current_state != 71 ); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + +yy_find_action: +/* %% [10.0] code to find the action number goes here */ + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +/* %% [11.0] code for skel_lineno update goes here */ + +do_action: /* This label is used only to access EOF actions. */ + +/* %% [12.0] debug code goes here */ + if ( skel__flex_debug ) + { + if ( yy_act == 0 ) + fprintf( stderr, "--scanner backing up\n" ); + else if ( yy_act < 25 ) + fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n", + (long)yy_rule_linenum[yy_act], skel_text ); + else if ( yy_act == 25 ) + fprintf( stderr, "--accepting default rule (\"%s\")\n", + skel_text ); + else if ( yy_act == 26 ) + fprintf( stderr, "--(end of buffer or a NUL)\n" ); + else + fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); + } + + switch ( yy_act ) + { /* beginning of action switch */ +/* %% [13.0] actions go here */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 72 "scan-skel.l" +continue; + YY_BREAK +case 2: +YY_RULE_SETUP +#line 73 "scan-skel.l" +fputc ('@', skel_out); + YY_BREAK +case 3: +YY_RULE_SETUP +#line 74 "scan-skel.l" +fputc ('[', skel_out); + YY_BREAK +case 4: +YY_RULE_SETUP +#line 75 "scan-skel.l" +fputc (']', skel_out); + YY_BREAK +case 5: +YY_RULE_SETUP +#line 76 "scan-skel.l" +continue; /* Used by b4_cat in ../data/bison.m4. */ + YY_BREAK +case 6: +/* rule 6 can match eol */ +YY_RULE_SETUP +#line 77 "scan-skel.l" +continue; + YY_BREAK +case 7: +YY_RULE_SETUP +#line 79 "scan-skel.l" +fprintf (skel_out, "%d", out_lineno + 1); + YY_BREAK +case 8: +YY_RULE_SETUP +#line 80 "scan-skel.l" +fputs (quotearg_style (c_quoting_style, out_name), skel_out); + YY_BREAK +case 9: +YY_RULE_SETUP +#line 82 "scan-skel.l" +at_init (&argc, argv, &at_ptr, &at_basename); + YY_BREAK +case 10: +YY_RULE_SETUP +#line 83 "scan-skel.l" +at_init (&argc, argv, &at_ptr, &at_complain); + YY_BREAK +case 11: +YY_RULE_SETUP +#line 84 "scan-skel.l" +at_init (&argc, argv, &at_ptr, &at_output); + YY_BREAK +/* This pattern must not match more than the previous @ patterns. */ +case 12: +YY_RULE_SETUP +#line 87 "scan-skel.l" +fail_for_invalid_at (skel_text); + YY_BREAK +case 13: +/* rule 13 can match eol */ +YY_RULE_SETUP +#line 88 "scan-skel.l" +out_lineno++; ECHO; + YY_BREAK +case 14: +YY_RULE_SETUP +#line 89 "scan-skel.l" +ECHO; + YY_BREAK +case YY_STATE_EOF(INITIAL): +#line 91 "scan-skel.l" +{ + if (out_name) + { + free (out_name); + xfclose (skel_out); + } + return EOF; +} + YY_BREAK + + +case 15: +/* rule 15 can match eol */ +YY_RULE_SETUP +#line 102 "scan-skel.l" +STRING_GROW; + YY_BREAK +case 16: +YY_RULE_SETUP +#line 104 "scan-skel.l" +obstack_1grow (&obstack_for_string, '@'); + YY_BREAK +case 17: +YY_RULE_SETUP +#line 105 "scan-skel.l" +obstack_1grow (&obstack_for_string, '['); + YY_BREAK +case 18: +YY_RULE_SETUP +#line 106 "scan-skel.l" +obstack_1grow (&obstack_for_string, ']'); + YY_BREAK +case 19: +YY_RULE_SETUP +#line 107 "scan-skel.l" +continue; /* For starting an argument that begins with whitespace. */ + YY_BREAK +case 20: +/* rule 20 can match eol */ +YY_RULE_SETUP +#line 108 "scan-skel.l" +continue; + YY_BREAK +case 21: +YY_RULE_SETUP +#line 110 "scan-skel.l" +{ + if (argc >= ARGC_MAX) + fail_for_at_directive_too_many_args (argv[0]); + + argv[argc++] = obstack_finish0 (&obstack_for_string); + + /* Like M4, skip whitespace after a comma. */ + if (skel_text[1] == ',') + BEGIN SC_AT_DIRECTIVE_SKIP_WS; + else + { + aver (at_ptr); + at_ptr (argc, argv, &out_name, &out_lineno); + obstack_free (&obstack_for_string, argv[0]); + argc = 0; + BEGIN INITIAL; + } + } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 129 "scan-skel.l" +fail_for_invalid_at (skel_text); + YY_BREAK + + + +case 23: +/* rule 23 can match eol */ +YY_RULE_SETUP +#line 134 "scan-skel.l" +continue; + YY_BREAK +case 24: +YY_RULE_SETUP +#line 135 "scan-skel.l" +yyless (0); BEGIN SC_AT_DIRECTIVE_ARGS; + YY_BREAK + + + +case YY_STATE_EOF(SC_AT_DIRECTIVE_ARGS): +case YY_STATE_EOF(SC_AT_DIRECTIVE_SKIP_WS): +#line 140 "scan-skel.l" +complain (NULL, fatal, _("unclosed %s directive in skeleton"), argv[0]); + YY_BREAK + +case 25: +YY_RULE_SETUP +#line 143 "scan-skel.l" +YY_FATAL_ERROR( "flex scanner jammed" ); + YY_BREAK +#line 1217 "lex.yy.c" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed skel_in at a new source and called + * skel_lex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = skel_in; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { +/* %% [14.0] code to do back-up for compressed tables and set up yy_cp goes here */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( skel_wrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * skel_text, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of skel_lex */ +/* %ok-for-header */ + +/* %if-c++-only */ +/* %not-for-header */ + +/* %ok-for-header */ + +/* %endif */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +/* %if-c-only */ +static int yy_get_next_buffer (void) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + skel_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + skel_restart(skel_in ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) skel_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +/* %if-c-only */ +/* %not-for-header */ + + static yy_state_type yy_get_previous_state (void) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + register yy_state_type yy_current_state; + register char *yy_cp; + +/* %% [15.0] code to get the start state into yy_current_state goes here */ + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { +/* %% [16.0] code to find the next state goes here */ + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 72 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ +/* %if-c-only */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + register int yy_is_jam; + /* %% [17.0] code to find the next state, and perhaps do backing up, goes here */ + register char *yy_cp = (yy_c_buf_p); + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 72 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 71); + + return yy_is_jam ? 0 : yy_current_state; +} + +/* %if-c-only */ + +/* %endif */ + +/* %if-c-only */ +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + skel_restart(skel_in ); + + BISON_FALLTHROUGH; + + case EOB_ACT_END_OF_FILE: + { + if ( skel_wrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve skel_text */ + (yy_hold_char) = *++(yy_c_buf_p); + +/* %% [19.0] update BOL and skel_lineno */ + + return c; +} +/* %if-c-only */ +#endif /* ifndef YY_NO_INPUT */ +/* %endif */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ +/* %if-c-only */ + void skel_restart (FILE * input_file ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + + if ( ! YY_CURRENT_BUFFER ){ + skel_ensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + skel__create_buffer(skel_in,YY_BUF_SIZE ); + } + + skel__init_buffer(YY_CURRENT_BUFFER,input_file ); + skel__load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ +/* %if-c-only */ + void skel__switch_to_buffer (YY_BUFFER_STATE new_buffer ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + + /* TODO. We should be able to replace this entire function body + * with + * skel_pop_buffer_state(); + * skel_push_buffer_state(new_buffer); + */ + skel_ensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + skel__load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (skel_wrap()) processing, but the only time this flag + * is looked at is after skel_wrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +/* %if-c-only */ +static void skel__load_buffer_state (void) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + skel_in = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ +/* %if-c-only */ + YY_BUFFER_STATE skel__create_buffer (FILE * file, int size ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) skel_alloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in skel__create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) skel_alloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in skel__create_buffer()" ); + + b->yy_is_our_buffer = 1; + + skel__init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with skel__create_buffer() + * + */ +/* %if-c-only */ + void skel__delete_buffer (YY_BUFFER_STATE b ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + skel_free((void *) b->yy_ch_buf ); + + skel_free((void *) b ); +} + +/* %if-c-only */ + +/* %endif */ + +/* %if-c++-only */ +/* %endif */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a skel_restart() or at EOF. + */ +/* %if-c-only */ + static void skel__init_buffer (YY_BUFFER_STATE b, FILE * file ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ + +{ + int oerrno = errno; + + skel__flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then skel__init_buffer was _probably_ + * called from skel_restart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + +/* %if-c-only */ + + b->yy_is_interactive = 0; + +/* %endif */ +/* %if-c++-only */ +/* %endif */ + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ +/* %if-c-only */ + void skel__flush_buffer (YY_BUFFER_STATE b ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + skel__load_buffer_state( ); +} + +/* %if-c-or-c++ */ +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +/* %if-c-only */ +void skel_push_buffer_state (YY_BUFFER_STATE new_buffer ) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + if (new_buffer == NULL) + return; + + skel_ensure_buffer_stack(); + + /* This block is copied from skel__switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from skel__switch_to_buffer. */ + skel__load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} +/* %endif */ + +/* %if-c-or-c++ */ +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +/* %if-c-only */ +void skel_pop_buffer_state (void) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + if (!YY_CURRENT_BUFFER) + return; + + skel__delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + skel__load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} +/* %endif */ + +/* %if-c-or-c++ */ +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +/* %if-c-only */ +static void skel_ensure_buffer_stack (void) +/* %endif */ +/* %if-c++-only */ +/* %endif */ +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)skel_alloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in skel_ensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)skel_realloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in skel_ensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} +/* %endif */ + +/* %if-c-only */ +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE skel__scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) skel_alloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in skel__scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + skel__switch_to_buffer(b ); + + return b; +} +/* %endif */ + +/* %if-c-only */ +/** Setup the input buffer state to scan a string. The next call to skel_lex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * skel__scan_bytes() instead. + */ +YY_BUFFER_STATE skel__scan_string (yyconst char * yystr ) +{ + + return skel__scan_bytes(yystr,strlen(yystr) ); +} +/* %endif */ + +/* %if-c-only */ +/** Setup the input buffer state to scan the given bytes. The next call to skel_lex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE skel__scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) skel_alloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in skel__scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = skel__scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in skel__scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} +/* %endif */ + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +/* %if-c-only */ +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} +/* %endif */ +/* %if-c++-only */ +/* %endif */ + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up skel_text. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + skel_text[skel_leng] = (yy_hold_char); \ + (yy_c_buf_p) = skel_text + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + skel_leng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/* %if-c-only */ +/* %if-reentrant */ +/* %endif */ + +/** Get the current line number. + * + */ +int skel_get_lineno (void) +{ + + return skel_lineno; +} + +/** Get the input stream. + * + */ +FILE *skel_get_in (void) +{ + return skel_in; +} + +/** Get the output stream. + * + */ +FILE *skel_get_out (void) +{ + return skel_out; +} + +/** Get the length of the current token. + * + */ +int skel_get_leng (void) +{ + return skel_leng; +} + +/** Get the current token. + * + */ + +char *skel_get_text (void) +{ + return skel_text; +} + +/* %if-reentrant */ +/* %endif */ + +/** Set the current line number. + * @param line_number + * + */ +void skel_set_lineno (int line_number ) +{ + + skel_lineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see skel__switch_to_buffer + */ +void skel_set_in (FILE * in_str ) +{ + skel_in = in_str ; +} + +void skel_set_out (FILE * out_str ) +{ + skel_out = out_str ; +} + +int skel_get_debug (void) +{ + return skel__flex_debug; +} + +void skel_set_debug (int bdebug ) +{ + skel__flex_debug = bdebug ; +} + +/* %endif */ + +/* %if-reentrant */ +/* %if-bison-bridge */ +/* %endif */ +/* %endif if-c-only */ + +/* %if-c-only */ +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from skel_lex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + skel_in = stdin; + skel_out = stdout; +#else + skel_in = (FILE *) 0; + skel_out = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * skel_lex_init() + */ + return 0; +} +/* %endif */ + +/* %if-c-only SNIP! this currently causes conflicts with the c++ scanner */ +/* skel_lex_destroy is for both reentrant and non-reentrant scanners. */ +int skel_lex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + skel__delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + skel_pop_buffer_state(); + } + + /* Destroy the stack itself. */ + skel_free((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * skel_lex() is called, initialization will occur. */ + yy_init_globals( ); + +/* %if-reentrant */ +/* %endif */ + return 0; +} +/* %endif */ + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *skel_alloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *skel_realloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void skel_free (void * ptr ) +{ + free( (char *) ptr ); /* see skel_realloc() for (char *) cast */ +} + +/* %if-tables-serialization definitions */ +/* %define-yytables The name for this specific scanner's tables. */ +#define YYTABLES_NAME "yytables" +/* %endif */ + +/* %ok-for-header */ + +#line 143 "scan-skel.l" + + + +static void +at_init (int *argc, char *argv[], at_directive *at_ptr, at_directive fun) +{ + *at_ptr = fun; + skel_text[skel_leng-1] = '\0'; + obstack_grow (&obstack_for_string, skel_text, skel_leng); + argv[(*argc)++] = obstack_finish (&obstack_for_string); + BEGIN SC_AT_DIRECTIVE_ARGS; +} + +/*------------------------. +| Scan a Bison skeleton. | +`------------------------*/ + +void +scan_skel (FILE *in) +{ + static bool initialized = false; + if (!initialized) + { + initialized = true; + obstack_init (&obstack_for_string); + } + skel_in = in; + skel__flex_debug = trace_flag & trace_skeleton; + skel_lex (); +} + +void +skel_scanner_free (void) +{ + obstack_free (&obstack_for_string, 0); + /* Reclaim Flex's buffers. */ + skel_lex_destroy (); +} + +static inline warnings +flag (const char *arg) +{ + /* compare with values issued from b4_error */ + if (STREQ (arg, "complain")) + return complaint; + else if (STREQ (arg, "deprecated")) + return Wdeprecated; + else if (STREQ (arg, "fatal")) + return fatal; + else if (STREQ (arg, "note")) + return silent | complaint | no_caret; + else if (STREQ (arg, "warn")) + return Wother; + else + aver (false); +} + +static void +at_basename (int argc, char *argv[], char **out_namep, int *out_linenop) +{ + (void) out_namep; + (void) out_linenop; + if (2 < argc) + fail_for_at_directive_too_many_args (argv[0]); + fputs (last_component (argv[1]), skel_out); +} + +static void +at_complain (int argc, char *argv[], char **out_namep, int *out_linenop) +{ + static unsigned indent; + warnings w = flag (argv[1]); + location loc; + location *locp = NULL; + + (void) out_namep; + (void) out_linenop; + + if (argc < 4) + fail_for_at_directive_too_few_args (argv[0]); + if (argv[2] && argv[2][0]) + { + boundary_set_from_string (&loc.start, argv[2]); + boundary_set_from_string (&loc.end, argv[3]); + locp = &loc; + } + if (w & silent) + indent += SUB_INDENT; + else + indent = 0; + complain_args (locp, w, &indent, argc - 4, argv + 4); + if (w & silent) + indent -= SUB_INDENT; +} + +static void +at_output (int argc, char *argv[], char **out_namep, int *out_linenop) +{ + if (2 < argc) + fail_for_at_directive_too_many_args (argv[0]); + if (*out_namep) + { + free (*out_namep); + xfclose (skel_out); + } + *out_namep = xstrdup (argv[1]); + output_file_name_check (out_namep); + skel_out = xfopen (*out_namep, "wb"); + *out_linenop = 1; +} + +static void +fail_for_at_directive_too_few_args (char const *at_directive_name) +{ + complain (NULL, fatal, _("too few arguments for %s directive in skeleton"), + at_directive_name); +} + +static void +fail_for_at_directive_too_many_args (char const *at_directive_name) +{ + complain (NULL, fatal, _("too many arguments for %s directive in skeleton"), + at_directive_name); +} + +static void +fail_for_invalid_at (char const *at) +{ + complain (NULL, fatal, "invalid @ in skeleton: %s", at); +} + diff --git a/contrib/tools/bison/src/scan-skel.h b/contrib/tools/bison/src/scan-skel.h new file mode 100644 index 0000000000..019d38af5a --- /dev/null +++ b/contrib/tools/bison/src/scan-skel.h @@ -0,0 +1,27 @@ +/* Scan Bison Skeletons. + + Copyright (C) 2005-2007, 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +void scan_skel (FILE *); + +/* Pacify "make syntax-check". */ +extern FILE *skel_in; +extern FILE *skel_out; +extern int skel__flex_debug; +extern int skel_lineno; +void skel_scanner_free (void); diff --git a/contrib/tools/bison/src/state.c b/contrib/tools/bison/src/state.c new file mode 100644 index 0000000000..c11b10f7dd --- /dev/null +++ b/contrib/tools/bison/src/state.c @@ -0,0 +1,466 @@ +/* Type definitions for the finite state machine for Bison. + + Copyright (C) 2001-2007, 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include <hash.h> + +#include "complain.h" +#include "gram.h" +#include "state.h" +#include "print-xml.h" + + + /*-------------------. + | Shifts and Gotos. | + `-------------------*/ + + +/*-----------------------------------------. +| Create a new array of NUM shifts/gotos. | +`-----------------------------------------*/ + +static transitions * +transitions_new (int num, state **the_states) +{ + size_t states_size = num * sizeof *the_states; + transitions *res = xmalloc (offsetof (transitions, states) + states_size); + res->num = num; + memcpy (res->states, the_states, states_size); + return res; +} + + +/*-------------------------------------------------------. +| Return the state such that SHIFTS contain a shift/goto | +| to it on SYM. Abort if none found. | +`-------------------------------------------------------*/ + +state * +transitions_to (transitions *shifts, symbol_number sym) +{ + int j; + for (j = 0; ; j++) + { + aver (j < shifts->num); + if (TRANSITION_SYMBOL (shifts, j) == sym) + return shifts->states[j]; + } +} + + + /*--------------------. + | Error transitions. | + `--------------------*/ + + +/*---------------------------------. +| Create a new array of NUM errs. | +`---------------------------------*/ + +errs * +errs_new (int num, symbol **tokens) +{ + size_t symbols_size = num * sizeof *tokens; + errs *res = xmalloc (offsetof (errs, symbols) + symbols_size); + res->num = num; + memcpy (res->symbols, tokens, symbols_size); + return res; +} + + + + + /*-------------. + | Reductions. | + `-------------*/ + + +/*---------------------------------------. +| Create a new array of NUM reductions. | +`---------------------------------------*/ + +static reductions * +reductions_new (int num, rule **reds) +{ + size_t rules_size = num * sizeof *reds; + reductions *res = xmalloc (offsetof (reductions, rules) + rules_size); + res->num = num; + res->lookahead_tokens = NULL; + memcpy (res->rules, reds, rules_size); + return res; +} + + + + /*---------. + | States. | + `---------*/ + + +state_number nstates = 0; +/* FINAL_STATE is properly set by new_state when it recognizes its + accessing symbol: $end. */ +state *final_state = NULL; + + +/*------------------------------------------------------------------. +| Create a new state with ACCESSING_SYMBOL, for those items. Store | +| it in the state hash table. | +`------------------------------------------------------------------*/ + +state * +state_new (symbol_number accessing_symbol, + size_t nitems, item_number *core) +{ + state *res; + size_t items_size = nitems * sizeof *core; + + aver (nstates < STATE_NUMBER_MAXIMUM); + + res = xmalloc (offsetof (state, items) + items_size); + res->number = nstates++; + res->accessing_symbol = accessing_symbol; + res->transitions = NULL; + res->reductions = NULL; + res->errs = NULL; + res->state_list = NULL; + res->consistent = 0; + res->solved_conflicts = NULL; + res->solved_conflicts_xml = NULL; + + res->nitems = nitems; + memcpy (res->items, core, items_size); + + state_hash_insert (res); + + return res; +} + +state * +state_new_isocore (state const *s) +{ + state *res; + size_t items_size = s->nitems * sizeof *s->items; + + aver (nstates < STATE_NUMBER_MAXIMUM); + + res = xmalloc (offsetof (state, items) + items_size); + res->number = nstates++; + res->accessing_symbol = s->accessing_symbol; + res->transitions = + transitions_new (s->transitions->num, s->transitions->states); + res->reductions = reductions_new (s->reductions->num, s->reductions->rules); + res->errs = NULL; + res->state_list = NULL; + res->consistent = s->consistent; + res->solved_conflicts = NULL; + res->solved_conflicts_xml = NULL; + + res->nitems = s->nitems; + memcpy (res->items, s->items, items_size); + + return res; +} + + +/*---------. +| Free S. | +`---------*/ + +static void +state_free (state *s) +{ + free (s->transitions); + free (s->reductions); + free (s->errs); + free (s); +} + + +/*---------------------------. +| Set the transitions of S. | +`---------------------------*/ + +void +state_transitions_set (state *s, int num, state **trans) +{ + aver (!s->transitions); + s->transitions = transitions_new (num, trans); +} + + +/*--------------------------. +| Set the reductions of S. | +`--------------------------*/ + +void +state_reductions_set (state *s, int num, rule **reds) +{ + aver (!s->reductions); + s->reductions = reductions_new (num, reds); +} + + +int +state_reduction_find (state *s, rule *r) +{ + int i; + reductions *reds = s->reductions; + for (i = 0; i < reds->num; ++i) + if (reds->rules[i] == r) + return i; + return -1; +} + + +/*--------------------. +| Set the errs of S. | +`--------------------*/ + +void +state_errs_set (state *s, int num, symbol **tokens) +{ + aver (!s->errs); + s->errs = errs_new (num, tokens); +} + + + +/*--------------------------------------------------. +| Print on OUT all the lookahead tokens such that S | +| wants to reduce R. | +`--------------------------------------------------*/ + +void +state_rule_lookahead_tokens_print (state *s, rule *r, FILE *out) +{ + /* Find the reduction we are handling. */ + reductions *reds = s->reductions; + int red = state_reduction_find (s, r); + + /* Print them if there are. */ + if (reds->lookahead_tokens && red != -1) + { + bitset_iterator biter; + int k; + char const *sep = ""; + fprintf (out, " ["); + BITSET_FOR_EACH (biter, reds->lookahead_tokens[red], k, 0) + { + fprintf (out, "%s%s", sep, symbols[k]->tag); + sep = ", "; + } + fprintf (out, "]"); + } +} + +void +state_rule_lookahead_tokens_print_xml (state *s, rule *r, + FILE *out, int level) +{ + /* Find the reduction we are handling. */ + reductions *reds = s->reductions; + int red = state_reduction_find (s, r); + + /* Print them if there are. */ + if (reds->lookahead_tokens && red != -1) + { + bitset_iterator biter; + int k; + xml_puts (out, level, "<lookaheads>"); + BITSET_FOR_EACH (biter, reds->lookahead_tokens[red], k, 0) + { + xml_printf (out, level + 1, "<symbol>%s</symbol>", + xml_escape (symbols[k]->tag)); + } + xml_puts (out, level, "</lookaheads>"); + } +} + + +/*---------------------. +| A state hash table. | +`---------------------*/ + +/* Initial capacity of states hash table. */ +#define HT_INITIAL_CAPACITY 257 + +static struct hash_table *state_table = NULL; + +/* Two states are equal if they have the same core items. */ +static inline bool +state_compare (state const *s1, state const *s2) +{ + size_t i; + + if (s1->nitems != s2->nitems) + return false; + + for (i = 0; i < s1->nitems; ++i) + if (s1->items[i] != s2->items[i]) + return false; + + return true; +} + +static bool +state_comparator (void const *s1, void const *s2) +{ + return state_compare (s1, s2); +} + +static inline size_t +state_hash (state const *s, size_t tablesize) +{ + /* Add up the state's item numbers to get a hash key. */ + size_t key = 0; + size_t i; + for (i = 0; i < s->nitems; ++i) + key += s->items[i]; + return key % tablesize; +} + +static size_t +state_hasher (void const *s, size_t tablesize) +{ + return state_hash (s, tablesize); +} + + +/*-------------------------------. +| Create the states hash table. | +`-------------------------------*/ + +void +state_hash_new (void) +{ + state_table = hash_initialize (HT_INITIAL_CAPACITY, + NULL, + state_hasher, + state_comparator, + NULL); +} + + +/*---------------------------------------------. +| Free the states hash table, not the states. | +`---------------------------------------------*/ + +void +state_hash_free (void) +{ + hash_free (state_table); +} + + +/*-----------------------------------. +| Insert S in the state hash table. | +`-----------------------------------*/ + +void +state_hash_insert (state *s) +{ + if (!hash_insert (state_table, s)) + xalloc_die (); +} + + +/*------------------------------------------------------------------. +| Find the state associated to the CORE, and return it. If it does | +| not exist yet, return NULL. | +`------------------------------------------------------------------*/ + +state * +state_hash_lookup (size_t nitems, item_number *core) +{ + size_t items_size = nitems * sizeof *core; + state *probe = xmalloc (offsetof (state, items) + items_size); + state *entry; + + probe->nitems = nitems; + memcpy (probe->items, core, items_size); + entry = hash_lookup (state_table, probe); + free (probe); + return entry; +} + + +/*--------------------------------------------------------. +| Record S and all states reachable from S in REACHABLE. | +`--------------------------------------------------------*/ + +static void +state_record_reachable_states (state *s, bitset reachable) +{ + if (bitset_test (reachable, s->number)) + return; + bitset_set (reachable, s->number); + { + int i; + for (i = 0; i < s->transitions->num; ++i) + if (!TRANSITION_IS_DISABLED (s->transitions, i)) + state_record_reachable_states (s->transitions->states[i], reachable); + } +} + +void +state_remove_unreachable_states (state_number old_to_new[]) +{ + state_number nstates_reachable = 0; + bitset reachable = bitset_create (nstates, BITSET_FIXED); + state_record_reachable_states (states[0], reachable); + { + state_number i; + for (i = 0; i < nstates; ++i) + { + if (bitset_test (reachable, states[i]->number)) + { + states[nstates_reachable] = states[i]; + states[nstates_reachable]->number = nstates_reachable; + old_to_new[i] = nstates_reachable++; + } + else + { + state_free (states[i]); + old_to_new[i] = nstates; + } + } + } + nstates = nstates_reachable; + bitset_free (reachable); +} + +/* All the decorated states, indexed by the state number. */ +state **states = NULL; + + +/*----------------------. +| Free all the states. | +`----------------------*/ + +void +states_free (void) +{ + state_number i; + for (i = 0; i < nstates; ++i) + state_free (states[i]); + free (states); +} diff --git a/contrib/tools/bison/src/state.h b/contrib/tools/bison/src/state.h new file mode 100644 index 0000000000..37cd9bf9ec --- /dev/null +++ b/contrib/tools/bison/src/state.h @@ -0,0 +1,274 @@ +/* Type definitions for the finite state machine for Bison. + + Copyright (C) 1984, 1989, 2000-2004, 2007, 2009-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + + +/* These type definitions are used to represent a nondeterministic + finite state machine that parses the specified grammar. This + information is generated by the function generate_states in the + file LR0. + + Each state of the machine is described by a set of items -- + particular positions in particular rules -- that are the possible + places where parsing could continue when the machine is in this + state. These symbols at these items are the allowable inputs that + can follow now. + + A core represents one state. States are numbered in the NUMBER + field. When generate_states is finished, the starting state is + state 0 and NSTATES is the number of states. (FIXME: This sentence + is no longer true: A transition to a state whose state number is + NSTATES indicates termination.) All the cores are chained together + and FIRST_STATE points to the first one (state 0). + + For each state there is a particular symbol which must have been + the last thing accepted to reach that state. It is the + ACCESSING_SYMBOL of the core. + + Each core contains a vector of NITEMS items which are the indices + in the RITEM vector of the items that are selected in this state. + + The two types of actions are shifts/gotos (push the lookahead token + and read another/goto to the state designated by a nterm) and + reductions (combine the last n things on the stack via a rule, + replace them with the symbol that the rule derives, and leave the + lookahead token alone). When the states are generated, these + actions are represented in two other lists. + + Each transition structure describes the possible transitions out + of one state, the state whose number is in the number field. Each + contains a vector of numbers of the states that transitions can go + to. The accessing_symbol fields of those states' cores say what + kind of input leads to them. + + A transition to state zero should be ignored: conflict resolution + deletes transitions by having them point to zero. + + Each reductions structure describes the possible reductions at the + state whose number is in the number field. rules is an array of + num rules. lookahead_tokens is an array of bitsets, one per rule. + + Conflict resolution can decide that certain tokens in certain + states should explicitly be errors (for implementing %nonassoc). + For each state, the tokens that are errors for this reason are + recorded in an errs structure, which holds the token numbers. + + There is at least one goto transition present in state zero. It + leads to a next-to-final state whose accessing_symbol is the + grammar's start symbol. The next-to-final state has one shift to + the final state, whose accessing_symbol is zero (end of input). + The final state has one shift, which goes to the termination state. + The reason for the extra state at the end is to placate the + parser's strategy of making all decisions one token ahead of its + actions. */ + +#ifndef STATE_H_ +# define STATE_H_ + +# include <bitset.h> + +# include "gram.h" +# include "symtab.h" + + +/*-------------------. +| Numbering states. | +`-------------------*/ + +typedef int state_number; +# define STATE_NUMBER_MAXIMUM INT_MAX + +/* Be ready to map a state_number to an int. */ +static inline int +state_number_as_int (state_number s) +{ + return s; +} + + +typedef struct state state; + +/*--------------. +| Transitions. | +`--------------*/ + +typedef struct +{ + int num; + state *states[1]; +} transitions; + + +/* What is the symbol labelling the transition to + TRANSITIONS->states[Num]? Can be a token (amongst which the error + token), or non terminals in case of gotos. */ + +# define TRANSITION_SYMBOL(Transitions, Num) \ + (Transitions->states[Num]->accessing_symbol) + +/* Is the TRANSITIONS->states[Num] a shift? (as opposed to gotos). */ + +# define TRANSITION_IS_SHIFT(Transitions, Num) \ + (ISTOKEN (TRANSITION_SYMBOL (Transitions, Num))) + +/* Is the TRANSITIONS->states[Num] a goto?. */ + +# define TRANSITION_IS_GOTO(Transitions, Num) \ + (!TRANSITION_IS_SHIFT (Transitions, Num)) + +/* Is the TRANSITIONS->states[Num] labelled by the error token? */ + +# define TRANSITION_IS_ERROR(Transitions, Num) \ + (TRANSITION_SYMBOL (Transitions, Num) == errtoken->number) + +/* When resolving a SR conflicts, if the reduction wins, the shift is + disabled. */ + +# define TRANSITION_DISABLE(Transitions, Num) \ + (Transitions->states[Num] = NULL) + +# define TRANSITION_IS_DISABLED(Transitions, Num) \ + (Transitions->states[Num] == NULL) + + +/* Iterate over each transition over a token (shifts). */ +# define FOR_EACH_SHIFT(Transitions, Iter) \ + for (Iter = 0; \ + Iter < Transitions->num \ + && (TRANSITION_IS_DISABLED (Transitions, Iter) \ + || TRANSITION_IS_SHIFT (Transitions, Iter)); \ + ++Iter) \ + if (!TRANSITION_IS_DISABLED (Transitions, Iter)) + + +/* Return the state such SHIFTS contain a shift/goto to it on SYM. + Abort if none found. */ +struct state *transitions_to (transitions *shifts, symbol_number sym); + + +/*-------. +| Errs. | +`-------*/ + +typedef struct +{ + int num; + symbol *symbols[1]; +} errs; + +errs *errs_new (int num, symbol **tokens); + + +/*-------------. +| Reductions. | +`-------------*/ + +typedef struct +{ + int num; + bitset *lookahead_tokens; + /* Sorted ascendingly on rule number. */ + rule *rules[1]; +} reductions; + + + +/*---------. +| states. | +`---------*/ + +struct state_list; + +struct state +{ + state_number number; + symbol_number accessing_symbol; + transitions *transitions; + reductions *reductions; + errs *errs; + + /* When an includer (such as ielr.c) needs to store states in a list, the + includer can define struct state_list as the list node structure and can + store in this member a reference to the node containing each state. */ + struct state_list *state_list; + + /* If non-zero, then no lookahead sets on reduce actions are needed to + decide what to do in state S. */ + char consistent; + + /* If some conflicts were solved thanks to precedence/associativity, + a human readable description of the resolution. */ + const char *solved_conflicts; + const char *solved_conflicts_xml; + + /* Its items. Must be last, since ITEMS can be arbitrarily large. Sorted + ascendingly on item index in RITEM, which is sorted on rule number. */ + size_t nitems; + item_number items[1]; +}; + +extern state_number nstates; +extern state *final_state; + +/* Create a new state with ACCESSING_SYMBOL for those items. */ +state *state_new (symbol_number accessing_symbol, + size_t core_size, item_number *core); +state *state_new_isocore (state const *s); + +/* Set the transitions of STATE. */ +void state_transitions_set (state *s, int num, state **trans); + +/* Set the reductions of STATE. */ +void state_reductions_set (state *s, int num, rule **reds); + +int state_reduction_find (state *s, rule *r); + +/* Set the errs of STATE. */ +void state_errs_set (state *s, int num, symbol **errors); + +/* Print on OUT all the lookahead tokens such that this STATE wants to + reduce R. */ +void state_rule_lookahead_tokens_print (state *s, rule *r, FILE *out); +void state_rule_lookahead_tokens_print_xml (state *s, rule *r, + FILE *out, int level); + +/* Create/destroy the states hash table. */ +void state_hash_new (void); +void state_hash_free (void); + +/* Find the state associated to the CORE, and return it. If it does + not exist yet, return NULL. */ +state *state_hash_lookup (size_t core_size, item_number *core); + +/* Insert STATE in the state hash table. */ +void state_hash_insert (state *s); + +/* Remove unreachable states, renumber remaining states, update NSTATES, and + write to OLD_TO_NEW a mapping of old state numbers to new state numbers such + that the old value of NSTATES is written as the new state number for removed + states. The size of OLD_TO_NEW must be the old value of NSTATES. */ +void state_remove_unreachable_states (state_number old_to_new[]); + +/* All the states, indexed by the state number. */ +extern state **states; + +/* Free all the states. */ +void states_free (void); + +#endif /* !STATE_H_ */ diff --git a/contrib/tools/bison/src/symlist.c b/contrib/tools/bison/src/symlist.c new file mode 100644 index 0000000000..531ec52fb8 --- /dev/null +++ b/contrib/tools/bison/src/symlist.c @@ -0,0 +1,239 @@ +/* Lists of symbols for Bison + + Copyright (C) 2002, 2005-2007, 2009-2013 Free Software Foundation, + Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include "complain.h" +#include "symlist.h" + +/*--------------------------------------. +| Create a list containing SYM at LOC. | +`--------------------------------------*/ + +symbol_list * +symbol_list_sym_new (symbol *sym, location loc) +{ + symbol_list *res = xmalloc (sizeof *res); + + res->content_type = SYMLIST_SYMBOL; + res->content.sym = sym; + res->location = res->sym_loc = loc; + res->named_ref = NULL; + + res->midrule = NULL; + res->midrule_parent_rule = NULL; + res->midrule_parent_rhs_index = 0; + + /* Members used for LHS only. */ + res->ruleprec = NULL; + res->percent_empty_loc = empty_location; + code_props_none_init (&res->action_props); + res->dprec = 0; + res->dprec_location = empty_location; + res->merger = 0; + res->merger_declaration_location = empty_location; + + res->next = NULL; + + return res; +} + + +/*--------------------------------------------. +| Create a list containing TYPE_NAME at LOC. | +`--------------------------------------------*/ + +symbol_list * +symbol_list_type_new (uniqstr type_name, location loc) +{ + symbol_list *res = xmalloc (sizeof *res); + + res->content_type = SYMLIST_TYPE; + res->content.sem_type = xmalloc (sizeof (semantic_type)); + res->content.sem_type->tag = type_name; + res->content.sem_type->location = loc; + res->content.sem_type->status = undeclared; + + res->location = res->sym_loc = loc; + res->named_ref = NULL; + res->next = NULL; + + return res; +} + + +/*-----------------------------------------------------------------------. +| Print this list, for which every content_type must be SYMLIST_SYMBOL. | +`-----------------------------------------------------------------------*/ + +void +symbol_list_syms_print (const symbol_list *l, FILE *f) +{ + char const *sep = ""; + for (/* Nothing. */; l && l->content.sym; l = l->next) + { + fputs (sep, f); + fputs (l->content_type == SYMLIST_SYMBOL ? "symbol: " + : l->content_type == SYMLIST_TYPE ? "type: " + : "invalid content_type: ", + f); + symbol_print (l->content.sym, f); + fputs (l->action_props.is_value_used ? " used" : " unused", f); + sep = ", "; + } +} + + +/*---------------------------. +| Prepend NODE to the LIST. | +`---------------------------*/ + +symbol_list * +symbol_list_prepend (symbol_list *list, symbol_list *node) +{ + node->next = list; + return node; +} + + +/*-------------------------. +| Append NODE to the LIST. | +`-------------------------*/ + +symbol_list * +symbol_list_append (symbol_list *list, symbol_list *node) +{ + symbol_list* next; + if (!list) + return node; + next = list; + while (next->next) + next = next->next; + next->next = node; + return list; +} + + +/*-----------------------------------------------. +| Free the LIST, but not the items it contains. | +`-----------------------------------------------*/ + +void +symbol_list_free (symbol_list *list) +{ + symbol_list *node, *next; + for (node = list; node; node = next) + { + next = node->next; + named_ref_free (node->named_ref); + if (node->content_type == SYMLIST_TYPE) + free (node->content.sem_type); + free (node); + } +} + + +/*--------------------. +| Return its length. | +`--------------------*/ + +int +symbol_list_length (symbol_list const *l) +{ + int res = 0; + for (/* Nothing. */; + l && !(l->content_type == SYMLIST_SYMBOL && l->content.sym == NULL); + l = l->next) + ++res; + return res; +} + + +/*------------------------------. +| Get item N in symbol list L. | +`------------------------------*/ + +symbol_list * +symbol_list_n_get (symbol_list *l, int n) +{ + int i; + + if (n < 0) + return NULL; + + for (i = 0; i < n; ++i) + { + l = l->next; + if (l == NULL + || (l->content_type == SYMLIST_SYMBOL && l->content.sym == NULL)) + return NULL; + } + + return l; +} + + +/*--------------------------------------------------------------. +| Get the data type (alternative in the union) of the value for | +| symbol N in symbol list L. | +`--------------------------------------------------------------*/ + +uniqstr +symbol_list_n_type_name_get (symbol_list *l, location loc, int n) +{ + l = symbol_list_n_get (l, n); + if (!l) + { + complain (&loc, complaint, _("invalid $ value: $%d"), n); + return NULL; + } + aver (l->content_type == SYMLIST_SYMBOL); + return l->content.sym->type_name; +} + +bool +symbol_list_null (symbol_list *node) +{ + return !node || + (node->content_type == SYMLIST_SYMBOL && !(node->content.sym)); +} + +void +symbol_list_code_props_set (symbol_list *node, code_props_type kind, + code_props const *cprops) +{ + switch (node->content_type) + { + case SYMLIST_SYMBOL: + symbol_code_props_set (node->content.sym, kind, cprops); + if (node->content.sym->status == undeclared) + node->content.sym->status = used; + break; + case SYMLIST_TYPE: + semantic_type_code_props_set + (semantic_type_get (node->content.sem_type->tag, + &node->content.sem_type->location), + kind, cprops); + if (node->content.sem_type->status == undeclared) + node->content.sem_type->status = used; + break; + } +} diff --git a/contrib/tools/bison/src/symlist.h b/contrib/tools/bison/src/symlist.h new file mode 100644 index 0000000000..c369f69bb1 --- /dev/null +++ b/contrib/tools/bison/src/symlist.h @@ -0,0 +1,133 @@ +/* Lists of symbols for Bison + + Copyright (C) 2002, 2005-2007, 2009-2013 Free Software Foundation, + Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef SYMLIST_H_ +# define SYMLIST_H_ + +# include "location.h" +# include "scan-code.h" +# include "symtab.h" +# include "named-ref.h" + +/* A list of symbols, used during the parsing to store the rules. */ +typedef struct symbol_list +{ + /** + * Whether this node contains a symbol, a semantic type, a \c <*>, or a + * \c <>. + */ + enum { + SYMLIST_SYMBOL, + SYMLIST_TYPE + } content_type; + union { + /** + * The symbol or \c NULL iff + * <tt>symbol_list::content_type = SYMLIST_SYMBOL</tt>. + */ + symbol *sym; + /** + * The semantic type iff <tt>symbol_list::content_type = SYMLIST_TYPE</tt>. + */ + semantic_type *sem_type; + } content; + location location; + + /* Named reference. */ + named_ref *named_ref; + + /* Proper location of the symbol, not all the rule */ + location sym_loc; + + /* If this symbol is the generated lhs for a midrule but this is the rule in + whose rhs it appears, MIDRULE = a pointer to that midrule. */ + struct symbol_list *midrule; + + /* If this symbol is the generated lhs for a midrule and this is that + midrule, MIDRULE_PARENT_RULE = a pointer to the rule in whose rhs it + appears, and MIDRULE_PARENT_RHS_INDEX = its rhs index (1-origin) in the + parent rule. */ + struct symbol_list *midrule_parent_rule; + int midrule_parent_rhs_index; + + /* ---------------------------------------------- */ + /* Apply to the rule (attached to the LHS only). */ + /* ---------------------------------------------- */ + + /* Precedence/associativity. */ + symbol *ruleprec; + + /* The action is attached to the LHS of a rule, but action properties for + * each RHS are also stored here. */ + code_props action_props; + + /* The location of the first %empty for this rule, or \a + empty_location. */ + location percent_empty_loc; + + int dprec; + location dprec_location; + int merger; + location merger_declaration_location; + + /* The list. */ + struct symbol_list *next; +} symbol_list; + + +/** Create a list containing \c sym at \c loc. */ +symbol_list *symbol_list_sym_new (symbol *sym, location loc); + +/** Create a list containing \c type_name at \c loc. */ +symbol_list *symbol_list_type_new (uniqstr type_name, location loc); + +/** Print this list. + + \pre For every node \c n in the list, <tt>n->content_type = + SYMLIST_SYMBOL</tt>. */ +void symbol_list_syms_print (const symbol_list *l, FILE *f); + +/** Prepend \c node to \c list. */ +symbol_list *symbol_list_prepend (symbol_list *list, symbol_list *node); + +/** Append \c node to \c list. */ +symbol_list *symbol_list_append (symbol_list *list, symbol_list *node); + +/** Free \c list, but not the items it contains. */ +void symbol_list_free (symbol_list *list); + +/** Return the length of \c l. */ +int symbol_list_length (symbol_list const *l); + +/** Get item \c n in symbol list \c l. */ +symbol_list *symbol_list_n_get (symbol_list *l, int n); + +/* Get the data type (alternative in the union) of the value for + symbol N in rule RULE. */ +uniqstr symbol_list_n_type_name_get (symbol_list *l, location loc, int n); + +/* Check whether the node is a border element of a rule. */ +bool symbol_list_null (symbol_list *node); + +/** Set the \c \%destructor or \c \%printer for \c node as \c cprops. */ +void symbol_list_code_props_set (symbol_list *node, code_props_type kind, + code_props const *cprops); + +#endif /* !SYMLIST_H_ */ diff --git a/contrib/tools/bison/src/symtab.c b/contrib/tools/bison/src/symtab.c new file mode 100644 index 0000000000..c06fcd2621 --- /dev/null +++ b/contrib/tools/bison/src/symtab.c @@ -0,0 +1,1178 @@ +/* Symbol table manager for Bison. + + Copyright (C) 1984, 1989, 2000-2002, 2004-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include <hash.h> + +#include "complain.h" +#include "gram.h" +#include "symtab.h" + +/*-------------------------------------------------------------------. +| Symbols sorted by tag. Allocated by the first invocation of | +| symbols_do, after which no more symbols should be created. | +`-------------------------------------------------------------------*/ + +static symbol **symbols_sorted = NULL; +static symbol **semantic_types_sorted = NULL; + +/*------------------------. +| Distinguished symbols. | +`------------------------*/ + +symbol *errtoken = NULL; +symbol *undeftoken = NULL; +symbol *endtoken = NULL; +symbol *accept = NULL; +symbol *startsymbol = NULL; +location startsymbol_location; + +/*---------------------------. +| Precedence relation graph. | +`---------------------------*/ + +static symgraph **prec_nodes; + +/*-----------------------------------. +| Store which associativity is used. | +`-----------------------------------*/ + +bool *used_assoc = NULL; + +/*---------------------------------. +| Create a new symbol, named TAG. | +`---------------------------------*/ + +static symbol * +symbol_new (uniqstr tag, location loc) +{ + symbol *res = xmalloc (sizeof *res); + uniqstr_assert (tag); + + /* If the tag is not a string (starts with a double quote), check + that it is valid for Yacc. */ + if (tag[0] != '\"' && tag[0] != '\'' && strchr (tag, '-')) + complain (&loc, Wyacc, + _("POSIX Yacc forbids dashes in symbol names: %s"), tag); + + res->tag = tag; + res->location = loc; + + res->type_name = NULL; + { + int i; + for (i = 0; i < CODE_PROPS_SIZE; ++i) + code_props_none_init (&res->props[i]); + } + + res->number = NUMBER_UNDEFINED; + res->prec = 0; + res->assoc = undef_assoc; + res->user_token_number = USER_NUMBER_UNDEFINED; + + res->alias = NULL; + res->class = unknown_sym; + res->status = undeclared; + + if (nsyms == SYMBOL_NUMBER_MAXIMUM) + complain (NULL, fatal, _("too many symbols in input grammar (limit is %d)"), + SYMBOL_NUMBER_MAXIMUM); + nsyms++; + return res; +} + +char const * +code_props_type_string (code_props_type kind) +{ + switch (kind) + { + case destructor: + return "%destructor"; + case printer: + return "%printer"; + } + assert (0); +} + +/*----------------------------------------. +| Create a new semantic type, named TAG. | +`----------------------------------------*/ + +static semantic_type * +semantic_type_new (uniqstr tag, const location *loc) +{ + semantic_type *res = xmalloc (sizeof *res); + + uniqstr_assert (tag); + res->tag = tag; + res->location = loc ? *loc : empty_location; + res->status = undeclared; + { + int i; + for (i = 0; i < CODE_PROPS_SIZE; ++i) + code_props_none_init (&res->props[i]); + } + + return res; +} + + +/*-----------------. +| Print a symbol. | +`-----------------*/ + +#define SYMBOL_ATTR_PRINT(Attr) \ + if (s->Attr) \ + fprintf (f, " %s { %s }", #Attr, s->Attr) + +#define SYMBOL_CODE_PRINT(Attr) \ + if (s->props[Attr].code) \ + fprintf (f, " %s { %s }", #Attr, s->props[Attr].code) + +void +symbol_print (symbol const *s, FILE *f) +{ + if (s) + { + fputs (s->tag, f); + SYMBOL_ATTR_PRINT (type_name); + SYMBOL_CODE_PRINT (destructor); + SYMBOL_CODE_PRINT (printer); + } + else + fputs ("<NULL>", f); +} + +#undef SYMBOL_ATTR_PRINT +#undef SYMBOL_CODE_PRINT + + +/*----------------------------------. +| Whether S is a valid identifier. | +`----------------------------------*/ + +static bool +is_identifier (uniqstr s) +{ + static char const alphanum[26 + 26 + 1 + 10 + 1] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "_" + "0123456789"; + if (!s || ! memchr (alphanum, *s, sizeof alphanum - 10)) + return false; + for (++s; *s; ++s) + if (! memchr (alphanum, *s, sizeof alphanum)) + return false; + return true; +} + + +/*-----------------------------------------------. +| Get the identifier associated to this symbol. | +`-----------------------------------------------*/ +uniqstr +symbol_id_get (symbol const *sym) +{ + aver (sym->user_token_number != USER_NUMBER_HAS_STRING_ALIAS); + if (sym->alias) + sym = sym->alias; + return is_identifier (sym->tag) ? sym->tag : 0; +} + + +/*------------------------------------------------------------------. +| Complain that S's WHAT is redeclared at SECOND, and was first set | +| at FIRST. | +`------------------------------------------------------------------*/ + +static void +symbol_redeclaration (symbol *s, const char *what, location first, + location second) +{ + unsigned i = 0; + complain_indent (&second, complaint, &i, + _("%s redeclaration for %s"), what, s->tag); + i += SUB_INDENT; + complain_indent (&first, complaint, &i, + _("previous declaration")); +} + +static void +semantic_type_redeclaration (semantic_type *s, const char *what, location first, + location second) +{ + unsigned i = 0; + complain_indent (&second, complaint, &i, + _("%s redeclaration for <%s>"), what, s->tag); + i += SUB_INDENT; + complain_indent (&first, complaint, &i, + _("previous declaration")); +} + + + +/*-----------------------------------------------------------------. +| Set the TYPE_NAME associated with SYM. Does nothing if passed 0 | +| as TYPE_NAME. | +`-----------------------------------------------------------------*/ + +void +symbol_type_set (symbol *sym, uniqstr type_name, location loc) +{ + if (type_name) + { + if (sym->type_name) + symbol_redeclaration (sym, "%type", sym->type_location, loc); + else + { + uniqstr_assert (type_name); + sym->type_name = type_name; + sym->type_location = loc; + } + } +} + +/*--------------------------------------------------------. +| Set the DESTRUCTOR or PRINTER associated with the SYM. | +`--------------------------------------------------------*/ + +void +symbol_code_props_set (symbol *sym, code_props_type kind, + code_props const *code) +{ + if (sym->props[kind].code) + symbol_redeclaration (sym, code_props_type_string (kind), + sym->props[kind].location, + code->location); + else + sym->props[kind] = *code; +} + +/*-----------------------------------------------------. +| Set the DESTRUCTOR or PRINTER associated with TYPE. | +`-----------------------------------------------------*/ + +void +semantic_type_code_props_set (semantic_type *type, + code_props_type kind, + code_props const *code) +{ + if (type->props[kind].code) + semantic_type_redeclaration (type, code_props_type_string (kind), + type->props[kind].location, + code->location); + else + type->props[kind] = *code; +} + +/*---------------------------------------------------. +| Get the computed %destructor or %printer for SYM. | +`---------------------------------------------------*/ + +code_props * +symbol_code_props_get (symbol *sym, code_props_type kind) +{ + /* Per-symbol code props. */ + if (sym->props[kind].code) + return &sym->props[kind]; + + /* Per-type code props. */ + if (sym->type_name) + { + code_props *code = + &semantic_type_get (sym->type_name, NULL)->props[kind]; + if (code->code) + return code; + } + + /* Apply default code props's only to user-defined symbols. */ + if (sym->tag[0] != '$' && sym != errtoken) + { + code_props *code = + &semantic_type_get (sym->type_name ? "*" : "", NULL)->props[kind]; + if (code->code) + return code; + } + return &code_props_none; +} + +/*-----------------------------------------------------------------. +| Set the PRECEDENCE associated with SYM. Does nothing if invoked | +| with UNDEF_ASSOC as ASSOC. | +`-----------------------------------------------------------------*/ + +void +symbol_precedence_set (symbol *sym, int prec, assoc a, location loc) +{ + if (a != undef_assoc) + { + if (sym->prec) + symbol_redeclaration (sym, assoc_to_string (a), sym->prec_location, + loc); + else + { + sym->prec = prec; + sym->assoc = a; + sym->prec_location = loc; + } + } + + /* Only terminals have a precedence. */ + symbol_class_set (sym, token_sym, loc, false); +} + + +/*------------------------------------. +| Set the CLASS associated with SYM. | +`------------------------------------*/ + +void +symbol_class_set (symbol *sym, symbol_class class, location loc, bool declaring) +{ + bool warned = false; + if (sym->class != unknown_sym && sym->class != class) + { + complain (&loc, complaint, _("symbol %s redefined"), sym->tag); + /* Don't report both "redefined" and "redeclared". */ + warned = true; + } + + if (class == nterm_sym && sym->class != nterm_sym) + sym->number = nvars++; + else if (class == token_sym && sym->number == NUMBER_UNDEFINED) + sym->number = ntokens++; + + sym->class = class; + + if (declaring) + { + if (sym->status == declared && !warned) + complain (&loc, Wother, _("symbol %s redeclared"), sym->tag); + else + sym->status = declared; + } +} + + +/*------------------------------------------------. +| Set the USER_TOKEN_NUMBER associated with SYM. | +`------------------------------------------------*/ + +void +symbol_user_token_number_set (symbol *sym, int user_token_number, location loc) +{ + int *user_token_numberp; + + if (sym->user_token_number != USER_NUMBER_HAS_STRING_ALIAS) + user_token_numberp = &sym->user_token_number; + else + user_token_numberp = &sym->alias->user_token_number; + if (*user_token_numberp != USER_NUMBER_UNDEFINED + && *user_token_numberp != user_token_number) + complain (&loc, complaint, _("redefining user token number of %s"), + sym->tag); + + *user_token_numberp = user_token_number; + /* User defined $end token? */ + if (user_token_number == 0) + { + endtoken = sym; + /* It is always mapped to 0, so it was already counted in + NTOKENS. */ + if (endtoken->number != NUMBER_UNDEFINED) + --ntokens; + endtoken->number = 0; + } +} + + +/*----------------------------------------------------------. +| If SYM is not defined, report an error, and consider it a | +| nonterminal. | +`----------------------------------------------------------*/ + +static inline bool +symbol_check_defined (symbol *sym) +{ + if (sym->class == unknown_sym) + { + assert (sym->status != declared); + complain (&sym->location, + sym->status == needed ? complaint : Wother, + _("symbol %s is used, but is not defined as a token" + " and has no rules"), + sym->tag); + sym->class = nterm_sym; + sym->number = nvars++; + } + + { + int i; + for (i = 0; i < 2; ++i) + symbol_code_props_get (sym, i)->is_used = true; + } + + /* Set the semantic type status associated to the current symbol to + 'declared' so that we could check semantic types unnecessary uses. */ + if (sym->type_name) + { + semantic_type *sem_type = semantic_type_get (sym->type_name, NULL); + if (sem_type) + sem_type->status = declared; + } + + return true; +} + +static inline bool +semantic_type_check_defined (semantic_type *sem_type) +{ + /* <*> and <> do not have to be "declared". */ + if (sem_type->status == declared + || !*sem_type->tag + || STREQ (sem_type->tag, "*")) + { + int i; + for (i = 0; i < 2; ++i) + if (sem_type->props[i].kind != CODE_PROPS_NONE + && ! sem_type->props[i].is_used) + complain (&sem_type->location, Wother, + _("useless %s for type <%s>"), + code_props_type_string (i), sem_type->tag); + } + else + complain (&sem_type->location, Wother, + _("type <%s> is used, but is not associated to any symbol"), + sem_type->tag); + + return true; +} + +static bool +symbol_check_defined_processor (void *sym, void *null ATTRIBUTE_UNUSED) +{ + return symbol_check_defined (sym); +} + +static bool +semantic_type_check_defined_processor (void *sem_type, + void *null ATTRIBUTE_UNUSED) +{ + return semantic_type_check_defined (sem_type); +} + + +void +symbol_make_alias (symbol *sym, symbol *str, location loc) +{ + if (str->alias) + complain (&loc, Wother, + _("symbol %s used more than once as a literal string"), str->tag); + else if (sym->alias) + complain (&loc, Wother, + _("symbol %s given more than one literal string"), sym->tag); + else + { + str->class = token_sym; + str->user_token_number = sym->user_token_number; + sym->user_token_number = USER_NUMBER_HAS_STRING_ALIAS; + str->alias = sym; + sym->alias = str; + str->number = sym->number; + symbol_type_set (str, sym->type_name, loc); + } +} + + +/*---------------------------------------------------------. +| Check that THIS, and its alias, have same precedence and | +| associativity. | +`---------------------------------------------------------*/ + +static inline void +symbol_check_alias_consistency (symbol *this) +{ + symbol *sym = this; + symbol *str = this->alias; + + /* Check only the symbol in the symbol-string pair. */ + if (!(this->alias + && this->user_token_number == USER_NUMBER_HAS_STRING_ALIAS)) + return; + + if (str->type_name != sym->type_name) + { + if (str->type_name) + symbol_type_set (sym, str->type_name, str->type_location); + else + symbol_type_set (str, sym->type_name, sym->type_location); + } + + + { + int i; + for (i = 0; i < CODE_PROPS_SIZE; ++i) + if (str->props[i].code) + symbol_code_props_set (sym, i, &str->props[i]); + else if (sym->props[i].code) + symbol_code_props_set (str, i, &sym->props[i]); + } + + if (sym->prec || str->prec) + { + if (str->prec) + symbol_precedence_set (sym, str->prec, str->assoc, + str->prec_location); + else + symbol_precedence_set (str, sym->prec, sym->assoc, + sym->prec_location); + } +} + +static bool +symbol_check_alias_consistency_processor (void *this, + void *null ATTRIBUTE_UNUSED) +{ + symbol_check_alias_consistency (this); + return true; +} + + +/*-------------------------------------------------------------------. +| Assign a symbol number, and write the definition of the token name | +| into FDEFINES. Put in SYMBOLS. | +`-------------------------------------------------------------------*/ + +static inline bool +symbol_pack (symbol *this) +{ + aver (this->number != NUMBER_UNDEFINED); + if (this->class == nterm_sym) + this->number += ntokens; + else if (this->user_token_number == USER_NUMBER_HAS_STRING_ALIAS) + return true; + + symbols[this->number] = this; + return true; +} + +static bool +symbol_pack_processor (void *this, void *null ATTRIBUTE_UNUSED) +{ + return symbol_pack (this); +} + + +static void +user_token_number_redeclaration (int num, symbol *first, symbol *second) +{ + unsigned i = 0; + /* User token numbers are not assigned during the parsing, but in a + second step, via a traversal of the symbol table sorted on tag. + + However, error messages make more sense if we keep the first + declaration first. */ + if (location_cmp (first->location, second->location) > 0) + { + symbol* tmp = first; + first = second; + second = tmp; + } + complain_indent (&second->location, complaint, &i, + _("user token number %d redeclaration for %s"), + num, second->tag); + i += SUB_INDENT; + complain_indent (&first->location, complaint, &i, + _("previous declaration for %s"), + first->tag); +} + +/*--------------------------------------------------. +| Put THIS in TOKEN_TRANSLATIONS if it is a token. | +`--------------------------------------------------*/ + +static inline bool +symbol_translation (symbol *this) +{ + /* Non-terminal? */ + if (this->class == token_sym + && this->user_token_number != USER_NUMBER_HAS_STRING_ALIAS) + { + /* A token which translation has already been set? */ + if (token_translations[this->user_token_number] != undeftoken->number) + user_token_number_redeclaration + (this->user_token_number, + symbols[token_translations[this->user_token_number]], + this); + else + token_translations[this->user_token_number] = this->number; + } + + return true; +} + +static bool +symbol_translation_processor (void *this, void *null ATTRIBUTE_UNUSED) +{ + return symbol_translation (this); +} + + +/*---------------------------------------. +| Symbol and semantic type hash tables. | +`---------------------------------------*/ + +/* Initial capacity of symbol and semantic type hash table. */ +#define HT_INITIAL_CAPACITY 257 + +static struct hash_table *symbol_table = NULL; +static struct hash_table *semantic_type_table = NULL; + +static inline bool +hash_compare_symbol (const symbol *m1, const symbol *m2) +{ + /* Since tags are unique, we can compare the pointers themselves. */ + return UNIQSTR_EQ (m1->tag, m2->tag); +} + +static inline bool +hash_compare_semantic_type (const semantic_type *m1, const semantic_type *m2) +{ + /* Since names are unique, we can compare the pointers themselves. */ + return UNIQSTR_EQ (m1->tag, m2->tag); +} + +static bool +hash_symbol_comparator (void const *m1, void const *m2) +{ + return hash_compare_symbol (m1, m2); +} + +static bool +hash_semantic_type_comparator (void const *m1, void const *m2) +{ + return hash_compare_semantic_type (m1, m2); +} + +static inline size_t +hash_symbol (const symbol *m, size_t tablesize) +{ + /* Since tags are unique, we can hash the pointer itself. */ + return ((uintptr_t) m->tag) % tablesize; +} + +static inline size_t +hash_semantic_type (const semantic_type *m, size_t tablesize) +{ + /* Since names are unique, we can hash the pointer itself. */ + return ((uintptr_t) m->tag) % tablesize; +} + +static size_t +hash_symbol_hasher (void const *m, size_t tablesize) +{ + return hash_symbol (m, tablesize); +} + +static size_t +hash_semantic_type_hasher (void const *m, size_t tablesize) +{ + return hash_semantic_type (m, tablesize); +} + +/*-------------------------------. +| Create the symbol hash table. | +`-------------------------------*/ + +void +symbols_new (void) +{ + symbol_table = hash_initialize (HT_INITIAL_CAPACITY, + NULL, + hash_symbol_hasher, + hash_symbol_comparator, + free); + semantic_type_table = hash_initialize (HT_INITIAL_CAPACITY, + NULL, + hash_semantic_type_hasher, + hash_semantic_type_comparator, + free); +} + + +/*----------------------------------------------------------------. +| Find the symbol named KEY, and return it. If it does not exist | +| yet, create it. | +`----------------------------------------------------------------*/ + +symbol * +symbol_from_uniqstr (const uniqstr key, location loc) +{ + symbol probe; + symbol *entry; + + probe.tag = key; + entry = hash_lookup (symbol_table, &probe); + + if (!entry) + { + /* First insertion in the hash. */ + aver (!symbols_sorted); + entry = symbol_new (key, loc); + if (!hash_insert (symbol_table, entry)) + xalloc_die (); + } + return entry; +} + + +/*-----------------------------------------------------------------------. +| Find the semantic type named KEY, and return it. If it does not exist | +| yet, create it. | +`-----------------------------------------------------------------------*/ + +semantic_type * +semantic_type_from_uniqstr (const uniqstr key, const location *loc) +{ + semantic_type probe; + semantic_type *entry; + + probe.tag = key; + entry = hash_lookup (semantic_type_table, &probe); + + if (!entry) + { + /* First insertion in the hash. */ + entry = semantic_type_new (key, loc); + if (!hash_insert (semantic_type_table, entry)) + xalloc_die (); + } + return entry; +} + + +/*----------------------------------------------------------------. +| Find the symbol named KEY, and return it. If it does not exist | +| yet, create it. | +`----------------------------------------------------------------*/ + +symbol * +symbol_get (const char *key, location loc) +{ + return symbol_from_uniqstr (uniqstr_new (key), loc); +} + + +/*-----------------------------------------------------------------------. +| Find the semantic type named KEY, and return it. If it does not exist | +| yet, create it. | +`-----------------------------------------------------------------------*/ + +semantic_type * +semantic_type_get (const char *key, const location *loc) +{ + return semantic_type_from_uniqstr (uniqstr_new (key), loc); +} + + +/*------------------------------------------------------------------. +| Generate a dummy nonterminal, whose name cannot conflict with the | +| user's names. | +`------------------------------------------------------------------*/ + +symbol * +dummy_symbol_get (location loc) +{ + /* Incremented for each generated symbol. */ + static int dummy_count = 0; + static char buf[256]; + + symbol *sym; + + sprintf (buf, "$@%d", ++dummy_count); + sym = symbol_get (buf, loc); + sym->class = nterm_sym; + sym->number = nvars++; + return sym; +} + +bool +symbol_is_dummy (const symbol *sym) +{ + return sym->tag[0] == '@' || (sym->tag[0] == '$' && sym->tag[1] == '@'); +} + +/*-------------------. +| Free the symbols. | +`-------------------*/ + +void +symbols_free (void) +{ + hash_free (symbol_table); + hash_free (semantic_type_table); + free (symbols); + free (symbols_sorted); + free (semantic_types_sorted); +} + + +/*---------------------------------------------------------------. +| Look for undefined symbols, report an error, and consider them | +| terminals. | +`---------------------------------------------------------------*/ + +static int +symbols_cmp (symbol const *a, symbol const *b) +{ + return strcmp (a->tag, b->tag); +} + +static int +symbols_cmp_qsort (void const *a, void const *b) +{ + return symbols_cmp (*(symbol * const *)a, *(symbol * const *)b); +} + +static void +symbols_do (Hash_processor processor, void *processor_data, + struct hash_table *table, symbol ***sorted) +{ + size_t count = hash_get_n_entries (table); + if (!*sorted) + { + *sorted = xnmalloc (count, sizeof **sorted); + hash_get_entries (table, (void**)*sorted, count); + qsort (*sorted, count, sizeof **sorted, symbols_cmp_qsort); + } + { + size_t i; + for (i = 0; i < count; ++i) + processor ((*sorted)[i], processor_data); + } +} + +/*--------------------------------------------------------------. +| Check that all the symbols are defined. Report any undefined | +| symbols and consider them nonterminals. | +`--------------------------------------------------------------*/ + +void +symbols_check_defined (void) +{ + symbols_do (symbol_check_defined_processor, NULL, + symbol_table, &symbols_sorted); + symbols_do (semantic_type_check_defined_processor, NULL, + semantic_type_table, &semantic_types_sorted); +} + +/*------------------------------------------------------------------. +| Set TOKEN_TRANSLATIONS. Check that no two symbols share the same | +| number. | +`------------------------------------------------------------------*/ + +static void +symbols_token_translations_init (void) +{ + bool num_256_available_p = true; + int i; + + /* Find the highest user token number, and whether 256, the POSIX + preferred user token number for the error token, is used. */ + max_user_token_number = 0; + for (i = 0; i < ntokens; ++i) + { + symbol *this = symbols[i]; + if (this->user_token_number != USER_NUMBER_UNDEFINED) + { + if (this->user_token_number > max_user_token_number) + max_user_token_number = this->user_token_number; + if (this->user_token_number == 256) + num_256_available_p = false; + } + } + + /* If 256 is not used, assign it to error, to follow POSIX. */ + if (num_256_available_p + && errtoken->user_token_number == USER_NUMBER_UNDEFINED) + errtoken->user_token_number = 256; + + /* Set the missing user numbers. */ + if (max_user_token_number < 256) + max_user_token_number = 256; + + for (i = 0; i < ntokens; ++i) + { + symbol *this = symbols[i]; + if (this->user_token_number == USER_NUMBER_UNDEFINED) + this->user_token_number = ++max_user_token_number; + if (this->user_token_number > max_user_token_number) + max_user_token_number = this->user_token_number; + } + + token_translations = xnmalloc (max_user_token_number + 1, + sizeof *token_translations); + + /* Initialize all entries for literal tokens to the internal token + number for $undefined, which represents all invalid inputs. */ + for (i = 0; i < max_user_token_number + 1; i++) + token_translations[i] = undeftoken->number; + symbols_do (symbol_translation_processor, NULL, + symbol_table, &symbols_sorted); +} + + +/*----------------------------------------------------------------. +| Assign symbol numbers, and write definition of token names into | +| FDEFINES. Set up vectors SYMBOL_TABLE, TAGS of symbols. | +`----------------------------------------------------------------*/ + +void +symbols_pack (void) +{ + symbols_do (symbol_check_alias_consistency_processor, NULL, + symbol_table, &symbols_sorted); + + symbols = xcalloc (nsyms, sizeof *symbols); + symbols_do (symbol_pack_processor, NULL, symbol_table, &symbols_sorted); + + /* Aliases leave empty slots in symbols, so remove them. */ + { + int writei; + int readi; + int nsyms_old = nsyms; + for (writei = 0, readi = 0; readi < nsyms_old; readi += 1) + { + if (symbols[readi] == NULL) + { + nsyms -= 1; + ntokens -= 1; + } + else + { + symbols[writei] = symbols[readi]; + symbols[writei]->number = writei; + if (symbols[writei]->alias) + symbols[writei]->alias->number = writei; + writei += 1; + } + } + } + symbols = xnrealloc (symbols, nsyms, sizeof *symbols); + + symbols_token_translations_init (); + + if (startsymbol->class == unknown_sym) + complain (&startsymbol_location, fatal, + _("the start symbol %s is undefined"), + startsymbol->tag); + else if (startsymbol->class == token_sym) + complain (&startsymbol_location, fatal, + _("the start symbol %s is a token"), + startsymbol->tag); +} + +/*---------------------------------. +| Initialize relation graph nodes. | +`---------------------------------*/ + +static void +init_prec_nodes (void) +{ + int i; + symgraph* s; + prec_nodes = xcalloc (nsyms, sizeof *prec_nodes); + for (i = 0; i < nsyms; ++i) + { + prec_nodes[i] = xmalloc (sizeof *prec_nodes[i]); + s = prec_nodes[i]; + s->id = i; + s->succ = 0; + s->pred = 0; + } +} + +/*----------------. +| Create a link. | +`----------------*/ + +static symgraphlink * +symgraphlink_new (graphid id, symgraphlink *next) +{ + symgraphlink *l = xmalloc (sizeof *l); + l->id = id; + l->next = next; + return l; +} + + +/*------------------------------------------------------------------. +| Register the second symbol of the precedence relation, and return | +| whether this relation is new. Use only in register_precedence. | +`------------------------------------------------------------------*/ + +static bool +register_precedence_second_symbol (symgraphlink **first, graphid sym) +{ + if (!*first || sym < (*first)->id) + *first = symgraphlink_new (sym, *first); + else + { + symgraphlink *slist = *first; + + while (slist->next && slist->next->id <= sym) + slist = slist->next; + + if (slist->id == sym) + /* Relation already present. */ + return false; + + slist->next = symgraphlink_new (sym, slist->next); + } + return true; +} + +/*------------------------------------------------------------------. +| Register a new relation between symbols as used. The first symbol | +| has a greater precedence than the second one. | +`------------------------------------------------------------------*/ + +void +register_precedence (graphid first, graphid snd) +{ + if (!prec_nodes) + init_prec_nodes (); + register_precedence_second_symbol (&(prec_nodes[first]->succ), snd); + register_precedence_second_symbol (&(prec_nodes[snd]->pred), first); +} + + +/*---------------------------------------. +| Deep clear a linked / adjacency list). | +`---------------------------------------*/ + +static void +linkedlist_free (symgraphlink *node) +{ + if (node) + { + while (node->next) + { + symgraphlink *tmp = node->next; + free (node); + node = tmp; + } + free (node); + } +} + +/*----------------------------------------------. +| Clear and destroy association tracking table. | +`----------------------------------------------*/ + +static void +assoc_free (void) +{ + int i; + for (i = 0; i < nsyms; ++i) + { + linkedlist_free (prec_nodes[i]->pred); + linkedlist_free (prec_nodes[i]->succ); + free (prec_nodes[i]); + } + free (prec_nodes); +} + +/*---------------------------------------. +| Initialize association tracking table. | +`---------------------------------------*/ + +static void +init_assoc (void) +{ + graphid i; + used_assoc = xcalloc (nsyms, sizeof *used_assoc); + for (i = 0; i < nsyms; ++i) + used_assoc[i] = false; +} + +/*------------------------------------------------------------------. +| Test if the associativity for the symbols is defined and useless. | +`------------------------------------------------------------------*/ + +static inline bool +is_assoc_useless (symbol *s) +{ + return s + && s->assoc != undef_assoc + && s->assoc != precedence_assoc + && !used_assoc[s->number]; +} + +/*-------------------------------. +| Register a used associativity. | +`-------------------------------*/ + +void +register_assoc (graphid i, graphid j) +{ + if (!used_assoc) + init_assoc (); + used_assoc[i] = true; + used_assoc[j] = true; +} + +/*--------------------------------------------------. +| Print a warning for unused precedence relations. | +`--------------------------------------------------*/ + +void +print_precedence_warnings (void) +{ + int i; + if (!prec_nodes) + init_prec_nodes (); + if (!used_assoc) + init_assoc (); + for (i = 0; i < nsyms; ++i) + { + symbol *s = symbols[i]; + if (s + && s->prec != 0 + && !prec_nodes[i]->pred + && !prec_nodes[i]->succ) + { + if (is_assoc_useless (s)) + complain (&s->prec_location, Wprecedence, + _("useless precedence and associativity for %s"), s->tag); + else if (s->assoc == precedence_assoc) + complain (&s->prec_location, Wprecedence, + _("useless precedence for %s"), s->tag); + } + else if (is_assoc_useless (s)) + complain (&s->prec_location, Wprecedence, + _("useless associativity for %s, use %%precedence"), s->tag); + } + free (used_assoc); + assoc_free (); +} diff --git a/contrib/tools/bison/src/symtab.h b/contrib/tools/bison/src/symtab.h new file mode 100644 index 0000000000..bcc749511c --- /dev/null +++ b/contrib/tools/bison/src/symtab.h @@ -0,0 +1,338 @@ +/* Definitions for symtab.c and callers, part of Bison. + + Copyright (C) 1984, 1989, 1992, 2000-2002, 2004-2013 Free Software + Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/** + * \file symtab.h + * \brief Manipulating ::symbol. + */ + +#ifndef SYMTAB_H_ +# define SYMTAB_H_ + +# include "assoc.h" +# include "location.h" +# include "scan-code.h" +# include "uniqstr.h" + +/*----------. +| Symbols. | +`----------*/ + +/** Symbol classes. */ +typedef enum +{ + unknown_sym, /**< Undefined. */ + token_sym, /**< Terminal. */ + nterm_sym /**< Non-terminal. */ +} symbol_class; + + +/** Internal token numbers. */ +typedef int symbol_number; +# define SYMBOL_NUMBER_MAXIMUM INT_MAX + + +typedef struct symbol symbol; + +/* Declaration status of a symbol. + + First, it is "undeclared". Then, if "undeclared" and used in a + %printer/%destructor, it is "used". If not "declared" but used in + a rule, it is "needed". Finally, if declared (via a rule for + nonterminals, or %token), it is "declared". + + When status are checked at the end, "declared" symbols are fine, + "used" symbols trigger warnings, otherwise it's an error. */ + +typedef enum + { + /** Used in the input file for an unknown reason (error). */ + undeclared, + /** Used by %destructor/%printer but not defined (warning). */ + used, + /** Used in the gramar (rules) but not defined (error). */ + needed, + /** Defined with %type or %token (good). */ + declared, + } status; + +typedef enum code_props_type code_props_type; +enum code_props_type + { + destructor = 0, + printer = 1, + }; + +enum { CODE_PROPS_SIZE = 2 }; + +/* When extending this structure, be sure to complete + symbol_check_alias_consistency. */ +struct symbol +{ + /** The key, name of the symbol. */ + uniqstr tag; + /** The location of its first occurrence. */ + location location; + + /** Its \c \%type. + + Beware that this is the type_name as was entered by the user, + including silly things such as "]" if she entered "%token <]> t". + Therefore, when outputting type_name to M4, be sure to escape it + into "@}". See quoted_output for instance. */ + uniqstr type_name; + + /** Its \c \%type's location. */ + location type_location; + + /** Any \c \%destructor (resp. \%printer) declared specificially for this + symbol. + + Access this field only through <tt>symbol</tt>'s interface functions. For + example, if <tt>symbol::destructor = NULL</tt> (resp. <tt>symbol::printer + = NULL</tt>), a default \c \%destructor (resp. \%printer) or a per-type + \c symbol_destructor_printer_get will compute the correct one. */ + code_props props[CODE_PROPS_SIZE]; + + symbol_number number; + location prec_location; + int prec; + assoc assoc; + int user_token_number; + + /* Points to the other in the symbol-string pair for an alias. + Special value USER_NUMBER_HAS_STRING_ALIAS in the symbol half of the + symbol-string pair for an alias. */ + symbol *alias; + symbol_class class; + status status; +}; + +/** Undefined user number. */ +# define USER_NUMBER_UNDEFINED -1 + +/* 'symbol->user_token_number == USER_NUMBER_HAS_STRING_ALIAS' means + this symbol has a literal string alias. For instance, '%token foo + "foo"' has '"foo"' numbered regularly, and 'foo' numbered as + USER_NUMBER_HAS_STRING_ALIAS. */ +# define USER_NUMBER_HAS_STRING_ALIAS -9991 + +/* Undefined internal token number. */ +# define NUMBER_UNDEFINED (-1) + +/** Fetch (or create) the symbol associated to KEY. */ +symbol *symbol_from_uniqstr (const uniqstr key, location loc); + +/** Fetch (or create) the symbol associated to KEY. */ +symbol *symbol_get (const char *key, location loc); + +/** Generate a dummy nonterminal. + + Its name cannot conflict with the user's names. */ +symbol *dummy_symbol_get (location loc); + + +/*--------------------. +| Methods on symbol. | +`--------------------*/ + +/** Print a symbol (for debugging). */ +void symbol_print (symbol const *s, FILE *f); + +/** Is this a dummy nonterminal? */ +bool symbol_is_dummy (const symbol *sym); + +/** The name of the code_props type: "\%destructor" or "\%printer". */ +char const *code_props_type_string (code_props_type kind); + +/** The name of the symbol that can be used as an identifier. + ** Consider the alias if needed. + ** Return 0 if there is none (e.g., the symbol is only defined as + ** a string). */ +uniqstr symbol_id_get (symbol const *sym); + +/** + * Make \c str the literal string alias of \c sym. Copy token number, + * symbol number, and type from \c sym to \c str. + */ +void symbol_make_alias (symbol *sym, symbol *str, location loc); + +/** Set the \c type_name associated with \c sym. + + Do nothing if passed 0 as \c type_name. */ +void symbol_type_set (symbol *sym, uniqstr type_name, location loc); + +/** Set the \c \%destructor or \c \%printer associated with \c sym. */ +void symbol_code_props_set (symbol *sym, code_props_type kind, + code_props const *destructor); + +/** Get the computed \c \%destructor or \c %printer for \c sym, which was + initialized with \c code_props_none_init if there's no \c \%destructor or + \c %printer. */ +code_props *symbol_code_props_get (symbol *sym, code_props_type kind); + +/** Set the \c precedence associated with \c sym. + + Ensure that \a symbol is a terminal. + Do nothing if invoked with \c undef_assoc as \c assoc. */ +void symbol_precedence_set (symbol *sym, int prec, assoc a, location loc); + +/** Set the \c class associated with \c sym. */ +void symbol_class_set (symbol *sym, symbol_class class, location loc, + bool declaring); + +/** Set the \c user_token_number associated with \c sym. */ +void symbol_user_token_number_set (symbol *sym, int user_number, location loc); + + + +/*------------------. +| Special symbols. | +`------------------*/ + +/** The error token. */ +extern symbol *errtoken; +/** The token for unknown tokens. */ +extern symbol *undeftoken; +/** The end of input token. */ +extern symbol *endtoken; +/** The genuine start symbol. + + $accept: start-symbol $end */ +extern symbol *accept; + +/** The user start symbol. */ +extern symbol *startsymbol; +/** The location of the \c \%start declaration. */ +extern location startsymbol_location; + + + +/*-------------------. +| Symbol Relations. | +`-------------------*/ + +/* The symbol relations are represented by a directed graph. */ + +/* The id of a node */ +typedef int graphid; + +typedef struct symgraphlink symgraphlink; + +struct symgraphlink +{ + /** The second \c symbol or group of a precedence relation. + * See \c symgraph. */ + graphid id; + + symgraphlink *next; +}; + +/* Symbol precedence graph, to store the used precedence relations between + * symbols. */ + +typedef struct symgraph symgraph; + +struct symgraph +{ + /** Identifier for the node: equal to the number of the symbol. */ + graphid id; + + /** The list of related symbols that have a smaller precedence. */ + symgraphlink *succ; + + /** The list of related symbols that have a greater precedence. */ + symgraphlink *pred; +}; + +/** Register a new precedence relation as used. */ + +void register_precedence (graphid first, graphid snd); + +/** Print a warning for each symbol whose precedence and/or associativity + * is useless. */ + +void print_precedence_warnings (void); + +/*----------------------. +| Symbol associativity | +`----------------------*/ + +void register_assoc (graphid i, graphid j); + +/*-----------------. +| Semantic types. | +`-----------------*/ + +/** A semantic type and its associated \c \%destructor and \c \%printer. + + Access the fields of this struct only through the interface functions in + this file. \sa symbol::destructor */ +typedef struct { + /** The key, name of the semantic type. */ + uniqstr tag; + + /** The location of its first occurence. */ + location location; + + /** Its status : "undeclared", "used" or "declared". + It cannot be "needed". */ + status status; + + /** Any \c %destructor and %printer declared for this + semantic type. */ + code_props props[CODE_PROPS_SIZE]; + +} semantic_type; + +/** Fetch (or create) the semantic type associated to KEY. */ +semantic_type *semantic_type_from_uniqstr (const uniqstr key, + const location *loc); + +/** Fetch (or create) the semantic type associated to KEY. */ +semantic_type *semantic_type_get (const char *key, const location *loc); + +/** Set the \c destructor or \c printer associated with \c type. */ +void semantic_type_code_props_set (semantic_type *type, + code_props_type kind, + code_props const *code); + +/*----------------------------------. +| Symbol and semantic type tables. | +`----------------------------------*/ + +/** Create the symbol and semantic type tables. */ +void symbols_new (void); + +/** Free all the memory allocated for symbols and semantic types. */ +void symbols_free (void); + +/** Check that all the symbols are defined. + + Report any undefined symbols and consider them nonterminals. */ +void symbols_check_defined (void); + +/** Sanity checks and #token_translations construction. + + Perform various sanity checks, assign symbol numbers, and set up + #token_translations. */ +void symbols_pack (void); + +#endif /* !SYMTAB_H_ */ diff --git a/contrib/tools/bison/src/system.h b/contrib/tools/bison/src/system.h new file mode 100644 index 0000000000..3267f2d24c --- /dev/null +++ b/contrib/tools/bison/src/system.h @@ -0,0 +1,261 @@ +/* System-dependent definitions for Bison. + + Copyright (C) 2000-2007, 2009-2013 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef BISON_SYSTEM_H +# define BISON_SYSTEM_H + +/* flex 2.5.31 gratutiously defines macros like INT8_MIN. But this + runs afoul of pre-C99 compilers that have <inttypes.h> or + <stdint.h>, which are included below if available. It also runs + afoul of pre-C99 compilers that define these macros in <limits.h>. */ +# if ! defined __STDC_VERSION__ || __STDC_VERSION__ < 199901 +# undef INT8_MIN +# undef INT16_MIN +# undef INT32_MIN +# undef INT8_MAX +# undef INT16_MAX +# undef UINT8_MAX +# undef INT32_MAX +# undef UINT16_MAX +# undef UINT32_MAX +# endif + +# include <limits.h> +# include <stddef.h> +# include <stdlib.h> +# include <string.h> + +# define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array)) +# define STREQ(L, R) (strcmp(L, R) == 0) +# define STRNEQ(L, R) (!STREQ(L, R)) + +/* Just like strncmp, but the second argument must be a literal string + and you don't specify the length. */ +# define STRNCMP_LIT(S, Literal) \ + strncmp (S, "" Literal "", sizeof (Literal) - 1) + +/* Whether Literal is a prefix of S. */ +# define STRPREFIX_LIT(Literal, S) \ + (STRNCMP_LIT (S, Literal) == 0) + +# include <unistd.h> +# include <inttypes.h> + +# ifndef UINTPTR_MAX +/* This isn't perfect, but it's good enough for Bison, which needs + only to hash pointers. */ +typedef size_t uintptr_t; +# endif + +/* Version mismatch. */ +# define EX_MISMATCH 63 + +/*---------. +| Gnulib. | +`---------*/ + +# include <unlocked-io.h> +# include <verify.h> +# include <xalloc.h> + + +/*-----------------. +| GCC extensions. | +`-----------------*/ + +/* Use PACIFY_CC to indicate that Code is unimportant to the logic of Bison + but that it is necessary for suppressing compiler warnings. For example, + Code might be a variable initializer that's always overwritten before the + variable is used. + + PACIFY_CC is intended to be useful only as a comment as it does not alter + Code. It is tempting to redefine PACIFY_CC so that it will suppress Code + when configuring without --enable-gcc-warnings. However, that would mean + that, for maintainers, Bison would compile with potentially less warnings + and safer logic than it would for users. Due to the overhead of M4, + suppressing Code is unlikely to offer any significant improvement in + Bison's performance anyway. */ +# define PACIFY_CC(Code) Code + +# ifndef __attribute__ +/* This feature is available in gcc versions 2.5 and later. */ +# if (! defined __GNUC__ || __GNUC__ < 2 \ + || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)) +# define __attribute__(Spec) /* empty */ +# endif +# endif + +/* The __-protected variants of 'format' and 'printf' attributes + are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) +# define __format__ format +# define __printf__ printf +# endif + +# ifndef ATTRIBUTE_NORETURN +# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) +# endif + +# ifndef ATTRIBUTE_UNUSED +# define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +# endif + + +/*------. +| NLS. | +`------*/ + +# include <locale.h> + +# include <gettext.h> +# define _(Msgid) gettext (Msgid) +# define N_(Msgid) (Msgid) + + +/*-----------. +| Booleans. | +`-----------*/ + +# include <stdbool.h> + + + +/*-------------. +| Assertions. | +`-------------*/ + +/* In the past, Bison defined aver to simply invoke abort in the case of + a failed assertion. The rationale was that <assert.h>'s assertions + were too heavyweight and could be disabled too easily. See + discussions at + <http://lists.gnu.org/archive/html/bison-patches/2006-01/msg00080.html> + <http://lists.gnu.org/archive/html/bison-patches/2006-09/msg00111.html>. + + However, normal assert output can be helpful during development and + in bug reports from users. Moreover, it's not clear now that + <assert.h>'s assertions are significantly heavyweight. Finally, if + users want to experiment with disabling assertions, it's debatable + whether it's our responsibility to stop them. See discussion + starting at + <http://lists.gnu.org/archive/html/bison-patches/2009-09/msg00013.html>. + + For now, we use assert but we call it aver throughout Bison in case + we later wish to try another scheme. +*/ +# include <assert.h> +# define aver assert + + +/*-----------. +| Obstacks. | +`-----------*/ + +# define obstack_chunk_alloc xmalloc +# define obstack_chunk_free free +# include <obstack.h> + +/* String-grow: append Str to Obs. */ + +# define obstack_sgrow(Obs, Str) \ + obstack_grow (Obs, Str, strlen (Str)) + +/* Output Str escaped for our postprocessing (i.e., escape M4 special + characters). + + For instance "[foo]" -> "@{foo@}", "$$" -> "$][$][". */ + +# define obstack_escape(Obs, Str) \ + do { \ + char const *p__; \ + for (p__ = Str; *p__; p__++) \ + switch (*p__) \ + { \ + case '$': obstack_sgrow (Obs, "$]["); break; \ + case '@': obstack_sgrow (Obs, "@@" ); break; \ + case '[': obstack_sgrow (Obs, "@{" ); break; \ + case ']': obstack_sgrow (Obs, "@}" ); break; \ + default: obstack_1grow (Obs, *p__ ); break; \ + } \ + } while (0) + + +/* Output Str both quoted for M4 (i.e., embed in [[...]]), and escaped + for our postprocessing (i.e., escape M4 special characters). If + Str is empty (or NULL), output "[]" instead of "[[]]" as it make M4 + programming easier (m4_ifval can be used). + + For instance "[foo]" -> "[[@{foo@}]]", "$$" -> "[[$][$][]]". */ + +# define obstack_quote(Obs, Str) \ + do { \ + char const* obstack_quote_p = Str; \ + if (obstack_quote_p && obstack_quote_p[0]) \ + { \ + obstack_sgrow (Obs, "[["); \ + obstack_escape (Obs, obstack_quote_p); \ + obstack_sgrow (Obs, "]]"); \ + } \ + else \ + obstack_sgrow (Obs, "[]"); \ + } while (0) + + +/* Append the ending 0, finish Obs, and return the string. */ + +# define obstack_finish0(Obs) \ + (obstack_1grow (Obs, '\0'), (char *) obstack_finish (Obs)) + + +/*-----------------------------------------. +| Extensions to use for the output files. | +`-----------------------------------------*/ + +# ifndef OUTPUT_EXT +# define OUTPUT_EXT ".output" +# endif + +# ifndef TAB_EXT +# define TAB_EXT ".tab" +# endif + + + +/*---------------------. +| Free a linked list. | +`---------------------*/ + +# define LIST_FREE(Type, List) \ + do { \ + Type *_node, *_next; \ + for (_node = List; _node; _node = _next) \ + { \ + _next = _node->next; \ + free (_node); \ + } \ + } while (0) + + +/*---------------------------------------------. +| Debugging memory allocation (must be last). | +`---------------------------------------------*/ + +# if WITH_DMALLOC +# define DMALLOC_FUNC_CHECK +# include <dmalloc.h> +# endif /* WITH_DMALLOC */ + +#endif /* ! BISON_SYSTEM_H */ diff --git a/contrib/tools/bison/src/tables.c b/contrib/tools/bison/src/tables.c new file mode 100644 index 0000000000..f06cba86b9 --- /dev/null +++ b/contrib/tools/bison/src/tables.c @@ -0,0 +1,863 @@ +/* Output the generated parsing program for Bison. + + Copyright (C) 1984, 1986, 1989, 1992, 2000-2006, 2009-2013 Free + Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include <bitsetv.h> + +#include "complain.h" +#include "conflicts.h" +#include "files.h" +#include "getargs.h" +#include "gram.h" +#include "lalr.h" +#include "muscle-tab.h" +#include "reader.h" +#include "symtab.h" +#include "tables.h" + +/* Several tables are indexed both by state and nonterminal numbers. + We call such an index a 'vector'; i.e., a vector is either a state + or a nonterminal number. + + Of course vector_number_t ought to be wide enough to contain + state_number and symbol_number. */ +typedef int vector_number; + +#if 0 /* Not currently used. */ +static inline vector_number +state_number_to_vector_number (state_number s) +{ + return s; +} +#endif + +static inline vector_number +symbol_number_to_vector_number (symbol_number sym) +{ + return state_number_as_int (nstates) + sym - ntokens; +} + +int nvectors; + + +/* FROMS and TOS are indexed by vector_number. + + If VECTOR is a nonterminal, (FROMS[VECTOR], TOS[VECTOR]) form an + array of state numbers of the non defaulted GOTO on VECTOR. + + If VECTOR is a state, TOS[VECTOR] is the array of actions to do on + the (array of) symbols FROMS[VECTOR]. + + In both cases, TALLY[VECTOR] is the size of the arrays + FROMS[VECTOR], TOS[VECTOR]; and WIDTH[VECTOR] = + (FROMS[VECTOR][SIZE] - FROMS[VECTOR][0] + 1) where SIZE = + TALLY[VECTOR]. + + FROMS therefore contains symbol_number and action_number, + TOS state_number and action_number, + TALLY sizes, + WIDTH differences of FROMS. + + Let base_number be the type of FROMS, TOS, and WIDTH. */ +#define BASE_MAXIMUM INT_MAX +#define BASE_MINIMUM INT_MIN + +static base_number **froms; +static base_number **tos; +static unsigned int **conflict_tos; +static size_t *tally; +static base_number *width; + + +/* For a given state, N = ACTROW[SYMBOL]: + + If N = 0, stands for 'run the default action'. + If N = MIN, stands for 'raise a syntax error'. + If N > 0, stands for 'shift SYMBOL and go to n'. + If N < 0, stands for 'reduce -N'. */ +typedef int action_number; +#define ACTION_NUMBER_MINIMUM INT_MIN + +static action_number *actrow; + +/* FROMS and TOS are reordered to be compressed. ORDER[VECTOR] is the + new vector number of VECTOR. We skip 'empty' vectors (i.e., + TALLY[VECTOR] = 0), and call these 'entries'. */ +static vector_number *order; +static int nentries; + +base_number *base = NULL; +/* A distinguished value of BASE, negative infinite. During the + computation equals to BASE_MINIMUM, later mapped to BASE_NINF to + keep parser tables small. */ +base_number base_ninf = 0; +static base_number *pos = NULL; + +static unsigned int *conflrow; +unsigned int *conflict_table; +unsigned int *conflict_list; +int conflict_list_cnt; +static int conflict_list_free; + +/* TABLE_SIZE is the allocated size of both TABLE and CHECK. We start + with more or less the original hard-coded value (which was + SHRT_MAX). */ +static int table_size = 32768; +base_number *table; +base_number *check; +/* The value used in TABLE to denote explicit syntax errors + (%nonassoc), a negative infinite. First defaults to ACTION_NUMBER_MINIMUM, + but in order to keep small tables, renumbered as TABLE_ERROR, which + is the smallest (non error) value minus 1. */ +base_number table_ninf = 0; +static int lowzero; +int high; + +state_number *yydefgoto; +rule_number *yydefact; + +/*-------------------------------------------------------------------. +| If TABLE, CONFLICT_TABLE, and CHECK are too small to be addressed | +| at DESIRED, grow them. TABLE[DESIRED] can be used, so the desired | +| size is at least DESIRED + 1. | +`-------------------------------------------------------------------*/ + +static void +table_grow (int desired) +{ + int old_size = table_size; + + while (table_size <= desired) + table_size *= 2; + + if (trace_flag & trace_resource) + fprintf (stderr, "growing table and check from: %d to %d\n", + old_size, table_size); + + table = xnrealloc (table, table_size, sizeof *table); + conflict_table = xnrealloc (conflict_table, table_size, + sizeof *conflict_table); + check = xnrealloc (check, table_size, sizeof *check); + + for (/* Nothing. */; old_size < table_size; ++old_size) + { + table[old_size] = 0; + conflict_table[old_size] = 0; + check[old_size] = -1; + } +} + + + + +/*-------------------------------------------------------------------. +| For GLR parsers, for each conflicted token in S, as indicated | +| by non-zero entries in CONFLROW, create a list of possible | +| reductions that are alternatives to the shift or reduction | +| currently recorded for that token in S. Store the alternative | +| reductions followed by a 0 in CONFLICT_LIST, updating | +| CONFLICT_LIST_CNT, and storing an index to the start of the list | +| back into CONFLROW. | +`-------------------------------------------------------------------*/ + +static void +conflict_row (state *s) +{ + int i, j; + reductions *reds = s->reductions; + + if (!nondeterministic_parser) + return; + + for (j = 0; j < ntokens; j += 1) + if (conflrow[j]) + { + conflrow[j] = conflict_list_cnt; + + /* Find all reductions for token J, and record all that do not + match ACTROW[J]. */ + for (i = 0; i < reds->num; i += 1) + if (bitset_test (reds->lookahead_tokens[i], j) + && (actrow[j] + != rule_number_as_item_number (reds->rules[i]->number))) + { + aver (0 < conflict_list_free); + conflict_list[conflict_list_cnt] = reds->rules[i]->number + 1; + conflict_list_cnt += 1; + conflict_list_free -= 1; + } + + /* Leave a 0 at the end. */ + aver (0 < conflict_list_free); + conflict_list[conflict_list_cnt] = 0; + conflict_list_cnt += 1; + conflict_list_free -= 1; + } +} + + +/*------------------------------------------------------------------. +| Decide what to do for each type of token if seen as the | +| lookahead in specified state. The value returned is used as the | +| default action (yydefact) for the state. In addition, ACTROW is | +| filled with what to do for each kind of token, index by symbol | +| number, with zero meaning do the default action. The value | +| ACTION_NUMBER_MINIMUM, a very negative number, means this | +| situation is an error. The parser recognizes this value | +| specially. | +| | +| This is where conflicts are resolved. The loop over lookahead | +| rules considered lower-numbered rules last, and the last rule | +| considered that likes a token gets to handle it. | +| | +| For GLR parsers, also sets CONFLROW[SYM] to an index into | +| CONFLICT_LIST iff there is an unresolved conflict (s/r or r/r) | +| with symbol SYM. The default reduction is not used for a symbol | +| that has any such conflicts. | +`------------------------------------------------------------------*/ + +static rule * +action_row (state *s) +{ + int i; + rule *default_reduction = NULL; + reductions *reds = s->reductions; + transitions *trans = s->transitions; + errs *errp = s->errs; + /* Set to nonzero to inhibit having any default reduction. */ + bool nodefault = false; + bool conflicted = false; + + for (i = 0; i < ntokens; i++) + actrow[i] = conflrow[i] = 0; + + if (reds->lookahead_tokens) + { + int j; + bitset_iterator biter; + /* loop over all the rules available here which require + lookahead (in reverse order to give precedence to the first + rule) */ + for (i = reds->num - 1; i >= 0; --i) + /* and find each token which the rule finds acceptable + to come next */ + BITSET_FOR_EACH (biter, reds->lookahead_tokens[i], j, 0) + { + /* and record this rule as the rule to use if that + token follows. */ + if (actrow[j] != 0) + { + conflicted = true; + conflrow[j] = 1; + } + actrow[j] = rule_number_as_item_number (reds->rules[i]->number); + } + } + + /* Now see which tokens are allowed for shifts in this state. For + them, record the shift as the thing to do. So shift is preferred + to reduce. */ + FOR_EACH_SHIFT (trans, i) + { + symbol_number sym = TRANSITION_SYMBOL (trans, i); + state *shift_state = trans->states[i]; + + if (actrow[sym] != 0) + { + conflicted = true; + conflrow[sym] = 1; + } + actrow[sym] = state_number_as_int (shift_state->number); + + /* Do not use any default reduction if there is a shift for + error */ + if (sym == errtoken->number) + nodefault = true; + } + + /* See which tokens are an explicit error in this state (due to + %nonassoc). For them, record ACTION_NUMBER_MINIMUM as the + action. */ + for (i = 0; i < errp->num; i++) + { + symbol *sym = errp->symbols[i]; + actrow[sym->number] = ACTION_NUMBER_MINIMUM; + } + + /* Turn off default reductions where requested by the user. See + state_lookahead_tokens_count in lalr.c to understand when states are + labeled as consistent. */ + { + char *default_reductions = + muscle_percent_define_get ("lr.default-reduction"); + if (STRNEQ (default_reductions, "most") && !s->consistent) + nodefault = true; + free (default_reductions); + } + + /* Now find the most common reduction and make it the default action + for this state. */ + + if (reds->num >= 1 && !nodefault) + { + if (s->consistent) + default_reduction = reds->rules[0]; + else + { + int max = 0; + for (i = 0; i < reds->num; i++) + { + int count = 0; + rule *r = reds->rules[i]; + symbol_number j; + + for (j = 0; j < ntokens; j++) + if (actrow[j] == rule_number_as_item_number (r->number)) + count++; + + if (count > max) + { + max = count; + default_reduction = r; + } + } + + /* GLR parsers need space for conflict lists, so we can't + default conflicted entries. For non-conflicted entries + or as long as we are not building a GLR parser, + actions that match the default are replaced with zero, + which means "use the default". */ + + if (max > 0) + { + int j; + for (j = 0; j < ntokens; j++) + if (actrow[j] + == rule_number_as_item_number (default_reduction->number) + && ! (nondeterministic_parser && conflrow[j])) + actrow[j] = 0; + } + } + } + + /* If have no default reduction, the default is an error. + So replace any action which says "error" with "use default". */ + + if (!default_reduction) + for (i = 0; i < ntokens; i++) + if (actrow[i] == ACTION_NUMBER_MINIMUM) + actrow[i] = 0; + + if (conflicted) + conflict_row (s); + + return default_reduction; +} + + +/*----------------------------------------. +| Set FROMS, TOS, TALLY and WIDTH for S. | +`----------------------------------------*/ + +static void +save_row (state_number s) +{ + symbol_number i; + + /* Number of non default actions in S. */ + size_t count = 0; + for (i = 0; i < ntokens; i++) + if (actrow[i] != 0) + count++; + + if (count) + { + /* Allocate non defaulted actions. */ + base_number *sp1 = froms[s] = xnmalloc (count, sizeof *sp1); + base_number *sp2 = tos[s] = xnmalloc (count, sizeof *sp2); + unsigned int *sp3 = conflict_tos[s] = + nondeterministic_parser ? xnmalloc (count, sizeof *sp3) : NULL; + + /* Store non defaulted actions. */ + for (i = 0; i < ntokens; i++) + if (actrow[i] != 0) + { + *sp1++ = i; + *sp2++ = actrow[i]; + if (nondeterministic_parser) + *sp3++ = conflrow[i]; + } + + tally[s] = count; + width[s] = sp1[-1] - froms[s][0] + 1; + } +} + + +/*------------------------------------------------------------------. +| Figure out the actions for the specified state, indexed by | +| lookahead token type. | +| | +| The YYDEFACT table is output now. The detailed info is saved for | +| putting into YYTABLE later. | +`------------------------------------------------------------------*/ + +static void +token_actions (void) +{ + int nconflict = nondeterministic_parser ? conflicts_total_count () : 0; + + yydefact = xnmalloc (nstates, sizeof *yydefact); + + actrow = xnmalloc (ntokens, sizeof *actrow); + conflrow = xnmalloc (ntokens, sizeof *conflrow); + + conflict_list = xnmalloc (1 + 2 * nconflict, sizeof *conflict_list); + conflict_list_free = 2 * nconflict; + conflict_list_cnt = 1; + + /* Find the rules which are reduced. */ + if (!nondeterministic_parser) + { + rule_number r; + for (r = 0; r < nrules; ++r) + rules[r].useful = false; + } + + { + state_number i; + for (i = 0; i < nstates; ++i) + { + rule *default_reduction = action_row (states[i]); + yydefact[i] = default_reduction ? default_reduction->number + 1 : 0; + save_row (i); + + /* Now that the parser was computed, we can find which rules are + really reduced, and which are not because of SR or RR + conflicts. */ + if (!nondeterministic_parser) + { + symbol_number j; + for (j = 0; j < ntokens; ++j) + if (actrow[j] < 0 && actrow[j] != ACTION_NUMBER_MINIMUM) + rules[item_number_as_rule_number (actrow[j])].useful = true; + if (yydefact[i]) + rules[yydefact[i] - 1].useful = true; + } + } + } + free (actrow); + free (conflrow); +} + + +/*------------------------------------------------------------------. +| Compute FROMS[VECTOR], TOS[VECTOR], TALLY[VECTOR], WIDTH[VECTOR], | +| i.e., the information related to non defaulted GOTO on the nterm | +| SYM. | +| | +| DEFAULT_STATE is the principal destination on SYM, i.e., the | +| default GOTO destination on SYM. | +`------------------------------------------------------------------*/ + +static void +save_column (symbol_number sym, state_number default_state) +{ + goto_number i; + goto_number begin = goto_map[sym - ntokens]; + goto_number end = goto_map[sym - ntokens + 1]; + + /* Number of non default GOTO. */ + size_t count = 0; + for (i = begin; i < end; i++) + if (to_state[i] != default_state) + count++; + + if (count) + { + /* Allocate room for non defaulted gotos. */ + vector_number symno = symbol_number_to_vector_number (sym); + base_number *sp1 = froms[symno] = xnmalloc (count, sizeof *sp1); + base_number *sp2 = tos[symno] = xnmalloc (count, sizeof *sp2); + + /* Store the state numbers of the non defaulted gotos. */ + for (i = begin; i < end; i++) + if (to_state[i] != default_state) + { + *sp1++ = from_state[i]; + *sp2++ = to_state[i]; + } + + tally[symno] = count; + width[symno] = sp1[-1] - froms[symno][0] + 1; + } +} + + +/*----------------------------------------------------------------. +| The default state for SYM: the state which is 'the' most common | +| GOTO destination on SYM (an nterm). | +`----------------------------------------------------------------*/ + +static state_number +default_goto (symbol_number sym, size_t state_count[]) +{ + goto_number begin = goto_map[sym - ntokens]; + goto_number end = goto_map[sym - ntokens + 1]; + state_number res = -1; + + if (begin != end) + { + size_t max = 0; + goto_number i; + state_number s; + + for (s = 0; s < nstates; s++) + state_count[s] = 0; + + for (i = begin; i < end; i++) + state_count[to_state[i]]++; + + for (s = 0; s < nstates; s++) + if (max < state_count[s]) + { + max = state_count[s]; + res = s; + } + } + return res; +} + + +/*-------------------------------------------------------------------. +| Figure out what to do after reducing with each rule, depending on | +| the saved state from before the beginning of parsing the data that | +| matched this rule. | +| | +| The YYDEFGOTO table is output now. The detailed info is saved for | +| putting into YYTABLE later. | +`-------------------------------------------------------------------*/ + +static void +goto_actions (void) +{ + symbol_number i; + size_t *state_count = xnmalloc (nstates, sizeof *state_count); + yydefgoto = xnmalloc (nvars, sizeof *yydefgoto); + + /* For a given nterm I, STATE_COUNT[S] is the number of times there + is a GOTO to S on I. */ + for (i = ntokens; i < nsyms; ++i) + { + state_number default_state = default_goto (i, state_count); + save_column (i, default_state); + yydefgoto[i - ntokens] = default_state; + } + free (state_count); +} + + +/*------------------------------------------------------------------. +| Compute ORDER, a reordering of vectors, in order to decide how to | +| pack the actions and gotos information into yytable. | +`------------------------------------------------------------------*/ + +static void +sort_actions (void) +{ + int i; + + nentries = 0; + + for (i = 0; i < nvectors; i++) + if (0 < tally[i]) + { + int k; + size_t t = tally[i]; + int w = width[i]; + int j = nentries - 1; + + while (0 <= j && width[order[j]] < w) + j--; + + while (0 <= j && width[order[j]] == w && tally[order[j]] < t) + j--; + + for (k = nentries - 1; k > j; k--) + order[k + 1] = order[k]; + + order[j + 1] = i; + nentries++; + } +} + + +/* If VECTOR is a state whose actions (reflected by FROMS, TOS, TALLY + and WIDTH of VECTOR) are common to a previous state, return this + state number. + + In any other case, return -1. */ + +static state_number +matching_state (vector_number vector) +{ + vector_number i = order[vector]; + /* If VECTOR is a nterm, return -1. */ + if (i < nstates) + { + size_t t = tally[i]; + int w = width[i]; + int prev; + + /* If VECTOR has GLR conflicts, return -1 */ + if (conflict_tos[i] != NULL) + { + int j; + for (j = 0; j < t; j += 1) + if (conflict_tos[i][j] != 0) + return -1; + } + + for (prev = vector - 1; 0 <= prev; prev--) + { + vector_number j = order[prev]; + /* Given how ORDER was computed, if the WIDTH or TALLY is + different, there cannot be a matching state. */ + if (width[j] != w || tally[j] != t) + return -1; + else + { + bool match = true; + int k; + for (k = 0; match && k < t; k++) + if (tos[j][k] != tos[i][k] + || froms[j][k] != froms[i][k] + || (conflict_tos[j] != NULL && conflict_tos[j][k] != 0)) + match = false; + if (match) + return j; + } + } + } + return -1; +} + + +static base_number +pack_vector (vector_number vector) +{ + base_number res; + vector_number i = order[vector]; + size_t t = tally[i]; + base_number *from = froms[i]; + base_number *to = tos[i]; + unsigned int *conflict_to = conflict_tos[i]; + + aver (t != 0); + + for (res = lowzero - from[0]; ; res++) + { + bool ok = true; + aver (res < table_size); + { + int k; + for (k = 0; ok && k < t; k++) + { + int loc = res + state_number_as_int (from[k]); + if (table_size <= loc) + table_grow (loc); + + if (table[loc] != 0) + ok = false; + } + + if (ok) + for (k = 0; k < vector; k++) + if (pos[k] == res) + ok = false; + } + + if (ok) + { + int loc; + int k; + for (k = 0; k < t; k++) + { + loc = res + state_number_as_int (from[k]); + table[loc] = to[k]; + if (nondeterministic_parser && conflict_to != NULL) + conflict_table[loc] = conflict_to[k]; + check[loc] = from[k]; + } + + while (table[lowzero] != 0) + lowzero++; + + if (high < loc) + high = loc; + + aver (BASE_MINIMUM <= res && res <= BASE_MAXIMUM); + return res; + } + } +} + + +/*-------------------------------------------------------------. +| Remap the negative infinite in TAB from NINF to the greatest | +| possible smallest value. Return it. | +| | +| In most case this allows us to use shorts instead of ints in | +| parsers. | +`-------------------------------------------------------------*/ + +static base_number +table_ninf_remap (base_number tab[], int size, base_number ninf) +{ + base_number res = 0; + int i; + + for (i = 0; i < size; i++) + if (tab[i] < res && tab[i] != ninf) + res = tab[i]; + + --res; + + for (i = 0; i < size; i++) + if (tab[i] == ninf) + tab[i] = res; + + return res; +} + +static void +pack_table (void) +{ + int i; + + base = xnmalloc (nvectors, sizeof *base); + pos = xnmalloc (nentries, sizeof *pos); + table = xcalloc (table_size, sizeof *table); + conflict_table = xcalloc (table_size, sizeof *conflict_table); + check = xnmalloc (table_size, sizeof *check); + + lowzero = 0; + high = 0; + + for (i = 0; i < nvectors; i++) + base[i] = BASE_MINIMUM; + + for (i = 0; i < table_size; i++) + check[i] = -1; + + for (i = 0; i < nentries; i++) + { + state_number s = matching_state (i); + base_number place; + + if (s < 0) + /* A new set of state actions, or a nonterminal. */ + place = pack_vector (i); + else + /* Action of I were already coded for S. */ + place = base[s]; + + pos[i] = place; + base[order[i]] = place; + } + + /* Use the greatest possible negative infinites. */ + base_ninf = table_ninf_remap (base, nvectors, BASE_MINIMUM); + table_ninf = table_ninf_remap (table, high + 1, ACTION_NUMBER_MINIMUM); + + free (pos); +} + + + +/*-----------------------------------------------------------------. +| Compute and output yydefact, yydefgoto, yypact, yypgoto, yytable | +| and yycheck. | +`-----------------------------------------------------------------*/ + +void +tables_generate (void) +{ + int i; + + /* This is a poor way to make sure the sizes are properly + correlated. In particular the signedness is not taken into + account. But it's not useless. */ + verify (sizeof nstates <= sizeof nvectors + && sizeof nvars <= sizeof nvectors); + + nvectors = state_number_as_int (nstates) + nvars; + + froms = xcalloc (nvectors, sizeof *froms); + tos = xcalloc (nvectors, sizeof *tos); + conflict_tos = xcalloc (nvectors, sizeof *conflict_tos); + tally = xcalloc (nvectors, sizeof *tally); + width = xnmalloc (nvectors, sizeof *width); + + token_actions (); + + goto_actions (); + free (goto_map); + free (from_state); + free (to_state); + + order = xcalloc (nvectors, sizeof *order); + sort_actions (); + pack_table (); + free (order); + + free (tally); + free (width); + + for (i = 0; i < nvectors; i++) + { + free (froms[i]); + free (tos[i]); + free (conflict_tos[i]); + } + + free (froms); + free (tos); + free (conflict_tos); +} + + +/*-------------------------. +| Free the parser tables. | +`-------------------------*/ + +void +tables_free (void) +{ + free (base); + free (conflict_table); + free (conflict_list); + free (table); + free (check); + free (yydefgoto); + free (yydefact); +} diff --git a/contrib/tools/bison/src/tables.h b/contrib/tools/bison/src/tables.h new file mode 100644 index 0000000000..c631584d6e --- /dev/null +++ b/contrib/tools/bison/src/tables.h @@ -0,0 +1,141 @@ +/* Prepare the LALR and GLR parser tables. + + Copyright (C) 2002, 2004, 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef TABLES_H_ +# define TABLES_H_ + +# include "state.h" + +/* The parser tables consist of these tables. + + YYTRANSLATE = vector mapping yylex's token numbers into bison's + token numbers. + + YYTNAME = vector of string-names indexed by bison token number. + + YYTOKNUM = vector of yylex token numbers corresponding to entries + in YYTNAME. + + YYRLINE = vector of line-numbers of all rules. For yydebug + printouts. + + YYRHS = vector of items of all rules. This is exactly what RITEMS + contains. For yydebug and for semantic parser. + + YYPRHS[R] = index in YYRHS of first item for rule R. + + YYR1[R] = symbol number of symbol that rule R derives. + + YYR2[R] = number of symbols composing right hand side of rule R. + + YYSTOS[S] = the symbol number of the symbol that leads to state S. + + YYFINAL = the state number of the termination state. + + YYTABLE = a vector filled with portions for different uses, found + via YYPACT and YYPGOTO, described below. + + YYLAST ( = high) the number of the last element of YYTABLE, i.e., + sizeof (YYTABLE) - 1. + + YYCHECK = a vector indexed in parallel with YYTABLE. It indicates, + in a roundabout way, the bounds of the portion you are trying to + examine. + + Suppose that the portion of YYTABLE starts at index P and the index + to be examined within the portion is I. Then if YYCHECK[P+I] != I, + I is outside the bounds of what is actually allocated, and the + default (from YYDEFACT or YYDEFGOTO) should be used. Otherwise, + YYTABLE[P+I] should be used. + + YYDEFACT[S] = default reduction number in state s. Performed when + YYTABLE doesn't specify something else to do. Zero means the default + is an error. + + YYDEFGOTO[I] = default state to go to after a reduction of a rule + that generates variable NTOKENS + I, except when YYTABLE specifies + something else to do. + + YYPACT[S] = index in YYTABLE of the portion describing state S. + The lookahead token's number, I, is used to index that portion of + YYTABLE to find out what action to perform. + + If YYPACT[S] == YYPACT_NINF, if YYPACT[S] + I is outside the bounds + of YYTABLE (from 0 to YYLAST), or I is outside the bounds for portion + S (that is, YYCHECK[YYPACT[S] + I] != I), then the default action + (that is, YYDEFACT[S]) should be used instead of YYTABLE. Otherwise, + the value YYTABLE[YYPACT[S] + I] should be used even if + YYPACT[S] < 0. + + If the value in YYTABLE is positive, we shift the token and go to + that state. + + If the value is negative, it is minus a rule number to reduce by. + + If the value is YYTABLE_NINF, it's a syntax error. + + YYPGOTO[I] = the index in YYTABLE of the portion describing what to + do after reducing a rule that derives variable I + NTOKENS. This + portion is indexed by the parser state number, S, as of before the + text for this nonterminal was read. + + If YYPGOTO[I] + S is outside the bounds of YYTABLE (from 0 to YYLAST) + or if S is outside the bounds of the portion for I (that is, + YYCHECK[YYPGOTO[I] + S] != S), then the default state (that is, + YYDEFGOTO[I]) should be used instead of YYTABLE. Otherwise, + YYTABLE[YYPGOTO[I] + S] is the state to go to even if YYPGOTO[I] < 0. + + When the above YYPACT, YYPGOTO, and YYCHECK tests determine that a + value from YYTABLE should be used, that value is never zero, so it is + useless to check for zero. When those tests indicate that the value + from YYDEFACT or YYDEFGOTO should be used instead, the value from + YYTABLE *might* be zero, which, as a consequence of the way in which + the tables are constructed, also happens to indicate that YYDEFACT or + YYDEFGOTO should be used. However, the YYTABLE value cannot be + trusted when the YYDEFACT or YYDEFGOTO value should be used. In + summary, forget about zero values in YYTABLE. +*/ + +extern int nvectors; + +typedef int base_number; +extern base_number *base; +/* A distinguished value of BASE, negative infinite. During the + computation equals to BASE_MINIMUM, later mapped to BASE_NINF to + keep parser tables small. */ +extern base_number base_ninf; + +extern unsigned int *conflict_table; +extern unsigned int *conflict_list; +extern int conflict_list_cnt; + +extern base_number *table; +extern base_number *check; +/* The value used in TABLE to denote explicit syntax errors + (%nonassoc), a negative infinite. */ +extern base_number table_ninf; + +extern state_number *yydefgoto; +extern rule_number *yydefact; +extern int high; + +void tables_generate (void); +void tables_free (void); + +#endif /* !TABLES_H_ */ diff --git a/contrib/tools/bison/src/uniqstr.c b/contrib/tools/bison/src/uniqstr.c new file mode 100644 index 0000000000..4a62e989c9 --- /dev/null +++ b/contrib/tools/bison/src/uniqstr.c @@ -0,0 +1,184 @@ +/* Keep a unique copy of strings. + + Copyright (C) 2002-2005, 2009-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include "system.h" + +#include <error.h> +#include <hash.h> +#include <quotearg.h> +#include <stdarg.h> +#include <xmalloca.h> + +#include "uniqstr.h" + +/*-----------------------. +| A uniqstr hash table. | +`-----------------------*/ + +/* Initial capacity of uniqstr hash table. */ +#define HT_INITIAL_CAPACITY 257 + +static struct hash_table *uniqstrs_table = NULL; + +/*-------------------------------------. +| Create the uniqstr for S if needed. | +`-------------------------------------*/ + +uniqstr +uniqstr_new (char const *str) +{ + uniqstr res = (uniqstr) hash_lookup (uniqstrs_table, str); + if (!res) + { + /* First insertion in the hash. */ + res = xstrdup (str); + if (!hash_insert (uniqstrs_table, res)) + xalloc_die (); + } + return res; +} + +uniqstr +uniqstr_vsprintf (char const *format, ...) +{ + va_list args; + size_t length; + char* res; + uniqstr str; + va_start (args, format); + length = vsnprintf (NULL, 0, format, args); + va_end (args); + + res = xmalloca(length + 1); + va_start (args, format); + vsprintf (res, format, args); + va_end (args); + str = uniqstr_new (res); + freea(res); + return str; +} + +/*------------------------------. +| Abort if S is not a uniqstr. | +`------------------------------*/ + +void +uniqstr_assert (char const *str) +{ + if (!hash_lookup (uniqstrs_table, str)) + { + error (0, 0, + "not a uniqstr: %s", quotearg (str)); + abort (); + } +} + + +/*--------------------. +| Print the uniqstr. | +`--------------------*/ + +static inline bool +uniqstr_print (uniqstr ustr) +{ + fprintf (stderr, "%s\n", ustr); + return true; +} + +static bool +uniqstr_print_processor (void *ustr, void *null ATTRIBUTE_UNUSED) +{ + return uniqstr_print (ustr); +} + + +int +uniqstr_cmp (uniqstr l, uniqstr r) +{ + return (l == r ? 0 + : !l ? -1 + : !r ? +1 + : strcmp (l, r)); +} + + +/*-----------------------. +| A uniqstr hash table. | +`-----------------------*/ + +static bool +hash_compare_uniqstr (void const *m1, void const *m2) +{ + return STREQ (m1, m2); +} + +static size_t +hash_uniqstr (void const *m, size_t tablesize) +{ + return hash_string (m, tablesize); +} + + +/*----------------------------. +| Create the uniqstrs table. | +`----------------------------*/ + +void +uniqstrs_new (void) +{ + uniqstrs_table = hash_initialize (HT_INITIAL_CAPACITY, + NULL, + hash_uniqstr, + hash_compare_uniqstr, + free); +} + + +/*-------------------------------------. +| Perform a task on all the uniqstrs. | +`-------------------------------------*/ + +static void +uniqstrs_do (Hash_processor processor, void *processor_data) +{ + hash_do_for_each (uniqstrs_table, processor, processor_data); +} + + +/*-----------------. +| Print them all. | +`-----------------*/ + +void +uniqstrs_print (void) +{ + uniqstrs_do (uniqstr_print_processor, NULL); +} + + +/*--------------------. +| Free the uniqstrs. | +`--------------------*/ + +void +uniqstrs_free (void) +{ + hash_free (uniqstrs_table); +} diff --git a/contrib/tools/bison/src/uniqstr.h b/contrib/tools/bison/src/uniqstr.h new file mode 100644 index 0000000000..f8e59ab24f --- /dev/null +++ b/contrib/tools/bison/src/uniqstr.h @@ -0,0 +1,103 @@ +/* Keeping a unique copy of strings. + + Copyright (C) 2002-2003, 2008-2013 Free Software Foundation, Inc. + + This file is part of Bison, the GNU Compiler Compiler. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef UNIQSTR_H_ +# define UNIQSTR_H_ + +#include "system.h" + +/*-----------------------------------------. +| Pointers to unique copies of C strings. | +`-----------------------------------------*/ + +typedef char const *uniqstr; + +/* Return the uniqstr for STR. */ +uniqstr uniqstr_new (char const *str); + +/* Return a uniqstr built by vsprintf. In order to simply concatenate + strings, use UNIQSTR_CONCAT, which is a convenient wrapper around + this function. */ +uniqstr uniqstr_vsprintf (char const *format, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); + +/* Two uniqstr values have the same value iff they are the same. */ +# define UNIQSTR_EQ(Ustr1, Ustr2) (!!((Ustr1) == (Ustr2))) + +/* Compare two uniqstr a la strcmp: negative for <, nul for =, and + positive for >. Undefined order, relies on addresses. */ +int uniqstr_cmp (uniqstr u1, uniqstr u2); + +/* Die if STR is not a uniqstr. */ +void uniqstr_assert (char const *str); + +#if 0 + // msvc still does not support __VA_ARGS__ +/*----------------. +| Concatenation. | +`----------------*/ + +/* Concatenate at most 20 strings and return a uniqstr. The goal of + this macro is to make the caller's code a little more succinct + without a trivial uniqstr_vsprintf format string to maintain + (for example, "%s%s%s") while still benefitting from gcc's type + checking. Unfortunately, because of the missing format string in the + macro invocation, the argument number reported by gcc for a bad + argument type is 1 too large. */ +# define UNIQSTR_CONCAT(...) \ + uniqstr_vsprintf (UNIQSTR_GEN_FORMAT (__VA_ARGS__, \ + "%s", "%s", "%s", "%s", "%s", \ + "%s", "%s", "%s", "%s", "%s", \ + "%s", "%s", "%s", "%s", "%s", \ + "%s", "%s", "%s", "%s", "%s"), \ + __VA_ARGS__) + +# define UNIQSTR_GEN_FORMAT(F1, F2, F3, F4, F5, \ + F6, F7, F8, F9, F10, \ + F11, F12, F13, F14, F15, \ + F16, F17, F18, F19, F20, \ + ...) \ + UNIQSTR_GEN_FORMAT_ (__VA_ARGS__, \ + "", "", "", "", "", \ + "", "", "", "", "", \ + "", "", "", "", "", \ + "", "", "", "", "") + +# define UNIQSTR_GEN_FORMAT_(F1, F2, F3, F4, F5, \ + F6, F7, F8, F9, F10, \ + F11, F12, F13, F14, F15, \ + F16, F17, F18, F19, F20, ...) \ + F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 \ + F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 + +#endif +/*--------------------. +| Table of uniqstrs. | +`--------------------*/ + +/* Create the string table. */ +void uniqstrs_new (void); + +/* Free all the memory allocated for symbols. */ +void uniqstrs_free (void); + +/* Report them all. */ +void uniqstrs_print (void); + +#endif /* ! defined UNIQSTR_H_ */ |