123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- /*
- * Copyright 2021
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * SPDX-License-Identifier: GPL-3.0+
- * License-Filename: LICENSE
- */
- #include <assert.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "arg.h"
- #include "cook.h"
- #include "error.h"
- #include "preen.h"
- #include "syntax.h"
- /* cook() prepares a grammar for feeding */
- /* perhaps we should use the walk() function from sugar.c, but that doesn't
- * support the "pre" variable that we use. */
- static void cook0(struct s_node *n) {
- static char *name;
- struct s_node *p;
- if (n->type == rule)
- name = n->text;
- /* Replace
- * ... _ foo
- * with
- * ... _ (foo / !.)
- * for any non-empty foo.
- */
- if (n->type == cafe) {
- struct s_node *t;
- //fprintf(stderr, "match at node %ld\n", n->id);
- if (!n->next)
- fatal3("invalid `$' at the end of rule `", name, "'");
- t = s_kid(seq, s_kid(not, s_new(any)));
- t = cons(s_kid(seq, n->next), t);
- t = s_kid(alt, t);
- // pre->next = t;
- // free(n);
- n->next = t;
- }
- if (s_has_children(n->type))
- for (p = n->first; p; p = p->next)
- cook0(p);
- }
- /* make all rules void, and remove all expr nodes */
- static void dexpr(struct s_node *n, struct s_node *par, struct s_node *sib) {
- struct s_node *p, *q;
- if (n->type == expr) {
- assert(par || sib);
- if (sib)
- sib->next = n->next;
- else
- par->first = 0;
- /* at this point we should free(n) and its children, but we can't do
- * that inside the loop */
- }
- /* XXX in principle, we could remove all bindings *except* those
- * used in guards. */
- if (s_has_children(n->type))
- for (p = 0, q = n->first; q; p = q, q = q->next)
- dexpr(q, n, p);
- }
- void cook(struct s_node *g) {
- char *newname;
- int l;
- dexpr(g, 0, 0);
- cook0(g);
- l = strlen(g->text) + strlen("_feed") + 1;
- newname = realloc(0, l);
- if (!newname) nomem();
- strcpy(newname, g->text);
- strcat(newname, "_feed");
- g->text = newname;
- check_recursion(g);
- }
- /* end. */
|