From c4eb7f17cf2912575d483b21a0021375f23553cb Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Fri, 7 Apr 2017 22:19:14 -0700 Subject: parser: refactor grammar to banish #[] etc. Turns out we have an over-eager parser whcih recognizes invalid notion such as #[...], #S[...] and others. This is because the grammar nonterminal list is overloaded with phrase structures. The syntax of a vector literal, for instance, is '#' list, but a list can be '[' ... and other expressions. * parser.y (dwim, meta, compound): New non-terminal symbols. Dwim derives the square bracketed "dwim" expressons that were previously overloaded into list. Meta derives the @ exprs. compound is what list used to be. (list): Handle only (...) list expressions. (o_elem, modifiers): Derives compound rather than list, thus preserving existing behavior. (i_expr, n_expr): Likewise. All other uses references to the list nonterminal stay, thereby trimming the grammar of dubious expressions. --- parser.y | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/parser.y b/parser.y index a4a98300..11664604 100644 --- a/parser.y +++ b/parser.y @@ -136,8 +136,9 @@ INLINE val expand_form_ver(val form, int ver) %type if_clause elif_clauses_opt else_clause_opt %type line elems_opt elems clause_parts_h additional_parts_h %type text texts elem var var_op modifiers vector hash struct range -%type list exprs exprs_opt n_exprs r_exprs i_expr i_dot_expr +%type exprs exprs_opt n_exprs r_exprs i_expr i_dot_expr %type n_expr n_exprs_opt n_dot_expr +%type list dwim meta compound %type out_clauses out_clauses_opt out_clause %type repeat_clause repeat_parts_opt o_line %type o_elems_opt o_elems o_elem o_var q_var rep_elem rep_parts_opt @@ -710,7 +711,7 @@ o_elem : TEXT { $$ = string_own($1); | SPACE { $$ = string_own($1); rl($$, num(parser->lineno)); } | o_var { $$ = $1; } - | list { $$ = rlcp(list(expr_s, + | compound { $$ = rlcp(list(expr_s, expand($1, nil), nao), $1); } | rep_elem { $$ = $1; } ; @@ -782,7 +783,7 @@ var_op : '*' { $$ = list(t, nao); } modifiers : NUMBER { $$ = cons($1, nil); } | regex { $$ = cons($1, nil); rlcp($$, $1); } - | list { $$ = rlcp(cons(expand_meta($1, nil), + | compound { $$ = rlcp(cons(expand_meta($1, nil), nil), $1); } ; @@ -849,28 +850,37 @@ list : '(' n_exprs ')' { $$ = rl($2, num($1)); } $$ = $3; else $$ = rlcp(cons(ur, cdr($3)), ur); } - | '[' '.' n_exprs ']' { val a = car($3); - val ur = uref_helper(parser, a); - $$ = rlcp_tree(cons(dwim_s, - cons(ur, cdr($3))), ur); } | '(' ')' { $$ = nil; } | '(' LAMBDOT n_expr ')' { $$ = $3; } | '(' CONSDOT n_expr ')' { $$ = $3; } - | '[' n_exprs ']' { $$ = rl(cons(dwim_s, $2), num($1)); } - | '[' ']' { $$ = rl(cons(dwim_s, nil), num($1)); } - | '@' n_expr { if (consp($2)) + | '(' error { $$ = nil; + yybadtok(yychar, lit("expression")); } + ; + +meta : '@' n_expr { if (consp($2)) $$ = rl(cons(expr_s, cons($2, nil)), num($1)); else $$ = rl(cons(var_s, cons($2, nil)), num($1)); } - | '(' error { $$ = nil; - yybadtok(yychar, lit("expression")); } - | '[' error { $$ = nil; - yybadtok(yychar, lit("DWIM expression")); } | '@' error { $$ = nil; yybadtok(yychar, lit("meta expression")); } ; +dwim : '[' '.' n_exprs ']' { val a = car($3); + val ur = uref_helper(parser, a); + $$ = rlcp_tree(cons(dwim_s, + cons(ur, cdr($3))), ur); } + | '[' n_exprs ']' { $$ = rl(cons(dwim_s, $2), num($1)); } + | '[' ']' { $$ = rl(cons(dwim_s, nil), num($1)); } + | '[' error { $$ = nil; + yybadtok(yychar, lit("DWIM expression")); } + ; + +compound : list + | dwim + | meta + ; + exprs : n_exprs { $$ = rlcp(expand_meta($1, nil), $1); } ; @@ -932,7 +942,7 @@ i_expr : SYMTOK { $$ = symhlpr($1, t); } | METANUM { $$ = cons(var_s, cons($1, nil)); rl($$, num(parser->lineno)); } | NUMBER { $$ = $1; } - | list { $$ = $1; } + | compound { $$ = $1; } | vector { $$ = $1; } | hash { $$ = $1; } | struct { $$ = $1; } @@ -964,7 +974,7 @@ n_expr : SYMTOK { $$ = symhlpr($1, t); } | METANUM { $$ = cons(var_s, cons($1, nil)); rl($$, num(parser->lineno)); } | NUMBER { $$ = $1; } - | list { $$ = $1; } + | compound { $$ = $1; } | vector { $$ = $1; } | hash { $$ = $1; } | struct { $$ = $1; } -- cgit v1.2.3