summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-09-06 22:50:52 -0700
committerKaz Kylheku <kaz@kylheku.com>2015-09-06 22:50:52 -0700
commitdcc75348c720acd6c2a0587bca34f7851e6c1283 (patch)
tree2eb725ccba3e27da07ad81344113ce2219377ebd
parenta17db859170976269eb79ddb0bbcbd5afabd45d7 (diff)
downloadtxr-dcc75348c720acd6c2a0587bca34f7851e6c1283.tar.gz
txr-dcc75348c720acd6c2a0587bca34f7851e6c1283.tar.bz2
txr-dcc75348c720acd6c2a0587bca34f7851e6c1283.zip
Reset flex scanner if exception thrown during read.
We must tear down and rebuild the Flex scanner, otherwise it is left in a bad state causing it to abort. * parser.c (parser_cleanup): After destroying scanner, null out the pointer. (parser_reset): Destroy the Flex scanner, and instantiate a new one in its place. (lisp_parse): Set up an unwind catch which will reset the parser if it was aborted by an exception. * parser.h (parser_reset): Declared.
-rw-r--r--parser.c23
-rw-r--r--parser.h1
2 files changed, 23 insertions, 1 deletions
diff --git a/parser.c b/parser.c
index 035291f6..37255ae0 100644
--- a/parser.c
+++ b/parser.c
@@ -120,6 +120,16 @@ void parser_cleanup(parser_t *p)
{
if (p->scanner != 0)
yylex_destroy(p->scanner);
+ p->scanner = 0;
+}
+
+void parser_reset(parser_t *p)
+{
+ yyscan_t yyscan;
+ parser_cleanup(p);
+ yylex_init(&yyscan);
+ p->scanner = convert(scanner_t *, yyscan);
+ yyset_extra(p, p->scanner);
}
val parser(val stream, val lineno)
@@ -279,6 +289,9 @@ val lisp_parse(val source_in, val error_stream, val error_return_val,
val parser = ensure_parser(input_stream);
val saved_dyn = dyn_env;
parser_t *pi = get_parser_impl(parser);
+ volatile val parsed = nil;
+
+ uw_simple_catch_begin;
dyn_env = make_env(nil, nil, dyn_env);
@@ -295,9 +308,17 @@ val lisp_parse(val source_in, val error_stream, val error_return_val,
int gc = gc_state(0);
parse(pi, if3(std_error != std_null, name, lit("")), prime_lisp);
gc_state(gc);
+ parsed = t;
+ }
+
+ uw_unwind {
+ dyn_env = saved_dyn;
+ if (!parsed) {
+ parser_reset(pi);
+ }
}
- dyn_env = saved_dyn;
+ uw_catch_end;
if (pi->errors || pi->syntax_tree == nao) {
if (missingp(error_return_val))
diff --git a/parser.h b/parser.h
index bc6a3364..efbaa351 100644
--- a/parser.h
+++ b/parser.h
@@ -86,6 +86,7 @@ int parse(parser_t *parser, val name, enum prime_parser);
val source_loc(val form);
val source_loc_str(val form, val alt);
val rlset(val form, val info);
+void parser_reset(parser_t *);
INLINE val rlcp(val to, val from)
{
return rlset(to, source_loc(from));