template/bison/yacc.c in lrama-0.5.2 vs template/bison/yacc.c in lrama-0.5.3
- old
+ new
@@ -540,10 +540,17 @@
static const <%= output.int_type_for(output.context.yytranslate) %> yytranslate[] =
{
<%= output.yytranslate %>
};
+<%- if output.error_recovery -%>
+/* YYTRANSLATE_INVERTED[SYMBOL-NUM] -- Token number corresponding to SYMBOL-NUM */
+static const <%= output.int_type_for(output.context.yytranslate_inverted) %> yytranslate_inverted[] =
+{
+<%= output.yytranslate_inverted %>
+};
+<%- end -%>
#if YYDEBUG
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const <%= output.int_type_for(output.context.yyrline) %> yyrline[] =
{
<%= output.yyrline %>
@@ -1209,13 +1216,310 @@
YY_IGNORE_MAYBE_UNINITIALIZED_END
}
+<%- if output.error_recovery -%>
+#ifndef YYMAXREPAIR
+# define YYMAXREPAIR 3
+#endif
+enum repair_type {
+ insert,
+ delete,
+ shift,
+};
+struct repair {
+ enum repair_type type;
+ yysymbol_kind_t term;
+};
+typedef struct repair repair;
+struct repairs {
+ /* For debug */
+ int id;
+ /* For breadth-first traversing */
+ struct repairs *next;
+ YYPTRDIFF_T stack_length;
+ /* Bottom of states */
+ yy_state_t *states;
+ /* Top of states */
+ yy_state_t *state;
+ /* repair length */
+ int repair_length;
+ /* */
+ struct repairs *prev_repair;
+ struct repair repair;
+};
+typedef struct repairs repairs;
+
+struct yy_term {
+ yysymbol_kind_t kind;
+ YYSTYPE value;
+ YYLTYPE location;
+};
+typedef struct yy_term yy_term;
+
+struct repair_terms {
+ int id;
+ int length;
+ yy_term terms[];
+};
+typedef struct repair_terms repair_terms;
+
+static void
+yy_error_token_initialize (yysymbol_kind_t yykind, YYSTYPE * const yyvaluep, YYLTYPE * const yylocationp<%= output.user_formals %>)
+{
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+switch (yykind)
+ {
+<%= output.symbol_actions_for_error_token -%>
+ default:
+ break;
+ }
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
+}
+
+static repair_terms *
+yy_create_repair_terms(repairs *reps)
+{
+ repairs *r = reps;
+ repair_terms *rep_terms;
+ int count = 0;
+
+ while (r->prev_repair)
+ {
+ count++;
+ r = r->prev_repair;
+ }
+
+ rep_terms = (repair_terms *) malloc (sizeof (repair_terms) + sizeof (yy_term) * count);
+ rep_terms->id = reps->id;
+ rep_terms->length = count;
+
+ r = reps;
+ while (r->prev_repair)
+ {
+ rep_terms->terms[count-1].kind = r->repair.term;
+ count--;
+ r = r->prev_repair;
+ }
+
+ return rep_terms;
+}
+
+static void
+yy_print_repairs(repairs *reps)
+{
+ repairs *r = reps;
+
+ fprintf (stderr,
+ "id: %d, repair_length: %d, repair_state: %d, prev_repair_id: %d\n",
+ reps->id, reps->repair_length, *reps->state, reps->prev_repair->id);
+
+ while (r->prev_repair)
+ {
+ fprintf (stderr, "%s ", yysymbol_name (r->repair.term));
+ r = r->prev_repair;
+ }
+
+ fprintf (stderr, "\n");
+}
+
+static void
+yy_print_repair_terms(repair_terms *rep_terms)
+{
+ for (int i = 0; i < rep_terms->length; i++)
+ fprintf (stderr, "%s ", yysymbol_name (rep_terms->terms[i].kind));
+
+ fprintf (stderr, "\n");
+}
+
+static void
+yy_free_repairs(repairs *reps)
+{
+ while (reps)
+ {
+ repairs *r = reps;
+ reps = reps->next;
+ free (r->states);
+ free (r);
+ }
+}
+
+static int
+yy_process_repairs(repairs *reps, yysymbol_kind_t token)
+{
+ int yyn;
+ int yystate = *reps->state;
+ int yylen = 0;
+ yysymbol_kind_t yytoken = token;
+
+ goto yyrecover_backup;
+
+yyrecover_newstate:
+ // TODO: check reps->stack_length
+ reps->state += 1;
+ *reps->state = (yy_state_t) yystate;
+
+
+yyrecover_backup:
+ yyn = yypact[yystate];
+ if (yypact_value_is_default (yyn))
+ goto yyrecover_default;
+
+ /* "Reading a token" */
+ if (yytoken == YYSYMBOL_YYEMPTY)
+ return 1;
+
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yyrecover_default;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yytable_value_is_error (yyn))
+ goto yyrecover_errlab;
+ yyn = -yyn;
+ goto yyrecover_reduce;
+ }
+
+ /* shift */
+ yystate = yyn;
+ yytoken = YYSYMBOL_YYEMPTY;
+ goto yyrecover_newstate;
+
+
+yyrecover_default:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyrecover_errlab;
+ goto yyrecover_reduce;
+
+
+yyrecover_reduce:
+ yylen = yyr2[yyn];
+ /* YYPOPSTACK */
+ reps->state -= yylen;
+ yylen = 0;
+
+ {
+ const int yylhs = yyr1[yyn] - YYNTOKENS;
+ const int yyi = yypgoto[yylhs] + *reps->state;
+ yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *reps->state
+ ? yytable[yyi]
+ : yydefgoto[yylhs]);
+ }
+
+ goto yyrecover_newstate;
+
+yyrecover_errlab:
+ return 0;
+}
+
+static repair_terms *
+yyrecover(yy_state_t *yyss, yy_state_t *yyssp, int yychar)
+{
+ yysymbol_kind_t yytoken = YYTRANSLATE (yychar);
+ repair_terms *rep_terms = YY_NULLPTR;
+ int count = 0;
+
+ repairs *head = (repairs *) malloc (sizeof (repairs));
+ repairs *current = head;
+ repairs *tail = head;
+ YYPTRDIFF_T stack_length = yyssp - yyss + 1;
+
+ head->id = count;
+ head->next = 0;
+ head->stack_length = stack_length;
+ head->states = (yy_state_t *) malloc (sizeof (yy_state_t) * (stack_length));
+ head->state = head->states + (yyssp - yyss);
+ YYCOPY (head->states, yyss, stack_length);
+ head->repair_length = 0;
+ head->prev_repair = 0;
+
+ stack_length = (stack_length * 2 > 100) ? (stack_length * 2) : 100;
+ count++;
+
+ while (current)
+ {
+ int yystate = *current->state;
+ int yyn = yypact[yystate];
+ /* See also: yypcontext_expected_tokens */
+ if (!yypact_value_is_default (yyn))
+ {
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ {
+ if (yyx != YYSYMBOL_YYerror)
+ {
+ if (current->repair_length + 1 > YYMAXREPAIR)
+ continue;
+
+ repairs *new = (repairs *) malloc (sizeof (repairs));
+ new->id = count;
+ new->next = 0;
+ new->stack_length = stack_length;
+ new->states = (yy_state_t *) malloc (sizeof (yy_state_t) * (stack_length));
+ new->state = new->states + (current->state - current->states);
+ YYCOPY (new->states, current->states, current->state - current->states + 1);
+ new->repair_length = current->repair_length + 1;
+ new->prev_repair = current;
+ new->repair.type = insert;
+ new->repair.term = (yysymbol_kind_t) yyx;
+
+ /* Process PDA assuming next token is yyx */
+ if (! yy_process_repairs (new, yyx))
+ {
+ free (new);
+ continue;
+ }
+
+ tail->next = new;
+ tail = new;
+ count++;
+
+ if (yyx == yytoken)
+ {
+ rep_terms = yy_create_repair_terms (current);
+ fprintf (stderr, "repair_terms found. id: %d, length: %d\n", rep_terms->id, rep_terms->length);
+ yy_print_repairs (current);
+ yy_print_repair_terms (rep_terms);
+
+ goto done;
+ }
+
+ fprintf (stderr,
+ "New repairs is enqueued. count: %d, yystate: %d, yyx: %d\n",
+ count, yystate, yyx);
+ yy_print_repairs (new);
+ }
+ }
+ }
+
+ current = current->next;
+ }
+
+done:
+
+ yy_free_repairs(head);
+
+ if (!rep_terms)
+ {
+ fprintf (stderr, "repair_terms not found\n");
+ }
+
+ return rep_terms;
+}
+<%- end -%>
+
+
+
/*----------.
| yyparse. |
`----------*/
int
@@ -1279,10 +1583,16 @@
YYSTYPE yyval;
YYLTYPE yyloc;
/* The locations where the error started and ended. */
YYLTYPE yyerror_range[3];
+<%- if output.error_recovery -%>
+ repair_terms *rep_terms = 0;
+ yy_term term_backup;
+ int rep_terms_index;
+ int yychar_backup;
+<%- end -%>
/* Buffer for error messages, and its allocated size. */
char yymsgbuf[128];
char *yymsg = yymsgbuf;
YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf;
@@ -1413,10 +1723,40 @@
if (yypact_value_is_default (yyn))
goto yydefault;
/* Not known => get a lookahead token if don't already have one. */
+<%- if output.error_recovery -%>
+ if (yychar == YYEMPTY && rep_terms)
+ {
+
+ if (rep_terms_index < rep_terms->length)
+ {
+ YYDPRINTF ((stderr, "An error recovery token is used\n"));
+ yy_term term = rep_terms->terms[rep_terms_index];
+ yytoken = term.kind;
+ yylval = term.value;
+ yylloc = term.location;
+ yychar = yytranslate_inverted[yytoken];
+ YY_SYMBOL_PRINT ("Next error recovery token is", yytoken, &yylval, &yylloc<%= output.user_args %>);
+ rep_terms_index++;
+ }
+ else
+ {
+ YYDPRINTF ((stderr, "Error recovery is completed\n"));
+ yytoken = term_backup.kind;
+ yylval = term_backup.value;
+ yylloc = term_backup.location;
+ yychar = yychar_backup;
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc<%= output.user_args %>);
+
+ free (rep_terms);
+ rep_terms = 0;
+ yychar_backup = 0;
+ }
+ }
+<%- end -%>
/* YYCHAR is either empty, or end-of-input, or a valid lookahead. */
if (yychar == YYEMPTY)
{
YYDPRINTF ((stderr, "Reading a token\n"));
yychar = yylex <%= output.yylex_formals %>;
@@ -1637,9 +1977,32 @@
/*-------------------------------------------------------------.
| yyerrlab1 -- common code for both syntax error and YYERROR. |
`-------------------------------------------------------------*/
yyerrlab1:
+<%- if output.error_recovery -%>
+ {
+ rep_terms = yyrecover (yyss, yyssp, yychar);
+ if (rep_terms)
+ {
+ for (int i = 0; i < rep_terms->length; i++)
+ {
+ yy_term *term = &rep_terms->terms[i];
+ yy_error_token_initialize (term->kind, &term->value, &term->location<%= output.user_args %>);
+ }
+
+ yychar_backup = yychar;
+ /* Can be packed into (the tail of) rep_terms? */
+ term_backup.kind = yytoken;
+ term_backup.value = yylval;
+ term_backup.location = yylloc;
+ rep_terms_index = 0;
+ yychar = YYEMPTY;
+
+ goto yybackup;
+ }
+ }
+<%- end -%>
yyerrstatus = 3; /* Each real token shifted decrements this. */
/* Pop stack until we find a state that shifts the error token. */
for (;;)
{