summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog25
-rw-r--r--parser.c32
-rw-r--r--parser.h14
-rw-r--r--parser.l8
-rw-r--r--parser.y21
5 files changed, 72 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index 367c2506..016c7ac4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2015-07-09 Kaz Kylheku <kaz@kylheku.com>
+
+ Parser cleanup: embed scanner in parser.
+
+ * parser.c (parser_destroy): New GC finalizer static function.
+ (parser_ops): Register parser_destroy.
+ (parser_common_init): New function, shared by parse and parse_once.
+ Initializes embedded scanner.
+ (parser_cleanup): New function, shared by parse_once and
+ parser_destroy.
+ (parser): Use parser_common_init.
+
+ * parser.h (parser_t): New member, yyscan.
+ (reset_scanner, parser_common_init): Declared.
+
+ * parser.l (reset_scanner): New function.
+
+ * parser.y (parse_once): Use parser_common_init, and
+ thus perform only a few initializations. Do not
+ define scanner as a local variable.
+ (parse): Call reset_scanner instead of
+ yylex_init since the scanner is being reused,
+ and for the same reason do not call yylex_destroy.
+ GC will do that now.
+
2015-07-08 Kaz Kylheku <kaz@kylheku.com>
Bugfix: define-modify-macro not registered for auto-loading.
diff --git a/parser.c b/parser.c
index c0f3c6da..aa85a7f4 100644
--- a/parser.c
+++ b/parser.c
@@ -64,32 +64,52 @@ static void parser_mark(val obj)
gc_mark(p->primer);
}
+static void parser_destroy(val obj)
+{
+ parser_t *p = coerce(parser_t *, obj->co.handle);
+ parser_cleanup(p);
+}
+
static struct cobj_ops parser_ops = {
eq,
cobj_print_op,
- cobj_destroy_free_op,
+ parser_destroy,
parser_mark,
cobj_hash_op,
};
-val parser(val stream, val lineno, val primer)
+void parser_common_init(parser_t *p)
{
- parser_t *p = coerce(parser_t *, chk_malloc(sizeof *p));
- val parser;
p->parser = nil;
- p->lineno = 0;
+ p->lineno = 1;
p->errors = 0;
p->stream = nil;
p->name = nil;
p->prepared_msg = nil;
p->syntax_tree = nil;
p->primer = nil;
- p->scanner = 0;
+ yylex_init(&p->yyscan);
+ p->scanner = convert(scanner_t *, p->yyscan);
+ yyset_extra(p, p->scanner);
+}
+
+void parser_cleanup(parser_t *p)
+{
+ if (p->scanner != 0)
+ yylex_destroy(p->scanner);
+}
+
+val parser(val stream, val lineno, val primer)
+{
+ parser_t *p = coerce(parser_t *, chk_malloc(sizeof *p));
+ val parser;
+ parser_common_init(p);
parser = cobj(coerce(mem_t *, p), parser_s, &parser_ops);
p->parser = parser;
p->lineno = c_num(default_arg(lineno, one));
p->stream = stream;
p->primer = primer;
+
return parser;
}
diff --git a/parser.h b/parser.h
index e6f531f2..0db10d4e 100644
--- a/parser.h
+++ b/parser.h
@@ -26,6 +26,11 @@
typedef struct yyguts_t scanner_t;
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void *yyscan_t;
+#endif
+
typedef struct {
val parser;
cnum lineno;
@@ -35,14 +40,10 @@ typedef struct {
val prepared_msg;
val syntax_tree;
val primer;
+ yyscan_t yyscan;
scanner_t *scanner;
} parser_t;
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-#define YY_TYPEDEF_YY_SCANNER_T
-typedef void *yyscan_t;
-#endif
-
extern const wchar_t *spec_file;
extern val form_to_ln_hash;
extern val parser_s;
@@ -52,6 +53,7 @@ void yyerrorf(scanner_t *scanner, val s, ...);
void yybadtoken(parser_t *, int tok, val context);
void end_of_regex(scanner_t *scanner);
void end_of_char(scanner_t *scanner);
+void reset_scanner(scanner_t *scanner);
int yylex_init(yyscan_t *pscanner);
int yylex_destroy(yyscan_t scanner);
parser_t *yyget_extra(yyscan_t scanner);
@@ -72,6 +74,8 @@ val rlcp_tree(val to, val from);
val regex_parse(val string, val error_stream);
val lisp_parse(val source, val error_stream, val error_return_val, val name);
val read_eval_stream(val stream, val error_stream, val hash_bang_support);
+void parser_common_init(parser_t *);
+void parser_cleanup(parser_t *);
val parser(val stream, val lineno, val primer);
val get_parser(val stream);
val parser_errors(val parser);
diff --git a/parser.l b/parser.l
index f7c717e8..4739dd59 100644
--- a/parser.l
+++ b/parser.l
@@ -960,6 +960,14 @@ void end_of_char(scanner_t *yyg)
yy_pop_state(yyg);
}
+void reset_scanner(scanner_t *yyg)
+{
+ while (YYSTATE != INITIAL)
+ yy_pop_state(yyg);
+
+ yy_flush_buffer(YY_CURRENT_BUFFER, yyg);
+}
+
val source_loc(val form)
{
return gethash(form_to_ln_hash, form);
diff --git a/parser.y b/parser.y
index 12324f51..de3f600d 100644
--- a/parser.y
+++ b/parser.y
@@ -1443,22 +1443,15 @@ void yybadtoken(parser_t *parser, int tok, val context)
int parse_once(val stream, val name, parser_t *parser)
{
int res;
- yyscan_t scanner;
- parser->lineno = 1;
- parser->errors = 0;
+ parser_common_init(parser);
+
parser->stream = stream;
parser->name = name;
- parser->prepared_msg = nil;
- parser->syntax_tree = nil;
- yylex_init(&scanner);
- parser->scanner = convert(scanner_t *, scanner);
-
- yyset_extra(parser, parser->scanner);
res = yyparse(parser->scanner, parser);
- yylex_destroy(parser->scanner);
+ parser_cleanup(parser);
return res;
}
@@ -1466,20 +1459,14 @@ int parse_once(val stream, val name, parser_t *parser)
int parse(parser_t *parser)
{
int res;
- yyscan_t scanner;
parser->errors = 0;
parser->prepared_msg = nil;
parser->syntax_tree = nil;
prime_parser(parser->parser);
- yylex_init(&scanner);
- parser->scanner = convert(scanner_t *, scanner);
-
- yyset_extra(parser, parser->scanner);
+ reset_scanner(parser->scanner);
res = yyparse(parser->scanner, parser);
- yylex_destroy(parser->scanner);
-
return res;
}