From c93846acd4905a20fbb1a0613954f20e34650f92 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Wed, 4 Apr 2018 23:30:12 -0700 Subject: parser: don't generate special lits outside quasiquote. The parser generates a sys:hash-lit, sys:struct-lit or sys:vector-lit whenever a hash, struct or vector literal contains unquotes. This allows the quasiquote expander to treat these objects as ordinary list structure when interpolating inside them, and then recognize these symbols and construct the implied real objects. The issue is that these literals are generated even if the unquotes occur outside of a backquote. For instance if a vector literal like #(,a) occurs out of the blue, not in any backquote, this is still a (sys:vector-lit (sys:unquote a)) and not an actual vector. The issue is compounded because this substitution takes place even if there is no actual comma or splice notation. Even the following is a sys:vector-lit: #((sys:unquote x)). In any case, it causes problems for compiled files, because such material can occur in the data vector of a compiled toplevel form. In this patch we modify the parser to keep track of the quasiquote/unquote level. The special literals are generated only when the object occurs inside a quasiquote. * parser.h (struct parser): New member, quasi_level. * parser.c (parser_common_init): Initialize the parser's new quasi_level member. * parser.y (vector, hash, struct): To decide whether to generate the special literal, don't just check whether unquotes occur in the list. Check that we are in a quasiquote, indicated by the quasiquoting level being positive. (i_expr, n_expr): Use a mid-rule actions on the quasiquote, unquote and splice rules to bump the quasiquoting level in one direction before recognizing the object, and then bump in the opposite direction when reducing the rule. (parse): Initialize quasi_level. --- parser.c | 1 + 1 file changed, 1 insertion(+) (limited to 'parser.c') diff --git a/parser.c b/parser.c index a5109a18..9d5d2577 100644 --- a/parser.c +++ b/parser.c @@ -122,6 +122,7 @@ void parser_common_init(parser_t *p) p->circ_ref_hash = nil; p->circ_count = 0; p->syntax_tree = nil; + p->quasi_level = 0; yylex_init(&yyscan); p->scanner = convert(scanner_t *, yyscan); yyset_extra(p, p->scanner); -- cgit v1.2.3