start = ff;
}
| C_LEXICAL C_IDENT
+ /*
+ * Declaration of a name for the lexical analyser.
+ * May appear only once
+ */
{ if (!lexical) {
lexical = store(lextoken.t_string);
}
else error(linecount,"Duplicate %%lexical");
}
';'
- /*
- * Declaration of a name for the lexical analyser.
- * May appear only once
- */
+ | C_ONERROR C_IDENT
+ { if (! onerror) {
+ onerror = store(lextoken.t_string);
+ }
+ else error(linecount,"Duplicate %%onerror");
+ }
+ ';'
| action(0) { acount++; }
/*
* A global C-declaration
extern string e_noopen; /* Error message string used often */
extern int verbose; /* Level of verbosity */
extern string lexical; /* name of lexical analyser */
+extern string onerror; /* name of user error handler */
extern int ntneeded; /* ntneeded = 1 if nonterminals are included
* in the sets.
*/
}
}
i = maxptr - setptr;
- fprintf(fpars,
+ fprintf(f,
"#define LL_LEXI %s\n#define LL_SSIZE %d\n#define LL_NSETS %d\n#define LL_NTERMINALS %d\n",
lexical,
nbytes,
i > 0 ? i : 1,
ntokens);
+ if (onerror) fprintf(f,"#define LL_USERHOOK %s\n", onerror);
/* Now generate the routines that call the startsymbols */
for (st = start; st; st = st->ff_next) {
fputs(st->ff_name, f);
genpop(findindex(n->n_contains));
}
if (g_gettype(n->n_rule) == EORULE &&
- safety == getntout(n) &&
- ! g_getnpar(p)) break;
+ safety <= getntout(n) &&
+ ! g_getnpar(p)) {
+ safety = getntout(n);
+ break;
+ }
fprintf(f,"L%d_%s(\n",g_getnont(p), n->n_name);
if (g_getnpar(p)) {
controlline();
string e_noopen = "Cannot open %s";
int verbose;
string lexical;
+string onerror;
int ntneeded;
int ntprint;
# ifndef NDEBUG
%token C_PERSISTENT ;
%token C_FIRST ;
%token C_LEXICAL ;
+%token C_ONERROR ;
%token C_AVOID ;
%token C_PREFER ;
%token C_DEFAULT ;
{ "first", C_FIRST },
{ "start", C_START },
{ "lexical", C_LEXICAL },
+ { "onerror", C_ONERROR },
{ 0, 0 }
};