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)
{
}
}
-###### functions
-
static void gen_states(FILE *f, struct grammar *g)
{
int i;
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