summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--parser.y205
1 files changed, 119 insertions, 86 deletions
diff --git a/parser.y b/parser.y
index f6ed9bf8..2062669a 100644
--- a/parser.y
+++ b/parser.y
@@ -110,7 +110,7 @@ int yyparse(scanner_t *, parser_t *);
%token <chr> REGCHAR REGTOKEN LITCHAR SPLICE CONSDOT LAMBDOT
-%type <val> spec clauses_rev clauses clauses_opt clause
+%type <val> spec clauses_rev clauses_opt clause
%type <val> all_clause some_clause none_clause maybe_clause block_clause
%type <val> cases_clause choose_clause gather_clause collect_clause until_last
%type <val> collect_repeat
@@ -146,8 +146,7 @@ int yyparse(scanner_t *, parser_t *);
%%
-spec : clauses { parser->syntax_tree = $1; }
- | /* empty */ { parser->syntax_tree = nil; }
+spec : clauses_opt { parser->syntax_tree = $1; }
| SECRET_ESCAPE_R regexpr { parser->syntax_tree = $2; end_of_regex(scnr); }
| SECRET_ESCAPE_E n_expr { parser->syntax_tree = $2; YYACCEPT; }
byacc_fool { internal_error("notreached"); }
@@ -180,8 +179,6 @@ byacc_fool : n_expr { internal_error("notreached"); }
| { internal_error("notreached"); }
;
-clauses : clauses_rev { $$ = nreverse($1); }
-
clauses_rev : clause { $$ = check_for_include(cons($1, nil)); }
| clauses_rev clause { $$ = check_for_include(cons($2, $1)); }
;
@@ -208,49 +205,47 @@ clause : all_clause { $$ = cons($1, nil); rlcp($$, $1); }
| line { $$ = $1; }
;
-all_clause : ALL newl clause_parts { $$ = list(all_s, $3, nao);
+all_clause : ALL newl clause_parts { if (nilp($3))
+ yyerr("empty all clause");
+ $$ = list(all_s, $3, nao);
rl($$, num($1)); }
| ALL newl error { $$ = nil;
yybadtok(yychar, lit("all clause")); }
- | ALL newl END newl { $$ = nil;
- yyerr("empty all clause"); }
-
;
some_clause : SOME exprs_opt ')'
- newl clause_parts { $$ = list(some_s, $5, $2, nao);
+ newl clause_parts { if (nilp($5))
+ yyerr("empty some clause");
+ $$ = list(some_s, $5, $2, nao);
rl($$, num($1)); }
| SOME exprs_opt ')'
newl error
{ $$ = nil;
yybadtok(yychar, lit("some clause")); }
- | SOME exprs_opt ')'
- newl END newl { $$ = nil;
- yyerr("empty some clause"); }
;
-none_clause : NONE newl clause_parts { $$ = list(none_s, $3, nao);
+none_clause : NONE newl clause_parts { if (nilp($3))
+ yyerr("empty none clause");
+ $$ = list(none_s, $3, nao);
rl($$, num($1)); }
| NONE newl error { $$ = nil;
yybadtok(yychar, lit("none clause")); }
- | NONE newl END newl { $$ = nil;
- yyerr("empty none clause"); }
;
-maybe_clause : MAYBE newl clause_parts { $$ = list(maybe_s, $3, nao);
+maybe_clause : MAYBE newl clause_parts { if (nilp($3))
+ yyerr("empty maybe clause");
+ $$ = list(maybe_s, $3, nao);
rl($$, num($1)); }
| MAYBE newl error { $$ = nil;
yybadtok(yychar, lit("maybe clause")); }
- | MAYBE newl END newl { $$ = nil;
- yyerr("empty maybe clause"); }
;
-cases_clause : CASES newl clause_parts { $$ = list(cases_s, $3, nao);
+cases_clause : CASES newl clause_parts { if (nilp($3))
+ yyerr("empty cases clause");
+ $$ = list(cases_s, $3, nao);
rl($$, num($1)); }
| CASES newl error { $$ = nil;
yybadtok(yychar, lit("cases clause")); }
- | CASES newl END newl { $$ = nil;
- yyerr("empty cases clause"); }
;
block_clause : BLOCK exprs_opt ')'
@@ -270,19 +265,20 @@ block_clause : BLOCK exprs_opt ')'
;
choose_clause : CHOOSE exprs_opt ')'
- newl clause_parts { $$ = list(choose_s, $5, $2, nao);
+ newl clause_parts { if (nilp($5))
+ yyerr("empty choose clause");
+ $$ = list(choose_s, $5, $2, nao);
rl($$, num($1)); }
| CHOOSE exprs_opt ')'
newl error { $$ = nil;
yybadtok(yychar, lit("choose clause")); }
- | CHOOSE exprs_opt ')'
- newl END newl { $$ = nil;
- yyerr("empty choose clause"); }
;
gather_clause : GATHER exprs_opt ')'
newl gather_parts
- END newl { $$ = list(gather_s,
+ END newl { if (nilp($5))
+ yyerr("empty gather clause");
+ $$ = list(gather_s,
append2(mapcar(curry_12_1(func_n2(cons), nil),
first($5)), rest($5)),
$2, nao);
@@ -291,8 +287,12 @@ gather_clause : GATHER exprs_opt ')'
| GATHER exprs_opt ')'
newl gather_parts
until_last exprs_opt ')' newl
- clauses
- END newl { $$ = list(gather_s,
+ clauses_opt
+ END newl { if (nilp($5))
+ yyerr("empty gather clause");
+ if (nilp($10))
+ yyerr("empty until/last clause in gather");
+ $$ = list(gather_s,
append2(mapcar(curry_12_1(func_n2(cons), nil),
first($5)), rest($5)),
$2, cons(cdr($6),
@@ -302,27 +302,36 @@ gather_clause : GATHER exprs_opt ')'
| GATHER exprs_opt ')'
newl error { $$ = nil;
yybadtok(yychar, lit("gather clause")); }
- | GATHER exprs_opt ')'
- newl END newl { $$ = nil;
- yyerr("empty gather clause"); }
;
-gather_parts : clauses additional_gather_parts { $$ = cons($1, $2); }
+gather_parts : clauses_opt additional_gather_parts
+ { $$ = if2($1, cons($1, $2)); }
;
-additional_gather_parts : AND newl clauses additional_gather_parts { $$ = cons($3, $4); }
- | OR newl clauses additional_parts { $$ = cons($3, $4); }
- | /* empty */ { $$ = nil; }
+additional_gather_parts : AND newl gather_parts { $$ = $3;
+ if (nilp($$))
+ yyerr("empty and subclause"); }
+ | OR newl gather_parts { $$ = $3;
+ if (nilp($$))
+ yyerr("empty or subclause"); }
+ | /* empty */ { $$ = nil; }
;
collect_clause : collect_repeat exprs_opt ')' newl
- clauses END newl { $$ = list(car($1),
+ clauses_opt END newl { if (nilp($5))
+ yyerr("empty collect clause");
+ $$ = list(car($1),
$5, nil, $2,
nao);
rl($$, cdr($1)); }
| collect_repeat exprs_opt ')'
- newl clauses until_last exprs_opt ')'
- newl clauses END newl { $$ = list(car($1), $5,
+ newl clauses_opt until_last exprs_opt ')'
+ newl clauses_opt END newl
+ { if (nilp($5))
+ yyerr("empty collect clause");
+ if (nilp($10))
+ yyerr("empty until/last in collect");
+ $$ = list(car($1), $5,
cons(cdr($6),
cons($7, $10)),
$2, nao);
@@ -330,12 +339,7 @@ collect_clause : collect_repeat exprs_opt ')' newl
rl($10, car($6)); }
| collect_repeat exprs_opt ')'
newl error { $$ = nil;
- if (yychar == UNTIL ||
- yychar == END ||
- yychar == LAST)
- yyerr("empty collect");
- else
- yybadtok(yychar, lit("collect clause")); }
+ yybadtok(yychar, lit("collect clause")); }
;
collect_repeat : COLLECT { $$ = cons(collect_s, num($1)); }
@@ -346,12 +350,16 @@ until_last : UNTIL { $$ = cons(num($1), until_s); }
| LAST { $$ = cons(num($1), last_s); }
;
-clause_parts : clauses additional_parts { $$ = cons($1, $2); }
+clause_parts : clauses_opt additional_parts { $$ = if2($1, cons($1, $2)); }
;
-additional_parts : END newl { $$ = nil; }
- | AND newl clauses additional_parts { $$ = cons($3, $4); }
- | OR newl clauses additional_parts { $$ = cons($3, $4); }
+additional_parts : END newl { $$ = nil; }
+ | AND newl clause_parts { $$ = $3;
+ if (nilp($$))
+ yyerr("empty and subclause"); }
+ | OR newl clause_parts { $$ = $3;
+ if (nilp($$))
+ yyerr("empty or subclause"); }
;
if_clause : IF exprs_opt ')'
@@ -447,21 +455,33 @@ elem : texts { $$ = rlcp(cons(text_s, $1), $1);
$$ = rlcp(cons(sym,
expand_meta(rest($1), nil)),
$1); }
- | COLL exprs_opt ')' elems END { $$ = list(coll_s, $4, nil, $2, nao);
+ | COLL exprs_opt ')' elems_opt END { if (nilp($4))
+ yyerr("empty coll clause");
+ $$ = list(coll_s, $4, nil, $2, nao);
rl($$, num($1)); }
- | COLL exprs_opt ')' elems
+ | COLL exprs_opt ')' elems_opt
until_last exprs_opt ')'
- elems END { $$ = list(coll_s, $4, cons(cdr($5),
+ elems_opt END { if (nilp($4))
+ yyerr("empty coll clause");
+ if (nilp($8))
+ yyerr("empty until/last in coll");
+ $$ = list(coll_s, $4, cons(cdr($5),
cons($6, $8)),
$2, nao);
rl($$, num($1));
rl($6, car($5)); }
- | REP exprs_opt ')' elems END { $$ = list(rep_s, $4, nil, $2, nao);
+ | REP exprs_opt ')' elems END { if (nilp($2))
+ yyerr("empty rep clause");
+ $$ = list(rep_s, $4, nil, $2, nao);
rl($$, num($1)); }
| REP exprs_opt ')' elems
until_last exprs_opt ')'
elems END
- { $$ = list(rep_s, $4, cons(cdr($5),
+ { if (nilp($2))
+ yyerr("empty rep clause");
+ if (nilp($8))
+ yyerr("empty until/last in rep");
+ $$ = list(rep_s, $4, cons(cdr($5),
cons($6, $8)),
$2, nao);
rl($$, num($1));
@@ -470,32 +490,42 @@ elem : texts { $$ = rlcp(cons(text_s, $1), $1);
yybadtok(yychar, lit("coll clause")); }
| REP error { $$ = nil;
yybadtok(yychar, lit("rep clause")); }
- | ALL clause_parts_h { $$ = rl(list(all_s, t, $2, nao), num($1)); }
- | ALL END { yyerr("empty all clause"); }
+ | ALL clause_parts_h { $$ = rl(list(all_s, t, $2, nao), num($1));
+ if (nilp($2))
+ yyerr("empty all clause"); }
| SOME exprs_opt ')'
- clause_parts_h { $$ = rl(list(some_s, t, $4, $2, nao), num($1)); }
- | SOME exprs_opt ')' END { yyerr("empty some clause"); }
- | NONE clause_parts_h { $$ = rl(list(none_s, t, $2, nao), num($1)); }
- | NONE END { yyerr("empty none clause"); }
- | MAYBE clause_parts_h { $$ = rl(list(maybe_s, t, $2, nao), num($1)); }
- | MAYBE END { yyerr("empty maybe clause"); }
- | CASES clause_parts_h { $$ = rl(list(cases_s, t, $2, nao), num($1)); }
- | CASES END { yyerr("empty cases clause"); }
+ clause_parts_h { $$ = rl(list(some_s, t, $4, $2, nao), num($1));
+ if (nilp($4))
+ yyerr("empty some clause"); }
+ | NONE clause_parts_h { $$ = rl(list(none_s, t, $2, nao), num($1));
+ if (nilp($2))
+ yyerr("empty none clause"); }
+ | MAYBE clause_parts_h { $$ = rl(list(maybe_s, t, $2, nao), num($1));
+ if (nilp($2))
+ yyerr("empty maybe clause"); }
+ | CASES clause_parts_h { $$ = rl(list(cases_s, t, $2, nao), num($1));
+ if (nilp($2))
+ yyerr("empty cases clause"); }
| CHOOSE exprs_opt ')'
clause_parts_h { $$ = list(choose_s, t, $4, $2, nao);
- rl($$, num($1)); }
- | CHOOSE exprs_opt ')' END { yyerr("empty cases clause"); }
+ rl($$, num($1));
+ if (nilp($4))
+ yyerr("empty cases clause"); }
| DEFINE exprs ')' elems END
{ $$ = list(define_s, t, $4, $2, nao);
rl($$, num($1)); }
;
-clause_parts_h : elems additional_parts_h { $$ = cons($1, $2); }
+clause_parts_h : elems_opt additional_parts_h { $$ = if2($1, cons($1, $2)); }
;
-additional_parts_h : END { $$ = nil; }
- | AND elems additional_parts_h { $$ = cons($2, $3); }
- | OR elems additional_parts_h { $$ = cons($2, $3); }
+additional_parts_h : END { $$ = nil; }
+ | AND clause_parts_h { $$ = $2;
+ if (nilp($$))
+ yyerr("empty and subclause"); }
+ | OR clause_parts_h { $$ = $2;
+ if (nilp($$))
+ yyerr("empty or subclause"); }
;
define_clause : DEFINE exprs ')' newl
@@ -516,51 +546,54 @@ define_clause : DEFINE exprs ')' newl
;
try_clause : TRY newl
- clauses
+ clauses_opt
catch_clauses_opt
- END newl { $$ = list(try_s,
+ END newl { if (nilp($3))
+ yyerr("empty try clause");
+ $$ = list(try_s,
flatten(mapcar(func_n1(second),
$4)),
$3, $4, nao);
rl($$, num($1)); }
| TRY newl
error { $$ = nil;
- if (yychar == END || yychar == CATCH ||
- yychar == FINALLY)
- yyerr("empty try clause");
- else
- yybadtok(yychar, lit("try clause")); }
- | TRY newl
- clauses
- error { $$ = nil;
yybadtok(yychar, lit("try clause")); }
;
catch_clauses_opt : CATCH ')' newl
clauses_opt
- catch_clauses_opt { $$ = cons(list(catch_s, cons(t, nil),
+ catch_clauses_opt { if ((!opt_compat || opt_compat > 139)
+ && nilp($4))
+ yyerr("empty catch clause");
+ $$ = cons(list(catch_s, cons(t, nil),
$4, nao), $5);
rl($$, num($1)); }
| CATCH exprs ')' newl
clauses_opt
- catch_clauses_opt { $$ = cons(list(catch_s, $2, $5, nao),
+ catch_clauses_opt { if ((!opt_compat || opt_compat > 139)
+ && nilp($5))
+ yyerr("empty catch clause");
+ $$ = cons(list(catch_s, $2, $5, nao),
$6);
rl($$, num($1)); }
| FINALLY newl
- clauses_opt { $$ = cons(list(finally_s, nil,
+ clauses_opt { if ((!opt_compat || opt_compat > 139)
+ && nilp($3))
+ yyerr("empty finally clause");
+ $$ = cons(list(finally_s, nil,
$3, nao),
nil);
rl($$, num($1)); }
| { $$ = nil; }
| CATCH ')' newl
error { $$ = nil;
- yybadtok(yychar, lit("try clause")); }
+ yybadtok(yychar, lit("catch clause")); }
| CATCH exprs ')' newl
error { $$ = nil;
- yybadtok(yychar, lit("try clause")); }
+ yybadtok(yychar, lit("catch clause")); }
| FINALLY newl
error { $$ = nil;
- yybadtok(yychar, lit("try clause")); }
+ yybadtok(yychar, lit("finally clause")); }
;