summaryrefslogtreecommitdiffstats
path: root/parser.y
diff options
context:
space:
mode:
Diffstat (limited to 'parser.y')
-rw-r--r--parser.y98
1 files changed, 62 insertions, 36 deletions
diff --git a/parser.y b/parser.y
index ca484e7d..be2042be 100644
--- a/parser.y
+++ b/parser.y
@@ -56,6 +56,7 @@ static val lit_char_helper(val litchars);
static val optimize_text(val text_form);
static val unquotes_occur(val quoted_form);
static val choose_quote(val quoted_form);
+static val expand_meta(val form);
static wchar_t char_from_name(const wchar_t *name);
static val parsed_spec;
@@ -91,7 +92,8 @@ static val parsed_spec;
%type <val> output_clause define_clause try_clause catch_clauses_opt
%type <val> line elems_opt elems clause_parts_h additional_parts_h
%type <val> text texts elem var var_op modifiers meta_expr vector hash
-%type <val> list exprs exprs_opt expr out_clauses out_clauses_opt out_clause
+%type <val> list exprs exprs_opt expr n_exprs n_expr
+%type <val> out_clauses out_clauses_opt out_clause
%type <val> repeat_clause repeat_parts_opt o_line
%type <val> o_elems_opt o_elems o_elem o_var rep_elem rep_parts_opt
%type <val> regex lisp_regex regexpr regbranch
@@ -347,7 +349,9 @@ elem : texts { $$ = rlcp(cons(text_s, $1), $1);
expand_forms(rest($1))),
$1);
else
- $$ = $1; }
+ $$ = rlcp(cons(sym,
+ expand_meta(rest($1))),
+ $1); }
| COLL exprs_opt ')' elems END { $$ = list(coll_s, $4, nil, $2, nao);
rl($$, num($1)); }
| COLL exprs_opt ')' elems
@@ -691,17 +695,17 @@ hash : HASH_H list { if (unquotes_occur($2))
num($1)); }
;
-list : '(' exprs ')' { $$ = rl($2, num($1)); }
+list : '(' n_exprs ')' { $$ = rl($2, num($1)); }
| '(' ')' { $$ = nil; }
- | '[' exprs ']' { $$ = rl(cons(dwim_s, $2), num($1)); }
+ | '[' n_exprs ']' { $$ = rl(cons(dwim_s, $2), num($1)); }
| '[' ']' { $$ = rl(cons(dwim_s, nil), num($1)); }
- | ',' expr { val expr = $2;
+ | ',' n_expr { val expr = $2;
if (consp(expr) && first(expr) == qquote_s)
expr = cons(quote_s, rest(expr));
$$ = rlcp(list(unquote_s, expr, nao), $2); }
- | '\'' expr { $$ = rlcp(list(choose_quote($2),
+ | '\'' n_expr { $$ = rlcp(list(choose_quote($2),
$2, nao), $2); }
- | SPLICE expr { val expr = $2;
+ | SPLICE n_expr { val expr = $2;
if (consp(expr) && first(expr) == qquote_s)
expr = cons(quote_s, rest(expr));
$$ = rlcp(list(splice_s, expr, nao), $2); }
@@ -711,18 +715,15 @@ list : '(' exprs ')' { $$ = rl($2, num($1)); }
yybadtoken(yychar, lit("DWIM expression")); }
;
-meta_expr : METAPAR exprs ')' { $$ = rlcp(cons(expr_s, expand($2)), $2); }
- | METABKT exprs ']' { $$ = rlcp(cons(expr_s,
- rlcp(expand(cons(dwim_s,
- $2)),
- $2)),
+meta_expr : METAPAR n_exprs ')' { $$ = rlcp(cons(expr_s, $2), $2); }
+ | METABKT n_exprs ']' { $$ = rlcp(cons(expr_s,
+ rlcp(cons(dwim_s, $2), $2)),
$2); }
| METAPAR ')' { $$ = rl(cons(expr_s, nil), num(lineno)); }
| METABKT ']' { $$ = rl(cons(expr_s, rl(cons(dwim_s, nil),
num(lineno))),
num(lineno)); }
- | METAQUO expr { val expnq = expand(list(choose_quote($2),
- $2, nao));
+ | METAQUO n_expr { val expnq = list(choose_quote($2), $2, nao);
val quote = rlcp(expnq, $2);
$$ = rlcp(cons(expr_s, quote), quote); }
| METAQUO error { $$ = nil;
@@ -733,33 +734,37 @@ meta_expr : METAPAR exprs ')' { $$ = rlcp(cons(expr_s, expand($2)), $2); }
yybadtoken(yychar, lit("meta expression")); }
;
-exprs : expr { $$ = rlcp(cons($1, nil), $1); }
- | expr exprs { $$ = rlcp(cons($1, $2), $1); }
- | expr '.' expr { $$ = rlcp(cons($1, $3), $1); }
- | expr DOTDOT exprs { $$ = rlcp(cons(list(cons_s, $1,
- car($3), nao),
- cdr($3)), $1); }
- ;
+exprs : n_exprs { $$ = rlcp(expand_meta($1), $1); }
+
+expr : n_expr { $$ = rlcp(expand_meta($1), $1); }
exprs_opt : exprs { $$ = $1; }
| /* empty */ { $$ = nil; }
;
-expr : SYMTOK { $$ = rl(sym_helper($1, t), num(lineno)); }
- | METANUM { $$ = cons(var_s, cons($1, nil));
- rl($$, num(lineno)); }
- | NUMBER { $$ = $1; }
- | list { $$ = $1; }
- | vector { $$ = $1; }
- | hash { $$ = $1; }
- | meta_expr { $$ = $1; }
- | lisp_regex { $$ = cons(regex_compile(rest($1), nil),
+n_exprs : n_expr { $$ = rlcp(cons($1, nil), $1); }
+ | n_expr n_exprs { $$ = rlcp(cons($1, $2), $1); }
+ | n_expr '.' n_expr { $$ = rlcp(cons($1, $3), $1); }
+ | n_expr DOTDOT n_exprs { $$ = rlcp(cons(list(cons_s, $1,
+ car($3), nao),
+ cdr($3)), $1); }
+ ;
+
+n_expr : SYMTOK { $$ = rl(sym_helper($1, t), num(lineno)); }
+ | METANUM { $$ = cons(var_s, cons($1, nil));
+ rl($$, num(lineno)); }
+ | NUMBER { $$ = $1; }
+ | list { $$ = $1; }
+ | vector { $$ = $1; }
+ | hash { $$ = $1; }
+ | meta_expr { $$ = $1; }
+ | lisp_regex { $$ = cons(regex_compile(rest($1), nil),
rest($1));
rlcp($$, $1); }
- | chrlit { $$ = rl($1, num(lineno)); }
- | strlit { $$ = $1; }
- | quasilit { $$ = $1; }
- ;
+ | chrlit { $$ = rl($1, num(lineno)); }
+ | strlit { $$ = $1; }
+ | quasilit { $$ = $1; }
+ ;
regex : '/' regexpr '/' { $$ = cons(regex_s, $2); end_of_regex();
rl($$, num(lineno)); }
@@ -771,10 +776,11 @@ regex : '/' regexpr '/' { $$ = cons(regex_s, $2); end_of_regex();
lisp_regex : HASH_SLASH regexpr '/'
{ $$ = cons(regex_s, $2); end_of_regex();
rl($$, num(lineno)); }
- | HASH_SLASH error { $$ = nil;
+ | HASH_SLASH error
+ { $$ = nil;
yybadtoken(yychar, lit("regex"));
end_of_regex(); }
- ;
+ ;
regexpr : regbranch { $$ = if3(cdr($1),
cons(compound_s, $1),
@@ -1115,6 +1121,26 @@ static val choose_quote(val quoted_form)
return unquotes_occur(quoted_form) ? qquote_s : quote_s;
}
+static val expand_meta(val form)
+{
+ if (atom(form))
+ return form;
+
+ if (car(form) == expr_s)
+ return cons(expr_s, expand(rest(form)));
+
+ {
+ list_collect_decl (out, ptail);
+
+ for (; consp(form); form = cdr(form))
+ ptail = list_collect(ptail, expand_meta(car(form)));
+
+ list_collect_nconc(ptail, form);
+
+ return out;
+ }
+}
+
val rl(val form, val lineno)
{
sethash(form_to_ln_hash, form, cons(lineno, spec_file_str));