mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-10 04:43:03 +00:00
Initial check-in introducing experimental GLR parsing. See entry in
ChangeLog dated 2002-06-27 from Paul Hilfinger for details.
This commit is contained in:
@@ -331,12 +331,15 @@ count_sr_conflicts (state_t *state)
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------.
|
||||
| Count the number of reduce/reduce conflicts. |
|
||||
`----------------------------------------------*/
|
||||
/*----------------------------------------------------------------.
|
||||
| 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 int
|
||||
count_rr_conflicts (state_t *state)
|
||||
count_rr_conflicts (state_t *state, int one_per_token)
|
||||
{
|
||||
int i;
|
||||
int rrc_count = 0;
|
||||
@@ -353,7 +356,7 @@ count_rr_conflicts (state_t *state)
|
||||
count++;
|
||||
|
||||
if (count >= 2)
|
||||
rrc_count++;
|
||||
rrc_count += one_per_token ? 1 : count-1;
|
||||
}
|
||||
|
||||
return rrc_count;
|
||||
@@ -412,13 +415,37 @@ conflicts_output (FILE *out)
|
||||
{
|
||||
fprintf (out, _("State %d contains "), i);
|
||||
fputs (conflict_report (count_sr_conflicts (states[i]),
|
||||
count_rr_conflicts (states[i])), out);
|
||||
count_rr_conflicts (states[i], TRUE)), out);
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
int count;
|
||||
|
||||
/* Conflicts by state. */
|
||||
count = 0;
|
||||
for (i = 0; i < nstates; i++)
|
||||
if (conflicts[i])
|
||||
{
|
||||
count += count_sr_conflicts (states[i]);
|
||||
count += count_rr_conflicts (states[i], FALSE);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------.
|
||||
| Reporting the total number of conflicts. |
|
||||
@@ -442,7 +469,7 @@ conflicts_print (void)
|
||||
if (conflicts[i])
|
||||
{
|
||||
src_total += count_sr_conflicts (states[i]);
|
||||
rrc_total += count_rr_conflicts (states[i]);
|
||||
rrc_total += count_rr_conflicts (states[i], TRUE);
|
||||
}
|
||||
|
||||
src_ok = src_total == (expected_conflicts == -1 ? 0 : expected_conflicts);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
void conflicts_solve PARAMS ((void));
|
||||
void conflicts_print PARAMS ((void));
|
||||
int conflicts_total_count PARAMS ((void));
|
||||
void conflicts_output PARAMS ((FILE *out));
|
||||
void conflicts_free PARAMS ((void));
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ symbol_number_t *token_translations = NULL;
|
||||
|
||||
int max_user_token_number = 256;
|
||||
|
||||
int glr_parser = 0;
|
||||
int pure_parser = 0;
|
||||
|
||||
|
||||
@@ -249,4 +250,5 @@ grammar_free (void)
|
||||
XFREE (token_translations);
|
||||
/* Free the symbol table data structure. */
|
||||
symbols_free ();
|
||||
free_merger_functions ();
|
||||
}
|
||||
|
||||
13
src/gram.h
13
src/gram.h
@@ -68,6 +68,10 @@
|
||||
|
||||
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
|
||||
@@ -141,6 +145,9 @@ typedef struct rule_s
|
||||
/* This symbol provides both the associativity, and the precedence. */
|
||||
symbol_t *prec;
|
||||
|
||||
short dprec;
|
||||
short merger;
|
||||
|
||||
/* This symbol was attached to the rule via %prec. */
|
||||
symbol_t *precsym;
|
||||
|
||||
@@ -163,6 +170,12 @@ extern symbol_number_t *token_translations;
|
||||
extern int max_user_token_number;
|
||||
|
||||
|
||||
/* GLR_PARSER is nonzero if the input file says to use the GLR
|
||||
(Generalized LR) parser, and to output some additional
|
||||
information used by the GLR algorithm. */
|
||||
|
||||
extern int glr_parser;
|
||||
|
||||
/* PURE_PARSER is nonzero if should generate a parser that is all pure
|
||||
and reentrant. */
|
||||
|
||||
|
||||
180
src/output.c
180
src/output.c
@@ -115,14 +115,21 @@ static int nvectors;
|
||||
static int nentries;
|
||||
static short **froms = NULL;
|
||||
static short **tos = NULL;
|
||||
static unsigned int **conflict_tos = NULL;
|
||||
static short *tally = NULL;
|
||||
static short *width = NULL;
|
||||
static short *actrow = NULL;
|
||||
static short *conflrow = NULL;
|
||||
static short *state_count = NULL;
|
||||
static short *order = NULL;
|
||||
static short *base = NULL;
|
||||
static short *pos = NULL;
|
||||
|
||||
static unsigned int *conflict_table = NULL;
|
||||
static unsigned int *conflict_list = NULL;
|
||||
static int conflict_list_cnt;
|
||||
static int conflict_list_free;
|
||||
|
||||
/* TABLE_SIZE is the allocated size of both TABLE and CHECK.
|
||||
We start with the original hard-coded value: SHRT_MAX
|
||||
(yes, not USHRT_MAX). */
|
||||
@@ -157,6 +164,8 @@ table_grow (size_t desired)
|
||||
|
||||
table = XREALLOC (table, short, table_size);
|
||||
check = XREALLOC (check, short, table_size);
|
||||
if (glr_parser)
|
||||
conflict_table = XREALLOC (conflict_table, unsigned int, table_size);
|
||||
|
||||
for (/* Nothing. */; old_size < table_size; ++old_size)
|
||||
{
|
||||
@@ -278,7 +287,7 @@ prepare_tokens (void)
|
||||
|
||||
/*-------------------------------------------------------------.
|
||||
| Prepare the muscles related to the rules: rhs, prhs, r1, r2, |
|
||||
| rline. |
|
||||
| rline, dprec, merger |
|
||||
`-------------------------------------------------------------*/
|
||||
|
||||
static void
|
||||
@@ -291,6 +300,8 @@ prepare_rules (void)
|
||||
unsigned int *rline = XMALLOC (unsigned int, nrules + 1);
|
||||
symbol_number_t *r1 = XMALLOC (symbol_number_t, nrules + 1);
|
||||
unsigned int *r2 = XMALLOC (unsigned int, nrules + 1);
|
||||
short *dprec = XMALLOC (short, nrules + 1);
|
||||
short *merger = XMALLOC (short, nrules + 1);
|
||||
|
||||
for (r = 1; r < nrules + 1; ++r)
|
||||
{
|
||||
@@ -308,6 +319,10 @@ prepare_rules (void)
|
||||
rhs[i++] = -1;
|
||||
/* Line where rule was defined. */
|
||||
rline[r] = rules[r].location.first_line;
|
||||
/* Dynamic precedence (GLR) */
|
||||
dprec[r] = rules[r].dprec;
|
||||
/* Merger-function index (GLR) */
|
||||
merger[r] = rules[r].merger;
|
||||
}
|
||||
assert (i == nritems);
|
||||
|
||||
@@ -316,12 +331,16 @@ prepare_rules (void)
|
||||
muscle_insert_unsigned_int_table ("rline", rline, 0, 1, nrules + 1);
|
||||
muscle_insert_symbol_number_table ("r1", r1, 0, 1, nrules + 1);
|
||||
muscle_insert_unsigned_int_table ("r2", r2, 0, 1, nrules + 1);
|
||||
muscle_insert_short_table ("dprec", dprec, 0, 1, nrules + 1);
|
||||
muscle_insert_short_table ("merger", merger, 0, 1, nrules + 1);
|
||||
|
||||
free (rhs);
|
||||
free (prhs);
|
||||
free (rline);
|
||||
free (r1);
|
||||
free (r2);
|
||||
free (dprec);
|
||||
free (merger);
|
||||
}
|
||||
|
||||
/*--------------------------------------------.
|
||||
@@ -341,6 +360,50 @@ prepare_states (void)
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------.
|
||||
| For GLR parsers, for each conflicted token in STATE, 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 STATE. 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_t *state)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (! glr_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 < state->nlookaheads; i += 1)
|
||||
if (bitset_test (state->lookaheads[i], j)
|
||||
&& actrow[j] != -state->lookaheads_rule[i]->number)
|
||||
{
|
||||
assert (conflict_list_free > 0);
|
||||
conflict_list[conflict_list_cnt]
|
||||
= state->lookaheads_rule[i]->number;
|
||||
conflict_list_cnt += 1;
|
||||
conflict_list_free -= 1;
|
||||
}
|
||||
|
||||
/* Leave a 0 at the end */
|
||||
assert (conflict_list_free > 0);
|
||||
conflict_list_cnt += 1;
|
||||
conflict_list_free -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------.
|
||||
| Decide what to do for each type of token if seen as the lookahead |
|
||||
| token in specified state. The value returned is used as the |
|
||||
@@ -353,6 +416,11 @@ prepare_states (void)
|
||||
| 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 int
|
||||
@@ -365,9 +433,10 @@ action_row (state_t *state)
|
||||
errs *errp = state->errs;
|
||||
/* set nonzero to inhibit having any default reduction */
|
||||
int nodefault = 0;
|
||||
int conflicted = 0;
|
||||
|
||||
for (i = 0; i < ntokens; i++)
|
||||
actrow[i] = 0;
|
||||
actrow[i] = conflrow[i] = 0;
|
||||
|
||||
if (redp->nreds >= 1)
|
||||
{
|
||||
@@ -381,7 +450,11 @@ action_row (state_t *state)
|
||||
/* and record this rule as the rule to use if that
|
||||
token follows. */
|
||||
if (bitset_test (state->lookaheads[i], j))
|
||||
actrow[j] = -state->lookaheads_rule[i]->number;
|
||||
{
|
||||
if (actrow[j] != 0)
|
||||
conflicted = conflrow[j] = 1;
|
||||
actrow[j] = -state->lookaheads_rule[i]->number;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now see which tokens are allowed for shifts in this state. For
|
||||
@@ -399,6 +472,8 @@ action_row (state_t *state)
|
||||
if (ISVAR (symbol))
|
||||
break;
|
||||
|
||||
if (actrow[symbol] != 0)
|
||||
conflicted = conflrow[symbol] = 1;
|
||||
actrow[symbol] = shift_state;
|
||||
|
||||
/* Do not use any default reduction if there is a shift for
|
||||
@@ -442,18 +517,20 @@ action_row (state_t *state)
|
||||
}
|
||||
}
|
||||
|
||||
/* actions which match the default are replaced with zero,
|
||||
which means "use the default" */
|
||||
/* 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] == default_rule)
|
||||
if (actrow[j] == default_rule && ! (glr_parser && conflrow[j]))
|
||||
actrow[j] = 0;
|
||||
|
||||
default_rule = -default_rule;
|
||||
}
|
||||
default_rule = -default_rule;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,6 +542,9 @@ action_row (state_t *state)
|
||||
if (actrow[i] == SHRT_MIN)
|
||||
actrow[i] = 0;
|
||||
|
||||
if (conflicted)
|
||||
conflict_row (state);
|
||||
|
||||
return default_rule;
|
||||
}
|
||||
|
||||
@@ -477,6 +557,7 @@ save_row (int state)
|
||||
short *sp;
|
||||
short *sp1;
|
||||
short *sp2;
|
||||
unsigned int *sp3;
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < ntokens; i++)
|
||||
@@ -488,12 +569,18 @@ save_row (int state)
|
||||
|
||||
froms[state] = sp1 = sp = XCALLOC (short, count);
|
||||
tos[state] = sp2 = XCALLOC (short, count);
|
||||
if (glr_parser)
|
||||
conflict_tos[state] = sp3 = XCALLOC (unsigned int, count);
|
||||
else
|
||||
conflict_tos[state] = NULL;
|
||||
|
||||
for (i = 0; i < ntokens; i++)
|
||||
if (actrow[i] != 0)
|
||||
{
|
||||
*sp1++ = i;
|
||||
*sp2++ = actrow[i];
|
||||
if (glr_parser)
|
||||
*sp3++ = conflrow[i];
|
||||
}
|
||||
|
||||
tally[state] = count;
|
||||
@@ -513,9 +600,22 @@ static void
|
||||
token_actions (void)
|
||||
{
|
||||
size_t i;
|
||||
int nconflict = conflicts_total_count ();
|
||||
|
||||
short *yydefact = XCALLOC (short, nstates);
|
||||
|
||||
actrow = XCALLOC (short, ntokens);
|
||||
|
||||
conflrow = XCALLOC (short, ntokens);
|
||||
if (glr_parser)
|
||||
{
|
||||
conflict_list = XCALLOC (unsigned int, 1 + 2 * nconflict);
|
||||
conflict_list_free = 2 * nconflict;
|
||||
conflict_list_cnt = 1;
|
||||
}
|
||||
else
|
||||
conflict_list_free = conflict_list_cnt = 0;
|
||||
|
||||
for (i = 0; i < nstates; ++i)
|
||||
{
|
||||
yydefact[i] = action_row (states[i]);
|
||||
@@ -525,6 +625,7 @@ token_actions (void)
|
||||
muscle_insert_short_table ("defact", yydefact,
|
||||
yydefact[0], 1, nstates);
|
||||
XFREE (actrow);
|
||||
XFREE (conflrow);
|
||||
XFREE (yydefact);
|
||||
}
|
||||
|
||||
@@ -555,6 +656,28 @@ actions_output (FILE *out)
|
||||
fputs ("]])\n\n", out);
|
||||
}
|
||||
|
||||
/*--------------------------------------.
|
||||
| Output the merge functions to OUT. |
|
||||
`--------------------------------------*/
|
||||
|
||||
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: yyval = %s (*yy0, *yy1); break;\n",
|
||||
n, p->name);
|
||||
else
|
||||
fprintf (out, " case %d: yyval.%s = %s (*yy0, *yy1); break;\n",
|
||||
n, p->type, p->name);
|
||||
}
|
||||
fputs ("]])\n\n", out);
|
||||
}
|
||||
|
||||
/*---------------------------------------.
|
||||
| Output the tokens definition to OOUT. |
|
||||
@@ -844,6 +967,7 @@ pack_vector (int vector)
|
||||
int loc = 0;
|
||||
short *from = froms[i];
|
||||
short *to = tos[i];
|
||||
unsigned int *conflict_to = conflict_tos[i];
|
||||
|
||||
assert (t);
|
||||
|
||||
@@ -872,6 +996,8 @@ pack_vector (int vector)
|
||||
{
|
||||
loc = j + from[k];
|
||||
table[loc] = to[k];
|
||||
if (glr_parser && conflict_to != NULL)
|
||||
conflict_table[loc] = conflict_to[k];
|
||||
check[loc] = from[k];
|
||||
}
|
||||
|
||||
@@ -900,6 +1026,8 @@ pack_table (void)
|
||||
base = XCALLOC (short, nvectors);
|
||||
pos = XCALLOC (short, nentries);
|
||||
table = XCALLOC (short, table_size);
|
||||
if (glr_parser)
|
||||
conflict_table = XCALLOC (unsigned int, table_size);
|
||||
check = XCALLOC (short, table_size);
|
||||
|
||||
lowzero = 0;
|
||||
@@ -928,14 +1056,16 @@ pack_table (void)
|
||||
{
|
||||
XFREE (froms[i]);
|
||||
XFREE (tos[i]);
|
||||
XFREE (conflict_tos[i]);
|
||||
}
|
||||
|
||||
XFREE (froms);
|
||||
XFREE (tos);
|
||||
XFREE (conflict_tos);
|
||||
XFREE (pos);
|
||||
}
|
||||
|
||||
/* the following functions output yytable, yycheck
|
||||
/* the following functions output yytable, yycheck, yyconflp, yyconfl,
|
||||
and the vectors whose elements index the portion starts */
|
||||
|
||||
static void
|
||||
@@ -961,6 +1091,28 @@ output_table (void)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
output_conflicts (void)
|
||||
{
|
||||
/* 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
|
||||
avoid accidents by not writing them out in that case. */
|
||||
if (! glr_parser)
|
||||
return;
|
||||
|
||||
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,
|
||||
conflict_list[0], 1, conflict_list_cnt);
|
||||
|
||||
XFREE (conflict_table);
|
||||
XFREE (conflict_list);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
output_check (void)
|
||||
{
|
||||
@@ -982,6 +1134,7 @@ output_actions (void)
|
||||
|
||||
froms = XCALLOC (short *, nvectors);
|
||||
tos = XCALLOC (short *, nvectors);
|
||||
conflict_tos = XCALLOC (unsigned int *, nvectors);
|
||||
tally = XCALLOC (short, nvectors);
|
||||
width = XCALLOC (short, nvectors);
|
||||
|
||||
@@ -999,6 +1152,7 @@ output_actions (void)
|
||||
|
||||
output_base ();
|
||||
output_table ();
|
||||
output_conflicts ();
|
||||
|
||||
output_check ();
|
||||
|
||||
@@ -1084,6 +1238,7 @@ output_skeleton (void)
|
||||
fputs ("m4_init()\n", out);
|
||||
|
||||
actions_output (out);
|
||||
merger_output (out);
|
||||
token_definitions_output (out);
|
||||
symbol_destructors_output (out);
|
||||
symbol_printers_output (out);
|
||||
@@ -1140,7 +1295,12 @@ prepare (void)
|
||||
|
||||
/* Find the right skeleton file. */
|
||||
if (!skeleton)
|
||||
skeleton = "yacc.c";
|
||||
{
|
||||
if (glr_parser)
|
||||
skeleton = "glr.c";
|
||||
else
|
||||
skeleton = "yacc.c";
|
||||
}
|
||||
|
||||
/* Parse the skeleton file and output the needed parsers. */
|
||||
muscle_insert ("skeleton", skeleton);
|
||||
|
||||
652
src/parse-gram.c
652
src/parse-gram.c
File diff suppressed because it is too large
Load Diff
106
src/parse-gram.h
106
src/parse-gram.h
@@ -23,30 +23,33 @@
|
||||
PERCENT_EXPECT = 270,
|
||||
PERCENT_START = 271,
|
||||
PERCENT_PREC = 272,
|
||||
PERCENT_VERBOSE = 273,
|
||||
PERCENT_ERROR_VERBOSE = 274,
|
||||
PERCENT_OUTPUT = 275,
|
||||
PERCENT_FILE_PREFIX = 276,
|
||||
PERCENT_NAME_PREFIX = 277,
|
||||
PERCENT_DEFINE = 278,
|
||||
PERCENT_PURE_PARSER = 279,
|
||||
PERCENT_DEFINES = 280,
|
||||
PERCENT_YACC = 281,
|
||||
PERCENT_DEBUG = 282,
|
||||
PERCENT_LOCATIONS = 283,
|
||||
PERCENT_NO_LINES = 284,
|
||||
PERCENT_SKELETON = 285,
|
||||
PERCENT_TOKEN_TABLE = 286,
|
||||
TYPE = 287,
|
||||
EQUAL = 288,
|
||||
SEMICOLON = 289,
|
||||
COLON = 290,
|
||||
PIPE = 291,
|
||||
ID = 292,
|
||||
PERCENT_PERCENT = 293,
|
||||
PROLOGUE = 294,
|
||||
EPILOGUE = 295,
|
||||
BRACED_CODE = 296
|
||||
PERCENT_DPREC = 273,
|
||||
PERCENT_MERGE = 274,
|
||||
PERCENT_VERBOSE = 275,
|
||||
PERCENT_ERROR_VERBOSE = 276,
|
||||
PERCENT_OUTPUT = 277,
|
||||
PERCENT_FILE_PREFIX = 278,
|
||||
PERCENT_NAME_PREFIX = 279,
|
||||
PERCENT_DEFINE = 280,
|
||||
PERCENT_PURE_PARSER = 281,
|
||||
PERCENT_GLR_PARSER = 282,
|
||||
PERCENT_DEFINES = 283,
|
||||
PERCENT_YACC = 284,
|
||||
PERCENT_DEBUG = 285,
|
||||
PERCENT_LOCATIONS = 286,
|
||||
PERCENT_NO_LINES = 287,
|
||||
PERCENT_SKELETON = 288,
|
||||
PERCENT_TOKEN_TABLE = 289,
|
||||
TYPE = 290,
|
||||
EQUAL = 291,
|
||||
SEMICOLON = 292,
|
||||
COLON = 293,
|
||||
PIPE = 294,
|
||||
ID = 295,
|
||||
PERCENT_PERCENT = 296,
|
||||
PROLOGUE = 297,
|
||||
EPILOGUE = 298,
|
||||
BRACED_CODE = 299
|
||||
};
|
||||
# endif
|
||||
/* POSIX requires `int' for tokens in interfaces. */
|
||||
@@ -68,30 +71,33 @@
|
||||
#define PERCENT_EXPECT 270
|
||||
#define PERCENT_START 271
|
||||
#define PERCENT_PREC 272
|
||||
#define PERCENT_VERBOSE 273
|
||||
#define PERCENT_ERROR_VERBOSE 274
|
||||
#define PERCENT_OUTPUT 275
|
||||
#define PERCENT_FILE_PREFIX 276
|
||||
#define PERCENT_NAME_PREFIX 277
|
||||
#define PERCENT_DEFINE 278
|
||||
#define PERCENT_PURE_PARSER 279
|
||||
#define PERCENT_DEFINES 280
|
||||
#define PERCENT_YACC 281
|
||||
#define PERCENT_DEBUG 282
|
||||
#define PERCENT_LOCATIONS 283
|
||||
#define PERCENT_NO_LINES 284
|
||||
#define PERCENT_SKELETON 285
|
||||
#define PERCENT_TOKEN_TABLE 286
|
||||
#define TYPE 287
|
||||
#define EQUAL 288
|
||||
#define SEMICOLON 289
|
||||
#define COLON 290
|
||||
#define PIPE 291
|
||||
#define ID 292
|
||||
#define PERCENT_PERCENT 293
|
||||
#define PROLOGUE 294
|
||||
#define EPILOGUE 295
|
||||
#define BRACED_CODE 296
|
||||
#define PERCENT_DPREC 273
|
||||
#define PERCENT_MERGE 274
|
||||
#define PERCENT_VERBOSE 275
|
||||
#define PERCENT_ERROR_VERBOSE 276
|
||||
#define PERCENT_OUTPUT 277
|
||||
#define PERCENT_FILE_PREFIX 278
|
||||
#define PERCENT_NAME_PREFIX 279
|
||||
#define PERCENT_DEFINE 280
|
||||
#define PERCENT_PURE_PARSER 281
|
||||
#define PERCENT_GLR_PARSER 282
|
||||
#define PERCENT_DEFINES 283
|
||||
#define PERCENT_YACC 284
|
||||
#define PERCENT_DEBUG 285
|
||||
#define PERCENT_LOCATIONS 286
|
||||
#define PERCENT_NO_LINES 287
|
||||
#define PERCENT_SKELETON 288
|
||||
#define PERCENT_TOKEN_TABLE 289
|
||||
#define TYPE 290
|
||||
#define EQUAL 291
|
||||
#define SEMICOLON 292
|
||||
#define COLON 293
|
||||
#define PIPE 294
|
||||
#define ID 295
|
||||
#define PERCENT_PERCENT 296
|
||||
#define PROLOGUE 297
|
||||
#define EPILOGUE 298
|
||||
#define BRACED_CODE 299
|
||||
|
||||
|
||||
|
||||
@@ -105,8 +111,8 @@ typedef union {
|
||||
char *string;
|
||||
associativity assoc;
|
||||
} yystype;
|
||||
/* Line 1331 of /usr/local/share/bison/bison.simple. */
|
||||
#line 110 "y.tab.h"
|
||||
/* Line 1343 of /home/cs/hilfingr/work/grammars/glr2/install/share/bison/yacc.c. */
|
||||
#line 116 "y.tab.h"
|
||||
# define YYSTYPE yystype
|
||||
#endif
|
||||
|
||||
|
||||
@@ -114,6 +114,8 @@ braced_code_t current_braced_code = action_braced_code;
|
||||
%token PERCENT_EXPECT "%expect"
|
||||
%token PERCENT_START "%start"
|
||||
%token PERCENT_PREC "%prec"
|
||||
%token PERCENT_DPREC "%dprec"
|
||||
%token PERCENT_MERGE "%merge"
|
||||
%token PERCENT_VERBOSE "%verbose"
|
||||
%token PERCENT_ERROR_VERBOSE "%error-verbose"
|
||||
|
||||
@@ -123,6 +125,7 @@ braced_code_t current_braced_code = action_braced_code;
|
||||
|
||||
%token PERCENT_DEFINE "%define"
|
||||
%token PERCENT_PURE_PARSER "%pure-parser"
|
||||
%token PERCENT_GLR_PARSER "%glr-parser"
|
||||
|
||||
%token PERCENT_DEFINES "%defines"
|
||||
|
||||
@@ -184,6 +187,7 @@ declaration:
|
||||
| "%no-lines" { no_lines_flag = 1; }
|
||||
| "%output" "=" string_content { spec_outfile = $3; }
|
||||
| "%pure-parser" { pure_parser = 1; }
|
||||
| "%glr-parser" { glr_parser = 1; }
|
||||
| "%skeleton" string_content { skeleton = $2; }
|
||||
| "%token-table" { token_table_flag = 1; }
|
||||
| "%verbose" { report_flag = 1; }
|
||||
@@ -355,6 +359,10 @@ rhs:
|
||||
{ grammar_current_rule_action_append ($2, @2); }
|
||||
| rhs "%prec" symbol
|
||||
{ grammar_current_rule_prec_set ($3, @3); }
|
||||
| rhs "%dprec" INT
|
||||
{ grammar_current_rule_dprec_set ($3, @3); }
|
||||
| rhs "%merge" TYPE
|
||||
{ grammar_current_rule_merge_set ($3, @3); }
|
||||
;
|
||||
|
||||
symbol:
|
||||
|
||||
86
src/reader.c
86
src/reader.c
@@ -37,6 +37,7 @@
|
||||
int lineno;
|
||||
static symbol_list_t *grammar = NULL;
|
||||
static int start_flag = 0;
|
||||
merger_list *merge_functions;
|
||||
|
||||
/* Nonzero if %union has been seen. */
|
||||
int typed = 0;
|
||||
@@ -105,6 +106,60 @@ epilogue_set (const char *epilogue, location_t location)
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------.
|
||||
| Return the merger index for a merging function named NAME, whose |
|
||||
| arguments have type TYPE. Records the function, if new, in |
|
||||
| merger_list. |
|
||||
`-------------------------------------------------------------------*/
|
||||
|
||||
static int
|
||||
get_merge_function (const char* name, const char* type)
|
||||
{
|
||||
merger_list *syms;
|
||||
merger_list head;
|
||||
int n;
|
||||
|
||||
if (! glr_parser)
|
||||
return 0;
|
||||
|
||||
if (type == NULL)
|
||||
type = "";
|
||||
|
||||
head.next = merge_functions;
|
||||
for (syms = &head, n = 1; syms->next != NULL; syms = syms->next, n += 1)
|
||||
if (strcmp (name, syms->next->name) == 0)
|
||||
break;
|
||||
if (syms->next == NULL) {
|
||||
syms->next = XMALLOC (merger_list, 1);
|
||||
syms->next->name = strdup (name);
|
||||
syms->next->type = strdup (type);
|
||||
syms->next->next = NULL;
|
||||
merge_functions = head.next;
|
||||
} else if (strcmp (type, syms->next->type) != 0)
|
||||
warn (_("result type clash on merge function %s: `%s' vs. `%s'"),
|
||||
name, type, syms->next->type);
|
||||
return n;
|
||||
}
|
||||
|
||||
/*--------------------------------------.
|
||||
| Free all merge-function definitions. |
|
||||
`--------------------------------------*/
|
||||
|
||||
void
|
||||
free_merger_functions (void)
|
||||
{
|
||||
merger_list *L0;
|
||||
if (! glr_parser)
|
||||
return;
|
||||
L0 = merge_functions;
|
||||
while (L0 != NULL)
|
||||
{
|
||||
merger_list *L1 = L0->next;
|
||||
free (L0);
|
||||
L0 = L1;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------.
|
||||
| Generate a dummy symbol, a nonterminal, whose name cannot conflict |
|
||||
| with the user's names. |
|
||||
@@ -307,6 +362,34 @@ grammar_current_rule_prec_set (symbol_t *precsym, location_t location)
|
||||
current_rule->ruleprec = precsym;
|
||||
}
|
||||
|
||||
/* Attach dynamic precedence DPREC to the current rule. */
|
||||
|
||||
void
|
||||
grammar_current_rule_dprec_set (int dprec, location_t location)
|
||||
{
|
||||
if (! glr_parser)
|
||||
warn_at (location, _("%%dprec affects only GLR parsers"));
|
||||
if (dprec <= 0)
|
||||
complain_at (location, _("%%dprec must be followed by positive number"));
|
||||
else if (current_rule->dprec != 0)
|
||||
complain_at (location, _("only one %%dprec allowed per rule"));
|
||||
current_rule->dprec = dprec;
|
||||
}
|
||||
|
||||
/* Attach a merge function NAME with argument type TYPE to current
|
||||
rule. */
|
||||
|
||||
void
|
||||
grammar_current_rule_merge_set (const char* name, location_t location)
|
||||
{
|
||||
if (! glr_parser)
|
||||
warn_at (location, _("%%merge affects only GLR parsers"));
|
||||
if (current_rule->merger != 0)
|
||||
complain_at (location, _("only one %%merge allowed per rule"));
|
||||
current_rule->merger =
|
||||
get_merge_function (name, current_rule->sym->type_name);
|
||||
}
|
||||
|
||||
/* Attach a SYMBOL to the current rule. If needed, move the previous
|
||||
action as a mid-rule action. */
|
||||
|
||||
@@ -319,7 +402,6 @@ grammar_current_rule_symbol_append (symbol_t *symbol, location_t location)
|
||||
grammar_symbol_append (symbol, location);
|
||||
}
|
||||
|
||||
|
||||
/* Attach an ACTION to the current rule. If needed, move the previous
|
||||
action as a mid-rule action. */
|
||||
|
||||
@@ -363,6 +445,8 @@ packgram (void)
|
||||
rules[ruleno].useful = TRUE;
|
||||
rules[ruleno].action = p->action;
|
||||
rules[ruleno].action_location = p->action_location;
|
||||
rules[ruleno].dprec = p->dprec;
|
||||
rules[ruleno].merger = p->merger;
|
||||
|
||||
p = p->next;
|
||||
while (p && p->sym)
|
||||
|
||||
17
src/reader.h
17
src/reader.h
@@ -24,6 +24,14 @@
|
||||
# include "symlist.h"
|
||||
# include "parse-gram.h"
|
||||
|
||||
typedef struct merger_list
|
||||
{
|
||||
struct merger_list* next;
|
||||
const char* name;
|
||||
const char* type;
|
||||
}
|
||||
merger_list;
|
||||
|
||||
typedef struct gram_control_s
|
||||
{
|
||||
int errcode;
|
||||
@@ -70,12 +78,21 @@ void grammar_rule_end PARAMS ((location_t l));
|
||||
void grammar_midrule_action PARAMS ((void));
|
||||
void grammar_current_rule_prec_set PARAMS ((symbol_t *precsym,
|
||||
location_t l));
|
||||
void grammar_current_rule_dprec_set PARAMS ((int dprec,
|
||||
location_t l));
|
||||
void grammer_current_rule_merge_set PARAMS ((const char* name,
|
||||
location_t l));
|
||||
|
||||
void grammar_current_rule_symbol_append PARAMS ((symbol_t *symbol,
|
||||
location_t l));
|
||||
void grammar_current_rule_action_append PARAMS ((const char *action,
|
||||
location_t l));
|
||||
extern symbol_list_t *current_rule;
|
||||
void reader PARAMS ((void));
|
||||
void free_merger_functions PARAMS ((void));
|
||||
|
||||
extern merger_list *merge_functions;
|
||||
|
||||
extern int typed;
|
||||
|
||||
#endif /* !READER_H_ */
|
||||
|
||||
1032
src/scan-gram.c
1032
src/scan-gram.c
File diff suppressed because it is too large
Load Diff
@@ -124,12 +124,15 @@ blanks [ \t\f]+
|
||||
"%define" return PERCENT_DEFINE;
|
||||
"%defines" return PERCENT_DEFINES;
|
||||
"%destructor" return PERCENT_DESTRUCTOR;
|
||||
"%dprec" return PERCENT_DPREC;
|
||||
"%error"[-_]"verbose" return PERCENT_ERROR_VERBOSE;
|
||||
"%expect" return PERCENT_EXPECT;
|
||||
"%file-prefix" return PERCENT_FILE_PREFIX;
|
||||
"%fixed"[-_]"output"[-_]"files" return PERCENT_YACC;
|
||||
"%glr"[-_]"parser" return PERCENT_GLR_PARSER;
|
||||
"%left" return PERCENT_LEFT;
|
||||
"%locations" return PERCENT_LOCATIONS;
|
||||
"%merge" return PERCENT_MERGE;
|
||||
"%name"[-_]"prefix" return PERCENT_NAME_PREFIX;
|
||||
"%no"[-_]"lines" return PERCENT_NO_LINES;
|
||||
"%nonassoc" return PERCENT_NONASSOC;
|
||||
|
||||
@@ -36,6 +36,8 @@ symbol_list_new (symbol_t *sym, location_t location)
|
||||
res->location = location;
|
||||
res->action = NULL;
|
||||
res->ruleprec = NULL;
|
||||
res->dprec = 0;
|
||||
res->merger = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ typedef struct symbol_list_s
|
||||
location_t action_location;
|
||||
|
||||
symbol_t *ruleprec;
|
||||
int dprec;
|
||||
int merger;
|
||||
} symbol_list_t;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user