abort:
while (tk.num != TK_newline && tk.num != TK_eof)
tk = token_next(state);
+ free(p.body);
return err;
}
s->name.len, s->name.txt);
}
if (errs) {
- free(g);
+ free(g); // FIXME free content
g = NULL;
}
}
fprintf(stderr, "Error at line %d: %s\n",
tk.line, err);
token_close(state);
- free(g);
+ free(g); // FIXME free content
return NULL;
}
done using `add_first` above and only needs to be done once as the
"first" sets are now stable and will not change.
+###### grammar fields
+ struct symset *follow;
+
###### follow code
for (p = 0; p < g->production_count; p++) {
We now just need to create and initialise the `follow` list to get a
complete function.
-###### grammar fields
- struct symset *follow;
-
###### functions
static void build_follow(struct grammar *g)
{
continue;
if (pr->body[bp] != sym)
continue;
+
+ bp += 1;
if (type >= LALR)
la = is->items.data[j];
- pos = symset_find(&newitemset, pr->head->num);
- if (bp + 1 == pr->body_size &&
+ if (bp == pr->body_size &&
pr->precedence > 0 &&
pr->precedence > precedence) {
// new itemset is reducible and has a precedence.
precedence = pr->precedence;
assoc = pr->assoc;
}
+ pos = symset_find(&newitemset, item_num(p, bp));
+
if (pos < 0)
- symset_add(&newitemset, item_num(p, bp+1), la);
+ symset_add(&newitemset, item_num(p, bp), la);
else if (type >= LALR) {
// Need to merge la set.
int la2 = newitemset.data[pos];
}
}
-###### functions
-
static void gen_states(FILE *f, struct grammar *g)
{
int i;
c = *name;
}
if (namlen == 0) {
- if (name == *namep)
+ if (name == *namep || n > p->body_size)
return -1;
*namep = name;
return n;
for (i = 0; i < p->body_size; i++) {
if (!subseq_match(nam, namlen, p->body[i]->name))
continue;
- if (slen == 0 || p->body[i]->name.len < slen)
+ if (slen == 0 || p->body[i]->name.len < slen) {
s = i;
+ slen = p->body[i]->name.len;
+ }
if (s >= 0 && p->body[i] != p->body[s] &&
p->body[i]->name.len == p->body[s]->name.len)
/* not unique, so s cannot be used */
}
if (s < 0)
return -1;
- if (n == 0);
+ if (n == 0)
n = 1;
for (i = 0; i < p->body_size; i++)
if (p->body[i] == p->body[s]) {
if (n == 0)
break;
}
- if (n > 1)
+ if (n > 0 || i == p->body_size)
return -1;
*namep = name;
return i + 1;
###### functions
static void gen_reduce(FILE *f, struct grammar *g, char *file,
- struct code_node *code)
+ struct code_node *pre_reduce)
{
int i;
fprintf(f, "#line 1 \"gen_reduce\"\n");
fprintf(f, "static int do_reduce(int prod, void **body, struct token_config *config, void *ret)\n");
fprintf(f, "{\n");
fprintf(f, "\tint ret_size = 0;\n");
- if (code)
- code_node_print(f, code, file);
+ if (pre_reduce)
+ code_node_print(f, pre_reduce, file);
fprintf(f, "#line 4 \"gen_reduce\"\n");
fprintf(f, "\tswitch(prod) {\n");
case 't':
tag = optarg; break;
default:
- fprintf(stderr, "Usage: parsergen ...\n");
+ fprintf(stderr, "Usage: parsergen -[05SL1R] [-t tag] [-o output] input\n");
exit(1);
}
}
return -1;
}
+### Memory allocation
+
+The `scanner` returns tokens in a local variable - we want them in allocated
+memory so they can live in the `asn_stack`. Similarly the `asn` produced by
+a reduce is in a large buffer. Both of these require some allocation and
+copying, hence `memdup` and `tok_copy`.
+
+###### parser includes
+ #include <memory.h>
+
+###### parser functions
+
+ void *memdup(void *m, int len)
+ {
+ void *ret;
+ if (len == 0)
+ return NULL;
+ ret = malloc(len);
+ memcpy(ret, m, len);
+ return ret;
+ }
+
+ static struct token *tok_copy(struct token tk)
+ {
+ struct token *new = malloc(sizeof(*new));
+ *new = tk;
+ return new;
+ }
+
### The state stack.
The core data structure for the parser is the stack. This tracks all
return indents;
}
-### Memory allocation
-
-The `scanner` returns tokens in a local variable - we want them in allocated
-memory so they can live in the `asn_stack`. Similarly the `asn` produced by
-a reduce is in a large buffer. Both of these require some allocation and
-copying, hence `memdup` and `tokcopy`.
-
-###### parser includes
- #include <memory.h>
-
-###### parser functions
-
- void *memdup(void *m, int len)
- {
- void *ret;
- if (len == 0)
- return NULL;
- ret = malloc(len);
- memcpy(ret, m, len);
- return ret;
- }
-
- static struct token *tok_copy(struct token tk)
- {
- struct token *new = malloc(sizeof(*new));
- *new = tk;
- return new;
- }
-
### The heart of the parser.
Now we have the parser. For each token we might shift it, trigger a