]> ocean-lang.org Git - ocean/blob - csrc/parsergen.mdc
parsergen: improve tracing.
[ocean] / csrc / parsergen.mdc
1 # LR(1) Parser Generator #
2
3 This parser generator takes a grammar description combined with code
4 fragments, analyses it, and can report details about the analysis and
5 write out C code files which can be compiled to make a parser.
6
7 There are several distinct sections.
8
9 1. `grammar_read` will read a grammar from a literate-code file and
10    store the productions, symbols, and code fragments.
11 2. `grammar_analyse` will take that grammar and build LR parsing
12    states and look-ahead tables.
13 3. `grammar_report` will present the details of the analysis
14    in a readable format and will report any conflicts.
15 4. `parser_generate` will write out C code files with various
16    tables and with the code fragments arranged in useful places.
17 5. `parser_run` is a library function intended to be linked together
18    with the generated parser tables to complete the implementation of
19    a parser.
20 6. Finally `calc` is a test grammar for a simple calculator.  The
21    `parsergen` program built from the C code in this file can extract
22    that grammar directly from this file and process it.
23
24
25 ###### File: parsergen.c
26         #include <unistd.h>
27         #include <stdlib.h>
28         #include <stdio.h>
29         ## includes
30         ## forward declarations
31         ## declarations
32         ## functions
33         ## grammar_read
34         ## grammar_analyse
35         ## grammar_report
36         ## parser_generate
37         ## main
38 ###### File: parser.h
39         ## exported types
40         ## exported functions
41 ###### File: libparser.c
42         #include <unistd.h>
43         #include <stdlib.h>
44         #include <stdio.h>
45         ## parser includes
46         ## parser functions
47         ## parser_run
48 ###### File: parsergen.mk
49         CFLAGS += -Wall -g
50         all :: parsergen calc
51         parsergen.c parsergen.mk libparser.c parser.h : parsergen.mdc
52                 ./md2c parsergen.mdc
53
54 ## Reading the grammar
55
56 The grammar must be stored in a markdown literate code file as parsed
57 by "[mdcode][]".  It must have three top level (i.e. unreferenced)
58 sections: `header`, `code`, and `grammar`.  The first two will be
59 literally copied into the generated `.c` and `.h`. files.  The last
60 contains the grammar.  This is tokenised with "[scanner][]".
61
62 If the `--tag` option is given, then any top level header that doesn't
63 start with the tag is ignored, and the tag is striped from the rest.  So
64 `--tag Foo`
65 means that the three needed sections must be `Foo: header`, `Foo: code`,
66 and `Foo: grammar`.
67
68 [mdcode]: mdcode.html
69 [scanner]: scanner.html
70
71 ###### includes
72         #include "mdcode.h"
73         #include "scanner.h"
74
75 ###### parser includes
76         #include "mdcode.h"
77         #include "scanner.h"
78
79 The grammar contains production sets, precedence/associativity
80 declarations, and data type declarations.  These are all parsed with
81 _ad hoc_ parsing as we don't have a parser generator yet.
82
83 The precedence and associativity can be set for each production, but
84 can be inherited from symbols.  The data type (either structure or a
85 reference to a structure) is potentially defined for each non-terminal
86 and describes what C structure is used to store information about each
87 symbol.
88
89 ###### declarations
90         enum assoc {Left, Right, Non};
91         char *assoc_names[] = {"Left","Right","Non"};
92
93         struct symbol {
94                 struct text struct_name;
95                 int isref;
96                 enum assoc assoc;
97                 unsigned short precedence;
98                 ## symbol fields
99         };
100         struct production {
101                 unsigned short precedence;
102                 enum assoc assoc;
103                 ## production fields
104         };
105         struct grammar {
106                 ## grammar fields
107         };
108
109 The strings reported by `mdcode` and `scanner` are `struct text` which have
110 length rather than being null terminated.  To help with printing and
111 comparing we define `text_is` and `prtxt`, which should possibly go in
112 `mdcode`.  `scanner` does provide `text_dump` which is useful for strings
113 which might contain control characters.
114
115 `strip_tag` is a bit like `strncmp`, but adds a test for a colon,
116 because that is what we need to detect tags.
117
118 ###### functions
119         static int text_is(struct text t, char *s)
120         {
121                 return (strlen(s) == t.len &&
122                         strncmp(s, t.txt, t.len) == 0);
123         }
124         static void prtxt(struct text t)
125         {
126                 printf("%.*s", t.len, t.txt);
127         }
128
129         static int strip_tag(struct text *t, char *tag)
130         {
131                 int skip = strlen(tag) + 1;
132                 if (skip >= t->len ||
133                     strncmp(t->txt, tag, skip-1) != 0 ||
134                     t->txt[skip-1] != ':')
135                         return 0;
136                 while (skip < t->len && t->txt[skip] == ' ')
137                         skip++;
138                 t->len -= skip;
139                 t->txt += skip;
140                 return 1;
141         }
142
143 ### Symbols
144
145 Productions are comprised primarily of symbols - terminal and
146 non-terminal.  We do not make a syntactic distinction between the two,
147 though non-terminals must be identifiers.  Non-terminal symbols are
148 those which appear in the head of a production, terminal symbols are
149 those which don't.  There are also "virtual" symbols used for precedence
150 marking discussed later, and sometimes we won't know what type a symbol
151 is yet.
152
153 ###### forward declarations
154         enum symtype { Unknown, Virtual, Terminal, Nonterminal };
155         char *symtypes = "UVTN";
156 ###### symbol fields
157         enum symtype type;
158
159 Symbols can be either `TK_ident` or `TK_mark`.  They are saved in a
160 table of known symbols and the resulting parser will report them as
161 `TK_reserved + N`.  A small set of identifiers are reserved for the
162 different token types that `scanner` can report.
163
164 ###### declarations
165         static char *reserved_words[] = {
166                 [TK_error]        = "ERROR",
167                 [TK_number]       = "NUMBER",
168                 [TK_ident]        = "IDENTIFIER",
169                 [TK_mark]         = "MARK",
170                 [TK_string]       = "STRING",
171                 [TK_multi_string] = "MULTI_STRING",
172                 [TK_in]           = "IN",
173                 [TK_out]          = "OUT",
174                 [TK_newline]      = "NEWLINE",
175                 [TK_eof]          = "$eof",
176         };
177 ###### symbol fields
178         short num;
179
180 Note that `TK_eof` and the two `TK_*_comment` tokens cannot be
181 recognised.  The former is automatically expected at the end of the text
182 being parsed. The latter are always ignored by the parser.
183
184 All of these symbols are stored in a simple symbol table.  We use the
185 `struct text` from `mdcode` to store the name and link them together
186 into a sorted list using an insertion sort.
187
188 We don't have separate `find` and `insert` functions as any symbol we
189 find needs to be remembered.  We simply expect `find` to always return a
190 symbol, but its type might be `Unknown`.
191
192 ###### includes
193         #include <string.h>
194
195 ###### symbol fields
196         struct text name;
197         struct symbol *next;
198
199 ###### grammar fields
200         struct symbol *syms;
201         int num_syms;
202
203 ###### functions
204         static struct symbol *sym_find(struct grammar *g, struct text s)
205         {
206                 struct symbol **l = &g->syms;
207                 struct symbol *n;
208                 int cmp = 1;
209
210                 while (*l &&
211                         (cmp = text_cmp((*l)->name, s)) < 0)
212                                 l = & (*l)->next;
213                 if (cmp == 0)
214                         return *l;
215                 n = calloc(1, sizeof(*n));
216                 n->name = s;
217                 n->type = Unknown;
218                 n->next = *l;
219                 n->num = -1;
220                 *l = n;
221                 return n;
222         }
223
224         static void symbols_init(struct grammar *g)
225         {
226                 int entries = sizeof(reserved_words)/sizeof(reserved_words[0]);
227                 int i;
228                 for (i = 0; i < entries; i++) {
229                         struct text t;
230                         struct symbol *s;
231                         t.txt = reserved_words[i];
232                         if (!t.txt)
233                                 continue;
234                         t.len = strlen(t.txt);
235                         s = sym_find(g, t);
236                         s->type = Terminal;
237                         s->num = i;
238                 }
239         }
240
241 ### Data types and precedence.
242
243 Data type specification and precedence specification are both
244 introduced by a dollar sign at the start of the line.  If the next
245 word is `LEFT`, `RIGHT` or `NON`, then the line specifies a
246 precedence, otherwise it specifies a data type.
247
248 The data type name is simply stored and applied to the head of all
249 subsequent productions.  It must be the name of a structure optionally
250 preceded by an asterisk which means a reference or "pointer".  So
251 `$expression` maps to `struct expression` and `$*statement` maps to
252 `struct statement *`.
253
254 Any productions given before the first data type declaration will have
255 no data type associated with them and can carry no information.  In
256 order to allow other non-terminals to have no type, the data type
257 `$void` can be given.  This does *not* mean that `struct void` will be
258 used, but rather than no type will be associated with future
259 non-terminals.
260
261 The precedence line must contain a list of symbols - typically
262 terminal symbols, but not necessarily.  It can only contain symbols
263 that have not been seen yet, so precedence declaration must precede
264 the productions that they affect.
265
266 A precedence line may also contain a "virtual" symbol which is an
267 identifier preceded by `$$`.  Virtual terminals carry precedence
268 information but are not included in the grammar.  A production can
269 declare that it inherits the precedence of a given virtual symbol.
270
271 This use for `$$` precludes it from being used as a symbol in the
272 described language.  Two other symbols: `${` and `}$` are also
273 unavailable.
274
275 Each new precedence line introduces a new precedence level and
276 declares how it associates.  This level is stored in each symbol
277 listed and may be inherited by any production which uses the symbol.  A
278 production inherits from the last symbol which has a precedence.
279
280 ###### grammar fields
281         struct text current_type;
282         int type_isref;
283         int prec_levels;
284
285 ###### declarations
286         enum symbols { TK_virtual = TK_reserved, TK_open, TK_close };
287         static const char *known[] = { "$$", "${", "}$" };
288
289 ###### functions
290         static char *dollar_line(struct token_state *ts, struct grammar *g, int isref)
291         {
292                 struct token t = token_next(ts);
293                 char *err;
294                 enum assoc assoc;
295                 int found;
296
297                 if (t.num != TK_ident) {
298                         err = "type or assoc expected after '$'";
299                         goto abort;
300                 }
301                 if (text_is(t.txt, "LEFT"))
302                         assoc = Left;
303                 else if (text_is(t.txt, "RIGHT"))
304                         assoc = Right;
305                 else if (text_is(t.txt, "NON"))
306                         assoc = Non;
307                 else {
308                         g->current_type = t.txt;
309                         g->type_isref = isref;
310                         if (text_is(t.txt, "void"))
311                                 g->current_type.txt = NULL;
312                         t = token_next(ts);
313                         if (t.num != TK_newline) {
314                                 err = "Extra tokens after type name";
315                                 goto abort;
316                         }
317                         return NULL;
318                 }
319
320                 if (isref) {
321                         err = "$* cannot be followed by a precedence";
322                         goto abort;
323                 }
324
325                 // This is a precedence line, need some symbols.
326                 found = 0;
327                 g->prec_levels += 1;
328                 t = token_next(ts);
329                 while (t.num != TK_newline) {
330                         enum symtype type = Terminal;
331                         struct symbol *s;
332                         if (t.num == TK_virtual) {
333                                 type = Virtual;
334                                 t = token_next(ts);
335                                 if (t.num != TK_ident) {
336                                         err = "$$ must be followed by a word";
337                                         goto abort;
338                                 }
339                         } else if (t.num != TK_ident &&
340                                    t.num != TK_mark) {
341                                 err = "Illegal token in precedence line";
342                                 goto abort;
343                         }
344                         s = sym_find(g, t.txt);
345                         if (s->type != Unknown) {
346                                 err = "Symbols in precedence line must not already be known.";
347                                 goto abort;
348                         }
349                         s->type = type;
350                         s->precedence = g->prec_levels;
351                         s->assoc = assoc;
352                         found += 1;
353                 }
354                 if (found == 0)
355                         err = "No symbols given on precedence line";
356                         goto abort;
357                 return NULL;
358         abort:
359                 while (t.num != TK_newline && t.num != TK_eof)
360                         t = token_next(ts);
361                 return err;
362         }
363
364 ### Productions
365
366 A production either starts with an identifier which is the head
367 non-terminal, or a vertical bar (`|`) in which case this production
368 uses the same head as the previous one.  The identifier must be
369 followed by a `->` mark.  All productions for a given non-terminal must
370 be grouped together with the `nonterminal ->` given only once.
371
372 After this a (possibly empty) sequence of identifiers and marks form
373 the body of the production.  A virtual symbol may be given after the
374 body by preceding it with `$$`.  If a virtual symbol is given, the
375 precedence of the production is that for the virtual symbol.  If none
376 is given, the precedence is inherited from the last symbol in the
377 production which has a precedence specified.
378
379 After the optional precedence may come the `${` mark.  This indicates
380 the start of a code fragment.  If present, this must be on the same
381 line as the start of the production.
382
383 All of the text from the `${` through to the matching `}$` is
384 collected and forms the code-fragment for the production.  It must all
385 be in one `code_node` of the literate code.  The `}$` must be
386 at the end of a line.
387
388 Text in the code fragment will undergo substitutions where `$N` or
389 `$<N`,for some numeric `N`, will be replaced with a variable holding
390 the parse information for the particular symbol in the production.
391 `$0` is the head of the production, `$1` is the first symbol of the
392 body, etc.  The type of `$N` for a terminal symbol is `struct token`.
393 For a non-terminal, it is whatever has been declared for that symbol.
394 The `<` may be included for symbols declared as storing a reference
395 (not a structure) and means that the reference is being moved out, so
396 it will not automatically be freed.
397
398 While building productions we will need to add to an array which needs to
399 grow dynamically.
400
401 ###### functions
402         static void array_add(void *varray, int *cnt, void *new)
403         {
404                 void ***array = varray;
405                 int current = 0;
406                 const int step = 8;
407                 current = ((*cnt-1) | (step-1))+1;
408                 if (*cnt == current) {
409                         /* must grow */
410                         current += step;
411                         *array = realloc(*array, current * sizeof(void*));
412                 }
413                 (*array)[*cnt] = new;
414                 (*cnt) += 1;
415         }
416
417 Collecting the code fragment simply involves reading tokens until we
418 hit the end token `}$`, and noting the character position of the start and
419 the end.
420
421 ###### functions
422         static struct text collect_code(struct token_state *state,
423                                         struct token start)
424         {
425                 struct text code;
426                 struct token t;
427                 code.txt = start.txt.txt + start.txt.len;
428                 do
429                         t = token_next(state);
430                 while (t.node == start.node &&
431                        t.num != TK_close && t.num != TK_error &&
432                        t.num != TK_eof);
433                 if (t.num == TK_close && t.node == start.node)
434                         code.len = t.txt.txt - code.txt;
435                 else
436                         code.txt = NULL;
437                 return code;
438         }
439
440 Now we have all the bit we need to parse a full production.
441
442 ###### includes
443         #include <memory.h>
444
445 ###### grammar fields
446         struct production **productions;
447         int production_count;
448
449 ###### production fields
450         struct symbol  *head;
451         struct symbol **body;
452         int             body_size;
453         struct text     code;
454
455 ###### symbol fields
456         int first_production;
457
458 ###### functions
459         static char *parse_production(struct grammar *g,
460                                       struct symbol *head,
461                                       struct token_state *state)
462         {
463                 /* Head has already been parsed. */
464                 struct token tk;
465                 char *err;
466                 struct production p, *pp;
467
468                 memset(&p, 0, sizeof(p));
469                 p.head = head;
470                 tk = token_next(state);
471                 while (tk.num == TK_ident || tk.num == TK_mark) {
472                         struct symbol *bs = sym_find(g, tk.txt);
473                         if (bs->type == Unknown)
474                                 bs->type = Terminal;
475                         if (bs->type == Virtual) {
476                                 err = "Virtual symbol not permitted in production";
477                                 goto abort;
478                         }
479                         if (bs->precedence) {
480                                 p.precedence = bs->precedence;
481                                 p.assoc = bs->assoc;
482                         }
483                         array_add(&p.body, &p.body_size, bs);
484                         tk = token_next(state);
485                 }
486                 if (tk.num == TK_virtual) {
487                         struct symbol *vs;
488                         tk = token_next(state);
489                         if (tk.num != TK_ident) {
490                                 err = "word required after $$";
491                                 goto abort;
492                         }
493                         vs = sym_find(g, tk.txt);
494                         if (vs->type != Virtual) {
495                                 err = "symbol after $$ must be virtual";
496                                 goto abort;
497                         }
498                         p.precedence = vs->precedence;
499                         p.assoc = vs->assoc;
500                         tk = token_next(state);
501                 }
502                 if (tk.num == TK_open) {
503                         p.code = collect_code(state, tk);
504                         if (p.code.txt == NULL) {
505                                 err = "code fragment not closed properly";
506                                 goto abort;
507                         }
508                         tk = token_next(state);
509                 }
510                 if (tk.num != TK_newline && tk.num != TK_eof) {
511                         err = "stray tokens at end of line";
512                         goto abort;
513                 }
514                 pp = malloc(sizeof(*pp));
515                 *pp = p;
516                 array_add(&g->productions, &g->production_count, pp);
517                 return NULL;
518         abort:
519                 while (tk.num != TK_newline && tk.num != TK_eof)
520                         tk = token_next(state);
521                 return err;
522         }
523
524 With the ability to parse production and dollar-lines, we have nearly all
525 that we need to parse a grammar from a `code_node`.
526
527 The head of the first production will effectively be the `start` symbol of
528 the grammar.  However it won't _actually_ be so.  Processing the grammar is
529 greatly simplified if the real start symbol only has a single production,
530 and expects `$eof` as the final terminal.  So when we find the first
531 explicit production we insert an extra production as production zero which
532 looks like
533
534 ###### Example: production 0
535         $start -> START $eof
536
537 where `START` is the first non-terminal given.
538
539 ###### create production zero
540         struct production *p = calloc(1,sizeof(*p));
541         struct text start = {"$start",6};
542         struct text eof = {"$eof",4};
543         struct text code = {"$0 = $<1;", 9};
544         p->head = sym_find(g, start);
545         p->head->type = Nonterminal;
546         p->head->struct_name = g->current_type;
547         p->head->isref = g->type_isref;
548         if (g->current_type.txt)
549                 p->code = code;
550         array_add(&p->body, &p->body_size, head);
551         array_add(&p->body, &p->body_size, sym_find(g, eof));
552         p->head->first_production = g->production_count;
553         array_add(&g->productions, &g->production_count, p);
554
555 Now we are ready to read in the grammar.
556
557 ###### grammar_read
558         static struct grammar *grammar_read(struct code_node *code)
559         {
560                 struct token_config conf = {
561                         .word_start = "",
562                         .word_cont = "",
563                         .words_marks = known,
564                         .known_count = sizeof(known)/sizeof(known[0]),
565                         .number_chars = "",
566                         .ignored = (1 << TK_line_comment)
567                                  | (1 << TK_block_comment)
568                                  | (0 << TK_number)
569                                  | (1 << TK_string)
570                                  | (1 << TK_multi_string)
571                                  | (1 << TK_in)
572                                  | (1 << TK_out),
573                 };
574
575                 struct token_state *state = token_open(code, &conf);
576                 struct token tk;
577                 struct symbol *head = NULL;
578                 struct grammar *g;
579                 char *err = NULL;
580
581                 g = calloc(1, sizeof(*g));
582                 symbols_init(g);
583
584                 for (tk = token_next(state); tk.num != TK_eof;
585                      tk = token_next(state)) {
586                         if (tk.num == TK_newline)
587                                 continue;
588                         if (tk.num == TK_ident) {
589                                 // new non-terminal
590                                 head = sym_find(g, tk.txt);
591                                 if (head->type == Nonterminal)
592                                         err = "This non-terminal has already be used.";
593                                 else if (head->type == Virtual)
594                                         err = "Virtual symbol not permitted in head of production";
595                                 else {
596                                         head->type = Nonterminal;
597                                         head->struct_name = g->current_type;
598                                         head->isref = g->type_isref;
599                                         if (g->production_count == 0) {
600                                                 ## create production zero
601                                         }
602                                         head->first_production = g->production_count;
603                                         tk = token_next(state);
604                                         if (tk.num == TK_mark &&
605                                             text_is(tk.txt, "->"))
606                                                 err = parse_production(g, head, state);
607                                         else
608                                                 err = "'->' missing in production";
609                                 }
610                         } else if (tk.num == TK_mark
611                                    && text_is(tk.txt, "|")) {
612                                 // another production for same non-term
613                                 if (head)
614                                         err = parse_production(g, head, state);
615                                 else
616                                         err = "First production must have a head";
617                         } else if (tk.num == TK_mark
618                                    && text_is(tk.txt, "$")) {
619                                 err = dollar_line(state, g, 0);
620                         } else if (tk.num == TK_mark
621                                    && text_is(tk.txt, "$*")) {
622                                 err = dollar_line(state, g, 1);
623                         } else {
624                                 err = "Unrecognised token at start of line.";
625                         }
626                         if (err)
627                                 goto abort;
628                 }
629                 token_close(state);
630                 return g;
631         abort:
632                 fprintf(stderr, "Error at line %d: %s\n",
633                         tk.line, err);
634                 token_close(state);
635                 free(g);
636                 return NULL;
637         }
638
639 ## Analysing the grammar
640
641 The central task in analysing the grammar is to determine a set of
642 states to drive the parsing process.  This will require finding
643 various sets of symbols and of "items".  Some of these sets will need
644 to attach information to each element in the set, so they are more
645 like maps.
646
647 Each "item" may have a 'look-ahead' or `LA` set associated with
648 it.  Many of these will be the same as each other.  To avoid memory
649 wastage, and to simplify some comparisons of sets, these sets will be
650 stored in a list of unique sets, each assigned a number.
651
652 Once we have the data structures in hand to manage these sets and
653 lists, we can start setting the 'nullable' flag, build the 'FIRST'
654 sets, and then create the item sets which define the various states.
655
656 ### Symbol sets.
657
658 Though we don't only store symbols in these sets, they are the main
659 things we store, so they are called symbol sets or "symsets".
660
661 A symset has a size, an array of shorts, and an optional array of data
662 values, which are also shorts.  If the array of data is not present,
663 we store an impossible pointer, as `NULL` is used to indicate that no
664 memory has been allocated yet;
665
666 ###### declarations
667         struct symset {
668                 short cnt;
669                 unsigned short *syms, *data;
670         };
671         #define NO_DATA ((unsigned short *)1)
672         const struct symset INIT_SYMSET =  { 0, NULL, NO_DATA };
673         const struct symset INIT_DATASET = { 0, NULL, NULL };
674
675 The arrays of shorts are allocated in blocks of 8 and are kept sorted
676 by using an insertion sort.  We don't explicitly record the amount of
677 allocated space as it can be derived directly from the current `cnt` using
678 `((cnt - 1) | 7) + 1`.
679
680 ###### functions
681         static void symset_add(struct symset *s, unsigned short key, unsigned short val)
682         {
683                 int i;
684                 int current = ((s->cnt-1) | 7) + 1;
685                 if (current == s->cnt) {
686                         current += 8;
687                         s->syms = realloc(s->syms, sizeof(*s->syms) * current);
688                         if (s->data != NO_DATA)
689                                 s->data = realloc(s->data, sizeof(*s->data) * current);
690                 }
691                 i = s->cnt;
692                 while (i > 0 && s->syms[i-1] > key) {
693                         s->syms[i] = s->syms[i-1];
694                         if (s->data != NO_DATA)
695                                 s->data[i] = s->data[i-1];
696                         i--;
697                 }
698                 s->syms[i] = key;
699                 if (s->data != NO_DATA)
700                         s->data[i] = val;
701                 s->cnt += 1;
702         }
703
704 Finding a symbol (or item) in a `symset` uses a simple binary search.
705 We return the index where the value was found (so data can be accessed),
706 or `-1` to indicate failure.
707
708         static int symset_find(struct symset *ss, unsigned short key)
709         {
710                 int lo = 0;
711                 int hi = ss->cnt;
712
713                 if (hi == 0)
714                         return -1;
715                 while (lo + 1 < hi) {
716                         int mid = (lo + hi) / 2;
717                         if (ss->syms[mid] <= key)
718                                 lo = mid;
719                         else
720                                 hi = mid;
721                 }
722                 if (ss->syms[lo] == key)
723                         return lo;
724                 return -1;
725         }
726
727 We will often want to form the union of two symsets.  When we do, we
728 will often want to know if anything changed (as they might mean there
729 is more work to do).  So `symset_union` reports whether anything was
730 added to the first set.  We use a slow quadratic approach as these
731 sets don't really get very big.  If profiles shows this to be a problem is
732 can be optimised later.
733
734         static int symset_union(struct symset *a, struct symset *b)
735         {
736                 int i;
737                 int added = 0;
738                 for (i = 0; i < b->cnt; i++)
739                         if (symset_find(a, b->syms[i]) < 0) {
740                                 unsigned short data = 0;
741                                 if (b->data != NO_DATA)
742                                         data = b->data[i];
743                                 symset_add(a, b->syms[i], data);
744                                 added++;
745                         }
746                 return added;
747         }
748
749 And of course we must be able to free a symset.
750
751         static void symset_free(struct symset ss)
752         {
753                 free(ss.syms);
754                 if (ss.data != NO_DATA)
755                         free(ss.data);
756         }
757
758 ### Symset Storage
759
760 Some symsets are simply stored somewhere appropriate in the `grammar`
761 data structure, others needs a bit of indirection.  This applies
762 particularly to "LA" sets.  These will be paired with "items" in an
763 "itemset".  As itemsets will be stored in a symset, the "LA" set needs to be
764 stored in the `data` field, so we need a mapping from a small (short)
765 number to an LA `symset`.
766
767 As mentioned earlier this involves creating a list of unique symsets.
768
769 For now, we just use a linear list sorted by insertion.  A skiplist
770 would be more efficient and may be added later.
771
772 ###### declarations
773
774         struct setlist {
775                 struct symset ss;
776                 int num;
777                 struct setlist *next;
778         };
779
780 ###### grammar fields
781         struct setlist *sets;
782         int nextset;
783
784 ###### functions
785
786         static int ss_cmp(struct symset a, struct symset b)
787         {
788                 int i;
789                 int diff = a.cnt - b.cnt;
790                 if (diff)
791                         return diff;
792                 for (i = 0; i < a.cnt; i++) {
793                         diff = (int)a.syms[i] - (int)b.syms[i];
794                         if (diff)
795                                 return diff;
796                 }
797                 return 0;
798         }
799
800         static int save_set(struct grammar *g, struct symset ss)
801         {
802                 struct setlist **sl = &g->sets;
803                 int cmp = 1;
804                 struct setlist *s;
805
806                 while (*sl && (cmp = ss_cmp((*sl)->ss, ss)) < 0)
807                         sl = & (*sl)->next;
808                 if (cmp == 0) {
809                         symset_free(ss);
810                         return (*sl)->num;
811                 }
812
813                 s = malloc(sizeof(*s));
814                 s->ss = ss;
815                 s->num = g->nextset;
816                 g->nextset += 1;
817                 s->next = *sl;
818                 *sl = s;
819                 return s->num;
820         }
821
822 Finding a set by number is currently performed by a simple linear search.
823 If this turns out to hurt performance, we can store the sets in a dynamic
824 array like the productions.
825
826         static struct symset set_find(struct grammar *g, int num)
827         {
828                 struct setlist *sl = g->sets;
829                 while (sl && sl->num != num)
830                         sl = sl->next;
831                 return sl->ss;
832         }
833
834
835 ### Setting `nullable`
836
837 We set `nullable` on the head symbol for any production for which all
838 the body symbols (if any) are nullable.  As this is a recursive
839 definition, any change in the `nullable` setting means that we need to
840 re-evaluate where it needs to be set.
841
842 We simply loop around performing the same calculations until no more
843 changes happen.
844
845 ###### symbol fields
846         int nullable;
847
848 ###### functions
849         static void set_nullable(struct grammar *g)
850         {
851                 int check_again = 1;
852                 while (check_again) {
853                         int p;
854                         check_again = 0;
855                         for (p = 0; p < g->production_count; p++) {
856                                 struct production *pr = g->productions[p];
857                                 int s;
858
859                                 if (pr->head->nullable)
860                                         continue;
861                                 for (s = 0; s < pr->body_size; s++)
862                                         if (! pr->body[s]->nullable)
863                                                 break;
864                                 if (s == pr->body_size) {
865                                         pr->head->nullable = 1;
866                                         check_again = 1;
867                                 }
868                         }
869                 }
870         }
871
872 ### Setting `can_eol`
873
874 In order to be able to ignore newline tokens when not relevant, but
875 still include them in the parse when needed, we will need to know
876 which states can start a "line-like" section of code.  We ignore
877 newlines when there is an indent since the most recent start of a
878 line-like section.
879
880 To know what is line-like, we first need to know which symbols can end
881 a line-like section, which is precisely those which can end with a
882 newline token.  These symbols don't necessarily alway end with a
883 newline, but they can.  Hence they are not described as "lines" but
884 only "line-like".
885
886 Clearly the `TK_newline` token can end with a newline.  Any symbol
887 which is the head of a production that contains a line-ending symbol
888 followed only by nullable symbols is also a line-ending symbol.  We
889 use a new field `can_eol` to record this attribute of symbols, and
890 compute it in a repetitive manner similar to `set_nullable`.
891
892 ###### symbol fields
893         int can_eol;
894
895 ###### functions
896         static void set_can_eol(struct grammar *g)
897         {
898                 int check_again = 1;
899                 g->symtab[TK_newline]->can_eol = 1;
900                 while (check_again) {
901                         int p;
902                         check_again = 0;
903                         for (p = 0; p < g->production_count; p++) {
904                                 struct production *pr = g->productions[p];
905                                 int s;
906
907                                 if (pr->head->can_eol)
908                                         continue;
909
910                                 for (s = pr->body_size - 1; s >= 0; s--) {
911                                         if (pr->body[s]->can_eol) {
912                                                 pr->head->can_eol = 1;
913                                                 check_again = 1;
914                                                 break;
915                                         }
916                                         if (!pr->body[s]->nullable)
917                                                 break;
918                                 }
919                         }
920                 }
921         }
922
923 ### Building the `first` sets
924
925 When calculating what can follow a particular non-terminal, we will need to
926 know what the "first" terminal in any subsequent non-terminal might be.  So
927 we calculate the `first` set for every non-terminal and store them in an
928 array.  We don't bother recording the "first" set for terminals as they are
929 trivial.
930
931 As the "first" for one symbol might depend on the "first" of another,
932 we repeat the calculations until no changes happen, just like with
933 `set_nullable`.  This makes use of the fact that `symset_union`
934 reports if any change happens.
935
936 The core of this which finds the "first" of part of a production body
937 will be reused for computing the "follow" sets, so we split it out
938 into a separate function.
939
940 ###### grammar fields
941         struct symset *first;
942
943 ###### functions
944
945         static int add_first(struct production *pr, int start,
946                              struct symset *target, struct grammar *g,
947                              int *to_end)
948         {
949                 int s;
950                 int changed = 0;
951                 for (s = start; s < pr->body_size; s++) {
952                         struct symbol *bs = pr->body[s];
953                         if (bs->type == Terminal) {
954                                 if (symset_find(target, bs->num) < 0) {
955                                         symset_add(target, bs->num, 0);
956                                         changed = 1;
957                                 }
958                                 break;
959                         } else if (symset_union(target, &g->first[bs->num]))
960                                 changed = 1;
961                         if (!bs->nullable)
962                                 break;
963                 }
964                 if (to_end)
965                         *to_end = (s == pr->body_size);
966                 return changed;
967         }
968
969         static void build_first(struct grammar *g)
970         {
971                 int check_again = 1;
972                 int s;
973                 g->first = calloc(g->num_syms, sizeof(g->first[0]));
974                 for (s = 0; s < g->num_syms; s++)
975                         g->first[s] = INIT_SYMSET;
976
977                 while (check_again) {
978                         int p;
979                         check_again = 0;
980                         for (p = 0; p < g->production_count; p++) {
981                                 struct production *pr = g->productions[p];
982                                 struct symset *head = &g->first[pr->head->num];
983
984                                 if (add_first(pr, 0, head, g, NULL))
985                                         check_again = 1;
986                         }
987                 }
988         }
989
990 ### Building the `follow` sets.
991
992 There are two different situations when we will want to generate "follow"
993 sets.  If we are doing an SLR analysis, we want to generate a single
994 "follow" set for each non-terminal in the grammar.  That is what is
995 happening here.  If we are doing an LALR or LR analysis we will want
996 to generate a separate "LA" set for each item.  We do that later
997 in state generation.
998
999 There are two parts to generating a "follow" set.  Firstly we look at
1000 every place that any non-terminal appears in the body of any
1001 production, and we find the set of possible "first" symbols after
1002 there.  This is done using `add_first` above and only needs to be done
1003 once as the "first" sets are now stable and will not change.
1004
1005 ###### follow code
1006
1007         for (p = 0; p < g->production_count; p++) {
1008                 struct production *pr = g->productions[p];
1009                 int b;
1010
1011                 for (b = 0; b < pr->body_size - 1; b++) {
1012                         struct symbol *bs = pr->body[b];
1013                         if (bs->type == Terminal)
1014                                 continue;
1015                         add_first(pr, b+1, &g->follow[bs->num], g, NULL);
1016                 }
1017         }
1018
1019 The second part is to add the "follow" set of the head of a production
1020 to the "follow" sets of the final symbol in the production, and any
1021 other symbol which is followed only by `nullable` symbols.  As this
1022 depends on "follow" itself we need to repeatedly perform the process
1023 until no further changes happen.
1024
1025 ###### follow code
1026
1027         for (again = 0, p = 0;
1028              p < g->production_count;
1029              p < g->production_count-1
1030                 ? p++ : again ? (again = 0, p = 0)
1031                               : p++) {
1032                 struct production *pr = g->productions[p];
1033                 int b;
1034
1035                 for (b = pr->body_size - 1; b >= 0; b--) {
1036                         struct symbol *bs = pr->body[b];
1037                         if (bs->type == Terminal)
1038                                 break;
1039                         if (symset_union(&g->follow[bs->num],
1040                                          &g->follow[pr->head->num]))
1041                                 again = 1;
1042                         if (!bs->nullable)
1043                                 break;
1044                 }
1045         }
1046
1047 We now just need to create and initialise the `follow` list to get a
1048 complete function.
1049
1050 ###### grammar fields
1051         struct symset *follow;
1052
1053 ###### functions
1054         static void build_follow(struct grammar *g)
1055         {
1056                 int s, again, p;
1057                 g->follow = calloc(g->num_syms, sizeof(g->follow[0]));
1058                 for (s = 0; s < g->num_syms; s++)
1059                         g->follow[s] = INIT_SYMSET;
1060                 ## follow code
1061         }
1062
1063 ### Building itemsets and states
1064
1065 There are three different levels of detail that can be chosen for
1066 building the itemsets and states for the LR grammar.  They are:
1067
1068 1. LR(0) or SLR(1), where no look-ahead is considered.
1069 2. LALR(1) where we build look-ahead sets with each item and merge
1070    the LA sets when we find two paths to the same "kernel" set of items.
1071 3. LR(1) where different look-ahead for any item in the set means
1072    a different state must be created.
1073
1074 ###### forward declarations
1075         enum grammar_type { LR0, LR05, SLR, LALR, LR1 };
1076
1077 We need to be able to look through existing states to see if a newly
1078 generated state already exists.  For now we use a simple sorted linked
1079 list.
1080
1081 An item is a pair of numbers: the production number and the position of
1082 "DOT", which is an index into the body of the production.
1083 As the numbers are not enormous we can combine them into a single "short"
1084 and store them in a `symset` - 4 bits for "DOT" and 12 bits for the
1085 production number (so 4000 productions with maximum of 15 symbols in the
1086 body).
1087
1088 Comparing the itemsets will be a little different to comparing symsets
1089 as we want to do the lookup after generating the "kernel" of an
1090 itemset, so we need to ignore the offset=zero items which are added during
1091 completion.
1092
1093 To facilitate this, we modify the "DOT" number so that "0" sorts to
1094 the end of the list in the symset, and then only compare items before
1095 the first "0".
1096
1097 ###### declarations
1098         static inline unsigned short item_num(int production, int index)
1099         {
1100                 return production | ((31-index) << 11);
1101         }
1102         static inline int item_prod(unsigned short item)
1103         {
1104                 return item & 0x7ff;
1105         }
1106         static inline int item_index(unsigned short item)
1107         {
1108                 return (31-(item >> 11)) & 0x1f;
1109         }
1110
1111 For LR(1) analysis we need to compare not just the itemset in a state
1112 but also the LA sets.  As we assign each unique LA set a number, we
1113 can just compare the symset and the data values together.
1114
1115 ###### functions
1116         static int itemset_cmp(struct symset a, struct symset b,
1117                                enum grammar_type type)
1118         {
1119                 int i;
1120                 int av, bv;
1121
1122                 for (i = 0;
1123                      i < a.cnt && i < b.cnt &&
1124                      item_index(a.syms[i]) > 0 &&
1125                      item_index(b.syms[i]) > 0;
1126                      i++) {
1127                         int diff = a.syms[i] - b.syms[i];
1128                         if (diff)
1129                                 return diff;
1130                         if (type == LR1) {
1131                                 diff = a.data[i] - b.data[i];
1132                                 if (diff)
1133                                         return diff;
1134                         }
1135                 }
1136                 if (i == a.cnt || item_index(a.syms[i]) == 0)
1137                         av = -1;
1138                 else
1139                         av = a.syms[i];
1140                 if (i == b.cnt || item_index(b.syms[i]) == 0)
1141                         bv = -1;
1142                 else
1143                         bv = b.syms[i];
1144                 if (av - bv)
1145                         return av - bv;
1146                 if (type < LR1 || av == -1)
1147                         return 0;
1148                 return
1149                         a.data[i] - b.data[i];
1150         }
1151
1152 And now we can build the list of itemsets.  The lookup routine returns
1153 both a success flag and a pointer to where in the list an insert
1154 should happen, so we don't need to search a second time.
1155
1156 ###### declarations
1157         struct itemset {
1158                 struct itemset *next;
1159                 short state;
1160                 struct symset items;
1161                 struct symset go_to;
1162                 char completed;
1163                 char starts_line;
1164         };
1165
1166 ###### grammar fields
1167         struct itemset *items;
1168         int states;
1169
1170 ###### functions
1171         static int itemset_find(struct grammar *g, struct itemset ***where,
1172                                 struct symset kernel, enum grammar_type type)
1173         {
1174                 struct itemset **ip;
1175
1176                 for (ip = &g->items; *ip ; ip = & (*ip)->next) {
1177                         struct itemset *i = *ip;
1178                         int diff;
1179                         diff = itemset_cmp(i->items, kernel, type);
1180                         if (diff < 0)
1181                                 continue;
1182                         if (diff > 0)
1183                                 break;
1184                         /* found */
1185                         *where = ip;
1186                         return 1;
1187                 }
1188                 *where = ip;
1189                 return 0;
1190         }
1191
1192 Adding an itemset may require merging the LA sets if LALR analysis is
1193 happening. If any new LA set adds any symbols that weren't in the old LA set, we
1194 clear the `completed` flag so that the dependants of this itemset will be
1195 recalculated and their LA sets updated.
1196
1197 `add_itemset` must consume the symsets it is passed, either by adding
1198 them to a data structure, of freeing them.
1199
1200         static int add_itemset(struct grammar *g, struct symset ss,
1201                                enum grammar_type type, int starts_line)
1202         {
1203                 struct itemset **where, *is;
1204                 int i;
1205                 int found = itemset_find(g, &where, ss, type);
1206                 if (!found) {
1207                         is = calloc(1, sizeof(*is));
1208                         is->state = g->states;
1209                         g->states += 1;
1210                         is->items = ss;
1211                         is->next = *where;
1212                         is->go_to = INIT_DATASET;
1213                         is->starts_line = starts_line;
1214                         *where = is;
1215                         return is->state;
1216                 }
1217                 is = *where;
1218                 if (type != LALR) {
1219                         symset_free(ss);
1220                         return is->state;
1221                 }
1222                 for (i = 0; i < ss.cnt; i++) {
1223                         struct symset temp = INIT_SYMSET, s;
1224                         if (ss.data[i] == is->items.data[i])
1225                                 continue;
1226                         s = set_find(g, is->items.data[i]);
1227                         symset_union(&temp, &s);
1228                         s = set_find(g, ss.data[i]);
1229                         if (symset_union(&temp, &s)) {
1230                                 is->items.data[i] = save_set(g, temp);
1231                                 is->completed = 0;
1232                         } else
1233                                 symset_free(temp);
1234                 }
1235                 symset_free(ss);
1236                 return is->state;
1237         }
1238
1239 #### The build
1240
1241 To build all the itemsets, we first insert the initial itemset made
1242 from production zero, complete each itemset, and then generate new
1243 itemsets from old until no new ones can be made.
1244
1245 Completing an itemset means finding all the items where "DOT" is followed by
1246 a nonterminal and adding "DOT=0" items for every production from that
1247 non-terminal - providing each item hasn't already been added.
1248
1249 If LA sets are needed, the LA set for each new item is found using
1250 `add_first` which was developed earlier for `FIRST` and `FOLLOW`.  This may
1251 be supplemented by the LA set for the item which produce the new item.
1252
1253 We also collect a set of all symbols which follow "DOT" (in `done`) as this
1254 is used in the next stage.
1255
1256 NOTE: precedence handling should happen here - I haven't written this yet
1257 though.
1258
1259 ###### complete itemset
1260         for (i = 0; i < is->items.cnt; i++) {
1261                 int p = item_prod(is->items.syms[i]);
1262                 int bs = item_index(is->items.syms[i]);
1263                 struct production *pr = g->productions[p];
1264                 int p2;
1265                 struct symbol *s;
1266                 struct symset LA = INIT_SYMSET;
1267                 unsigned short sn = 0;
1268
1269                 if (bs == pr->body_size)
1270                         continue;
1271                 s = pr->body[bs];
1272                 if (symset_find(&done, s->num) < 0)
1273                         symset_add(&done, s->num, 0);
1274                 if (s->type != Nonterminal)
1275                         continue;
1276                 again = 1;
1277                 if (type >= LALR) {
1278                         // Need the LA set.
1279                         int to_end;
1280                         add_first(pr, bs+1, &LA, g, &to_end);
1281                         if (to_end) {
1282                                 struct symset ss = set_find(g, is->items.data[i]);
1283                                 symset_union(&LA, &ss);
1284                         }
1285                         sn = save_set(g, LA);
1286                         LA = set_find(g, sn);
1287                 }
1288
1289                 /* Add productions for this symbol */
1290                 for (p2 = s->first_production;
1291                      p2 < g->production_count &&
1292                       g->productions[p2]->head == s;
1293                      p2++) {
1294                         int itm = item_num(p2, 0);
1295                         int pos = symset_find(&is->items, itm);
1296                         if (pos < 0) {
1297                                 symset_add(&is->items, itm, sn);
1298                                 /* Will have re-ordered, so start
1299                                  * from beginning again */
1300                                 i = -1;
1301                         } else if (type >= LALR) {
1302                                 struct symset ss = set_find(g, is->items.data[pos]);
1303                                 struct symset tmp = INIT_SYMSET;
1304
1305                                 symset_union(&tmp, &ss);
1306                                 if (symset_union(&tmp, &LA)) {
1307                                         is->items.data[pos] = save_set(g, tmp);
1308                                         i = -1;
1309                                 }else
1310                                         symset_free(tmp);
1311                         }
1312                 }
1313         }
1314
1315 For each symbol we found (and placed in `done`) we collect all the items for
1316 which this symbol is next, and create a new itemset with "DOT" advanced over
1317 the symbol.  This is then added to the collection of itemsets (or merged
1318 with a pre-existing itemset).
1319
1320 ###### derive itemsets
1321         // Now we have a completed itemset, so we need to
1322         // compute all the 'next' itemsets and create them
1323         // if they don't exist.
1324         for (i = 0; i < done.cnt; i++) {
1325                 int j;
1326                 unsigned short state;
1327                 int starts_line = 0;
1328                 struct symbol *sym = g->symtab[done.syms[i]];
1329                 struct symset newitemset = INIT_SYMSET;
1330                 if (type >= LALR)
1331                         newitemset = INIT_DATASET;
1332
1333                 if (sym->can_eol ||
1334                     (sym->nullable && is->starts_line))
1335                         starts_line = 1;
1336                 for (j = 0; j < is->items.cnt; j++) {
1337                         int itm = is->items.syms[j];
1338                         int p = item_prod(itm);
1339                         int bp = item_index(itm);
1340                         struct production *pr = g->productions[p];
1341                         unsigned short la = 0;
1342                         int pos;
1343
1344                         if (bp == pr->body_size)
1345                                 continue;
1346                         if (pr->body[bp] != sym)
1347                                 continue;
1348                         if (type >= LALR)
1349                                 la = is->items.data[j];
1350                         pos = symset_find(&newitemset, pr->head->num);
1351                         if (pos < 0)
1352                                 symset_add(&newitemset, item_num(p, bp+1), la);
1353                         else if (type >= LALR) {
1354                                 // Need to merge la set.
1355                                 int la2 = newitemset.data[pos];
1356                                 if (la != la2) {
1357                                         struct symset ss = set_find(g, la2);
1358                                         struct symset LA = INIT_SYMSET;
1359                                         symset_union(&LA, &ss);
1360                                         ss = set_find(g, la);
1361                                         if (symset_union(&LA, &ss))
1362                                                 newitemset.data[pos] = save_set(g, LA);
1363                                         else
1364                                                 symset_free(LA);
1365                                 }
1366                         }
1367                 }
1368                 state = add_itemset(g, newitemset, type, starts_line);
1369                 if (symset_find(&is->go_to, done.syms[i]) < 0)
1370                         symset_add(&is->go_to, done.syms[i], state);
1371         }
1372
1373 All that is left is to crate the initial itemset from production zero, and
1374 with `TK_eof` as the LA set.
1375
1376 ###### functions
1377         static void build_itemsets(struct grammar *g, enum grammar_type type)
1378         {
1379                 struct symset first = INIT_SYMSET;
1380                 struct itemset *is;
1381                 int again;
1382                 unsigned short la = 0;
1383                 if (type >= LALR) {
1384                         // LA set just has eof
1385                         struct symset eof = INIT_SYMSET;
1386                         symset_add(&eof, TK_eof, 0);
1387                         la = save_set(g, eof);
1388                         first = INIT_DATASET;
1389                 }
1390                 // production 0, offset 0 (with no data)
1391                 symset_add(&first, item_num(0, 0), la);
1392                 add_itemset(g, first, type, g->productions[0]->body[0]->can_eol);
1393                 for (again = 0, is = g->items;
1394                      is;
1395                      is = is->next ?: again ? (again = 0, g->items) : NULL) {
1396                         int i;
1397                         struct symset done = INIT_SYMSET;
1398                         if (is->completed)
1399                                 continue;
1400                         is->completed = 1;
1401                         again = 1;
1402                         ## complete itemset
1403                         ## derive itemsets
1404                         symset_free(done);
1405                 }
1406         }
1407
1408 ### Completing the analysis.
1409
1410 The exact process of analysis depends on which level was requested.  For
1411 `LR0` and `LR05` we don't need first and follow sets at all.  For `LALR` and
1412 `LR1` we need first, but not follow.  For `SLR` we need both.
1413
1414 We don't build the "action" tables that you might expect as the parser
1415 doesn't use them.  They will be calculated to some extent if needed for
1416 a report.
1417
1418 Once we have built everything we allocate arrays for the two lists:
1419 symbols and itemsets.  This allows more efficient access during reporting.
1420 The symbols are grouped as terminals and non-terminals and we record the
1421 changeover point in `first_nonterm`.
1422
1423 ###### grammar fields
1424         struct symbol **symtab;
1425         struct itemset **statetab;
1426         int first_nonterm;
1427
1428 ###### grammar_analyse
1429
1430         static void grammar_analyse(struct grammar *g, enum grammar_type type)
1431         {
1432                 struct symbol *s;
1433                 struct itemset *is;
1434                 int snum = TK_reserved;
1435                 for (s = g->syms; s; s = s->next)
1436                         if (s->num < 0 && s->type == Terminal) {
1437                                 s->num = snum;
1438                                 snum++;
1439                         }
1440                 g->first_nonterm = snum;
1441                 for (s = g->syms; s; s = s->next)
1442                         if (s->num < 0) {
1443                                 s->num = snum;
1444                                 snum++;
1445                         }
1446                 g->num_syms = snum;
1447                 g->symtab = calloc(g->num_syms, sizeof(g->symtab[0]));
1448                 for (s = g->syms; s; s = s->next)
1449                         g->symtab[s->num] = s;
1450
1451                 set_nullable(g);
1452                 set_can_eol(g);
1453                 if (type >= SLR)
1454                         build_first(g);
1455
1456                 if (type == SLR)
1457                         build_follow(g);
1458
1459                 build_itemsets(g, type);
1460
1461                 g->statetab = calloc(g->states, sizeof(g->statetab[0]));
1462                 for (is = g->items; is ; is = is->next)
1463                         g->statetab[is->state] = is;
1464         }
1465
1466 ## Reporting on the Grammar
1467
1468 The purpose of the report is to give the grammar developer insight into
1469 how the grammar parser will work.  It is basically a structured dump of
1470 all the tables that have been generated, plus a description of any conflicts.
1471
1472 ###### grammar_report
1473         static int grammar_report(struct grammar *g, enum grammar_type type)
1474         {
1475                 report_symbols(g);
1476                 if (g->follow)
1477                         report_follow(g);
1478                 report_itemsets(g);
1479                 return report_conflicts(g, type);
1480         }
1481
1482 Firstly we have the complete list of symbols, together with the
1483 "FIRST" set if that was generated.  We add a mark to each symbol to
1484 show if it can end in a newline (`>`), or if it is nullable (`.`).
1485
1486 ###### functions
1487
1488         static void report_symbols(struct grammar *g)
1489         {
1490                 int n;
1491                 if (g->first)
1492                         printf("SYMBOLS + FIRST:\n");
1493                 else
1494                         printf("SYMBOLS:\n");
1495
1496                 for (n = 0; n < g->num_syms; n++) {
1497                         struct symbol *s = g->symtab[n];
1498                         if (!s)
1499                                 continue;
1500
1501                         printf(" %c%c%3d%c: ",
1502                                s->nullable ? '.':' ',
1503                                s->can_eol ? '>':' ',
1504                                s->num, symtypes[s->type]);
1505                         prtxt(s->name);
1506                         if (s->precedence)
1507                                 printf(" (%d%s)", s->precedence,
1508                                        assoc_names[s->assoc]);
1509
1510                         if (g->first && s->type == Nonterminal) {
1511                                 int j;
1512                                 char c = ':';
1513                                 for (j = 0; j < g->first[n].cnt; j++) {
1514                                         printf("%c ", c);
1515                                         c = ',';
1516                                         prtxt(g->symtab[g->first[n].syms[j]]->name);
1517                                 }
1518                         }
1519                         printf("\n");
1520                 }
1521         }
1522
1523 Then we have the follow sets if they were computed.
1524
1525         static void report_follow(struct grammar *g)
1526         {
1527                 int n;
1528                 printf("FOLLOW:\n");
1529                 for (n = 0; n < g->num_syms; n++)
1530                         if (g->follow[n].cnt) {
1531                                 int j;
1532                                 char c = ':';
1533                                 printf("  ");
1534                                 prtxt(g->symtab[n]->name);
1535                                 for (j = 0; j < g->follow[n].cnt; j++) {
1536                                         printf("%c ", c);
1537                                         c = ',';
1538                                         prtxt(g->symtab[g->follow[n].syms[j]]->name);
1539                                 }
1540                                 printf("\n");
1541                         }
1542         }
1543
1544 And finally the item sets.  These include the GO TO tables and, for
1545 LALR and LR1, the LA set for each item.  Lots of stuff, so we break
1546 it up a bit.  First the items, with production number and associativity.
1547
1548         static void report_item(struct grammar *g, int itm)
1549         {
1550                 int p = item_prod(itm);
1551                 int dot = item_index(itm);
1552                 struct production *pr = g->productions[p];
1553                 int i;
1554
1555                 printf("    ");
1556                 prtxt(pr->head->name);
1557                 printf(" ->");
1558                 for (i = 0; i < pr->body_size; i++) {
1559                         printf(" %s", (dot == i ? ". ": ""));
1560                         prtxt(pr->body[i]->name);
1561                 }
1562                 if (dot == pr->body_size)
1563                         printf(" .");
1564                 printf(" [%d]", p);
1565                 if (pr->precedence)
1566                         printf(" (%d%s)", pr->precedence,
1567                                assoc_names[pr->assoc]);
1568                 printf("\n");
1569         }
1570
1571 The LA sets which are (possibly) reported with each item:
1572
1573         static void report_la(struct grammar *g, int lanum)
1574         {
1575                 struct symset la = set_find(g, lanum);
1576                 int i;
1577                 char c = ':';
1578
1579                 printf("        LOOK AHEAD(%d)", lanum);
1580                 for (i = 0; i < la.cnt; i++) {
1581                         printf("%c ", c);
1582                         c = ',';
1583                         prtxt(g->symtab[la.syms[i]]->name);
1584                 }
1585                 printf("\n");
1586         }
1587
1588 Then the go to sets:
1589
1590
1591         static void report_goto(struct grammar *g, struct symset gt)
1592         {
1593                 int i;
1594                 printf("    GOTO:\n");
1595
1596                 for (i = 0; i < gt.cnt; i++) {
1597                         printf("      ");
1598                         prtxt(g->symtab[gt.syms[i]]->name);
1599                         printf(" -> %d\n", gt.data[i]);
1600                 }
1601         }
1602
1603 Now we can report all the item sets complete with items, LA sets, and GO TO.
1604
1605         static void report_itemsets(struct grammar *g)
1606         {
1607                 int s;
1608                 printf("ITEM SETS(%d)\n", g->states);
1609                 for (s = 0; s < g->states; s++) {
1610                         int j;
1611                         struct itemset *is = g->statetab[s];
1612                         printf("  Itemset %d:%s\n", s, is->starts_line?" (startsline)":"");
1613                         for (j = 0; j < is->items.cnt; j++) {
1614                                 report_item(g, is->items.syms[j]);
1615                                 if (is->items.data != NO_DATA)
1616                                         report_la(g, is->items.data[j]);
1617                         }
1618                         report_goto(g, is->go_to);
1619                 }
1620         }
1621
1622 ### Reporting conflicts
1623
1624 Conflict detection varies a lot among different analysis levels.  However
1625 LR0 and LR0.5 are quite similar - having no follow sets, and SLR, LALR and
1626 LR1 are also similar as they have FOLLOW or LA sets.
1627
1628 ###### functions
1629
1630         ## conflict functions
1631
1632         static int report_conflicts(struct grammar *g, enum grammar_type type)
1633         {
1634                 int cnt = 0;
1635                 printf("Conflicts:\n");
1636                 if (type < SLR)
1637                         cnt = conflicts_lr0(g, type);
1638                 else
1639                         cnt = conflicts_slr(g, type);
1640                 if (cnt == 0)
1641                         printf(" - no conflicts\n");
1642                 return cnt;
1643         }
1644
1645 LR0 conflicts are any state which have both a reducible item and
1646 a shiftable item, or two reducible items.
1647
1648 LR05 conflicts only occurs if two possibly reductions exist,
1649 as shifts always over-ride reductions.
1650
1651 ###### conflict functions
1652         static int conflicts_lr0(struct grammar *g, enum grammar_type type)
1653         {
1654                 int i;
1655                 int cnt = 0;
1656                 for (i = 0; i < g->states; i++) {
1657                         struct itemset *is = g->statetab[i];
1658                         int last_reduce = -1;
1659                         int prev_reduce = -1;
1660                         int last_shift = -1;
1661                         int j;
1662                         if (!is)
1663                                 continue;
1664                         for (j = 0; j < is->items.cnt; j++) {
1665                                 int itm = is->items.syms[j];
1666                                 int p = item_prod(itm);
1667                                 int bp = item_index(itm);
1668                                 struct production *pr = g->productions[p];
1669
1670                                 if (bp == pr->body_size) {
1671                                         prev_reduce = last_reduce;
1672                                         last_reduce = j;
1673                                         continue;
1674                                 }
1675                                 if (pr->body[bp]->type == Terminal)
1676                                         last_shift = j;
1677                         }
1678                         if (type == LR0 && last_reduce >= 0 && last_shift >= 0) {
1679                                 printf("  State %d has both SHIFT and REDUCE:\n", i);
1680                                 report_item(g, is->items.syms[last_shift]);
1681                                 report_item(g, is->items.syms[last_reduce]);
1682                                 cnt++;
1683                         }
1684                         if (prev_reduce >= 0) {
1685                                 printf("  State %d has 2 (or more) reducible items\n", i);
1686                                 report_item(g, is->items.syms[prev_reduce]);
1687                                 report_item(g, is->items.syms[last_reduce]);
1688                                 cnt++;
1689                         }
1690                 }
1691                 return cnt;
1692         }
1693
1694 SLR, LALR, and LR1 conflicts happen if two reducible items have over-lapping
1695 look ahead, or if a symbol in a look-ahead can be shifted.  They differ only
1696 in the source of the look ahead set.
1697
1698 We build two datasets to reflect the "action" table: one which maps
1699 terminals to items where that terminal could be shifted and another
1700 which maps terminals to items that could be reduced when the terminal
1701 is in look-ahead.  We report when we get conflicts between the two.
1702
1703         static int conflicts_slr(struct grammar *g, enum grammar_type type)
1704         {
1705                 int i;
1706                 int cnt = 0;
1707
1708                 for (i = 0; i < g->states; i++) {
1709                         struct itemset *is = g->statetab[i];
1710                         struct symset shifts = INIT_DATASET;
1711                         struct symset reduce = INIT_DATASET;
1712                         int j;
1713                         if (!is)
1714                                 continue;
1715                         /* First collect the shifts */
1716                         for (j = 0; j < is->items.cnt; j++) {
1717                                 unsigned short itm = is->items.syms[j];
1718                                 int p = item_prod(itm);
1719                                 int bp = item_index(itm);
1720                                 struct production *pr = g->productions[p];
1721
1722                                 if (bp < pr->body_size &&
1723                                     pr->body[bp]->type == Terminal) {
1724                                         /* shiftable */
1725                                         int sym = pr->body[bp]->num;
1726                                         if (symset_find(&shifts, sym) < 0)
1727                                                 symset_add(&shifts, sym, itm);
1728                                 }
1729                         }
1730                         /* Now look for reduction and conflicts */
1731                         for (j = 0; j < is->items.cnt; j++) {
1732                                 unsigned short itm = is->items.syms[j];
1733                                 int p = item_prod(itm);
1734                                 int bp = item_index(itm);
1735                                 struct production *pr = g->productions[p];
1736
1737                                 if (bp < pr->body_size)
1738                                         continue;
1739                                 /* reducible */
1740                                 struct symset la;
1741                                 if (type == SLR)
1742                                         la = g->follow[pr->head->num];
1743                                 else
1744                                         la = set_find(g, is->items.data[j]);
1745                                 int k;
1746                                 for (k = 0; k < la.cnt; k++) {
1747                                         int pos = symset_find(&shifts, la.syms[k]);
1748                                         if (pos >= 0) {
1749                                                 printf("  State %d has SHIFT/REDUCE conflict on ", i);
1750                                                 prtxt(g->symtab[la.syms[k]]->name);
1751                                                 printf(":\n");
1752                                                 report_item(g, shifts.data[pos]);
1753                                                 report_item(g, itm);
1754                                                 cnt++;
1755                                         }
1756                                         pos = symset_find(&reduce, la.syms[k]);
1757                                         if (pos < 0) {
1758                                                 symset_add(&reduce, la.syms[k], itm);
1759                                                 continue;
1760                                         }
1761                                         printf("  State %d has REDUCE/REDUCE conflict on ", i);
1762                                         prtxt(g->symtab[la.syms[k]]->name);
1763                                         printf(":\n");
1764                                         report_item(g, itm);
1765                                         report_item(g, reduce.data[pos]);
1766                                         cnt++;
1767                                 }
1768                         }
1769                         symset_free(shifts);
1770                         symset_free(reduce);
1771                 }
1772                 return cnt;
1773         }
1774
1775
1776 ## Generating the parser
1777
1778 The exported part of the parser is the `parse_XX` function, where the name
1779 `XX` is based on the name of the parser files.
1780
1781 This takes a `code_node`, a partially initialized `token_config`, and an
1782 optional `FILE` to send tracing to.  The `token_config` gets the list of
1783 known words added and then is used with the `code_node` to initialize the
1784 scanner.
1785
1786 `parse_XX` then calls the library function `parser_run` to actually complete
1787 the parse.  This needs the `states` table and function to call the various
1788 pieces of code provided in the grammar file, so they are generated first.
1789
1790 ###### parser_generate
1791
1792         static void gen_parser(FILE *f, struct grammar *g, char *file, char *name)
1793         {
1794                 gen_known(f, g);
1795                 gen_non_term(f, g);
1796                 gen_goto(f, g);
1797                 gen_states(f, g);
1798                 gen_reduce(f, g, file);
1799                 gen_free(f, g);
1800
1801                 fprintf(f, "#line 0 \"gen_parser\"\n");
1802                 fprintf(f, "void *parse_%s(struct code_node *code, struct token_config *config, FILE *trace)\n",
1803                         name);
1804                 fprintf(f, "{\n");
1805                 fprintf(f, "\tstruct token_state *tokens;\n");
1806                 fprintf(f, "\tconfig->words_marks = known;\n");
1807                 fprintf(f, "\tconfig->known_count = sizeof(known)/sizeof(known[0]);\n");
1808                 fprintf(f, "\tconfig->ignored |= (1 << TK_line_comment) | (1 << TK_block_comment);\n");
1809                 fprintf(f, "\ttokens = token_open(code, config);\n");
1810                 fprintf(f, "\tvoid *rv = parser_run(tokens, states, do_reduce, do_free, trace, non_term, config);\n");
1811                 fprintf(f, "\ttoken_close(tokens);\n");
1812                 fprintf(f, "\treturn rv;\n");
1813                 fprintf(f, "}\n\n");
1814         }
1815
1816 ### Known words table
1817
1818 The known words table is simply an array of terminal symbols.
1819 The table of nonterminals used for tracing is a similar array.
1820
1821 ###### functions
1822
1823         static void gen_known(FILE *f, struct grammar *g)
1824         {
1825                 int i;
1826                 fprintf(f, "#line 0 \"gen_known\"\n");
1827                 fprintf(f, "static const char *known[] = {\n");
1828                 for (i = TK_reserved;
1829                      i < g->num_syms && g->symtab[i]->type == Terminal;
1830                      i++)
1831                         fprintf(f, "\t\"%.*s\",\n", g->symtab[i]->name.len,
1832                                 g->symtab[i]->name.txt);
1833                 fprintf(f, "};\n\n");
1834         }
1835
1836         static void gen_non_term(FILE *f, struct grammar *g)
1837         {
1838                 int i;
1839                 fprintf(f, "#line 0 \"gen_non_term\"\n");
1840                 fprintf(f, "static const char *non_term[] = {\n");
1841                 for (i = TK_reserved;
1842                      i < g->num_syms;
1843                      i++)
1844                         if (g->symtab[i]->type == Nonterminal)
1845                                 fprintf(f, "\t\"%.*s\",\n", g->symtab[i]->name.len,
1846                                         g->symtab[i]->name.txt);
1847                 fprintf(f, "};\n\n");
1848         }
1849
1850 ### States and the goto tables.
1851
1852 For each state we record the goto table, the reducible production if
1853 there is one, or a symbol to shift for error recovery.
1854 Some of the details of the reducible production are stored in the
1855 `do_reduce` function to come later.  Here we store the production number,
1856 the body size (useful for stack management) and the resulting symbol (useful
1857 for knowing how to free data later).
1858
1859 The go to table is stored in a simple array of `sym` and corresponding
1860 `state`.
1861
1862 ###### exported types
1863
1864         struct lookup {
1865                 short sym;
1866                 short state;
1867         };
1868         struct state {
1869                 short go_to_cnt;
1870                 const struct lookup * go_to;
1871                 short reduce_prod;
1872                 short reduce_size;
1873                 short reduce_sym;
1874                 short shift_sym;
1875                 short starts_line;
1876         };
1877
1878
1879 ###### functions
1880
1881         static void gen_goto(FILE *f, struct grammar *g)
1882         {
1883                 int i;
1884                 fprintf(f, "#line 0 \"gen_goto\"\n");
1885                 for (i = 0; i < g->states; i++) {
1886                         int j;
1887                         fprintf(f, "static const struct lookup goto_%d[] = {\n",
1888                                 i);
1889                         struct symset gt = g->statetab[i]->go_to;
1890                         for (j = 0; j < gt.cnt; j++)
1891                                 fprintf(f, "\t{ %d, %d },\n",
1892                                         gt.syms[j], gt.data[j]);
1893                         fprintf(f, "};\n");
1894                 }
1895         }
1896
1897 ###### functions
1898
1899         static void gen_states(FILE *f, struct grammar *g)
1900         {
1901                 int i;
1902                 fprintf(f, "#line 0 \"gen_states\"\n");
1903                 fprintf(f, "static const struct state states[] = {\n");
1904                 for (i = 0; i < g->states; i++) {
1905                         struct itemset *is = g->statetab[i];
1906                         int j, prod = -1, prod_len;
1907                         int shift_sym = -1;
1908                         int shift_len = 0, shift_remain = 0;
1909                         for (j = 0; j < is->items.cnt; j++) {
1910                                 int itm = is->items.syms[j];
1911                                 int p = item_prod(itm);
1912                                 int bp = item_index(itm);
1913                                 struct production *pr = g->productions[p];
1914
1915                                 if (bp < pr->body_size) {
1916                                         if (shift_sym < 0 ||
1917                                             (shift_len == bp && shift_remain > pr->body_size - bp)) {
1918                                                 shift_sym = pr->body[bp]->num;
1919                                                 shift_len = bp;
1920                                                 shift_remain = pr->body_size - bp;
1921                                         }
1922                                         continue;
1923                                 }
1924                                 /* This is what we reduce */
1925                                 if (prod < 0 || prod_len < pr->body_size) {
1926                                         prod = p;
1927                                         prod_len = pr->body_size;
1928                                 }
1929                         }
1930
1931                         if (prod >= 0)
1932                                 fprintf(f, "\t[%d] = { %d, goto_%d, %d, %d, %d, 0, %d },\n",
1933                                         i, is->go_to.cnt, i, prod,
1934                                         g->productions[prod]->body_size,
1935                                         g->productions[prod]->head->num,
1936                                         is->starts_line);
1937                         else
1938                                 fprintf(f, "\t[%d] = { %d, goto_%d, -1, -1, -1, %d, %d },\n",
1939                                         i, is->go_to.cnt, i, shift_sym,
1940                                         is->starts_line);
1941                 }
1942                 fprintf(f, "};\n\n");
1943         }
1944
1945 ### The `do_reduce` function and the code
1946
1947 When the parser engine decides to reduce a production, it calls `do_reduce`.
1948 This has two functions.
1949
1950 Firstly, if a non-NULL `trace` file is passed, it prints out details of the
1951 production being reduced.  Secondly it runs the code that was included with
1952 the production if any.
1953
1954 This code needs to be able to store data somewhere.  Rather than requiring
1955 `do_reduce` to `malloc` that "somewhere", we pass in a large buffer and have
1956 `do_reduce` return the size to be saved.
1957
1958 In order for the code to access "global" context, we pass in the
1959 "config" pointer that was passed to parser function.  If the `struct
1960 token_config` is embedded in some larger structure, the reducing code
1961 can access the larger structure using pointer manipulation.
1962
1963 The code fragment requires translation when written out.  Any `$N` needs to
1964 be converted to a reference either to that buffer (if `$0`) or to the
1965 structure returned by a previous reduction.  These pointers need to be cast
1966 to the appropriate type for each access.  All this is handling in
1967 `gen_code`.
1968
1969 `gen_code` also allows symbol references to contain a '`<`' as in '`$<2`'.
1970 This applied only to symbols with references (or pointers), not those with structures.
1971 The `<` implies that the reference it being moved out, so the object will not be
1972 automatically freed.  This is equivalent to assigning `NULL` to the pointer.
1973
1974 ###### functions
1975
1976         static void gen_code(struct production *p, FILE *f, struct grammar *g)
1977         {
1978                 char *c;
1979                 char *used = calloc(1, p->body_size);
1980                 int i;
1981
1982                 fprintf(f, "\t\t\t");
1983                 for (c = p->code.txt; c < p->code.txt + p->code.len; c++) {
1984                         int n;
1985                         int use = 0;
1986                         if (*c != '$') {
1987                                 fputc(*c, f);
1988                                 if (*c == '\n')
1989                                         fputs("\t\t\t", f);
1990                                 continue;
1991                         }
1992                         c++;
1993                         if (*c == '<') {
1994                                 use = 1;
1995                                 c++;
1996                         }
1997                         if (*c < '0' || *c > '9') {
1998                                 if (use)
1999                                         fputc('<', f);
2000                                 fputc(*c, f);
2001                                 continue;
2002                         }
2003                         n = *c - '0';
2004                         while (c[1] >= '0' && c[1] <= '9') {
2005                                 c += 1;
2006                                 n = n * 10 + *c - '0';
2007                         }
2008                         if (n == 0)
2009                                 fprintf(f, "(*(struct %.*s*%s)ret)",
2010                                         p->head->struct_name.len,
2011                                         p->head->struct_name.txt,
2012                                         p->head->isref ? "*":"");
2013                         else if (n > p->body_size)
2014                                 fprintf(f, "$%d", n);
2015                         else if (p->body[n-1]->type == Terminal)
2016                                 fprintf(f, "(*(struct token *)body[%d])",
2017                                         n-1);
2018                         else if (p->body[n-1]->struct_name.txt == NULL)
2019                                 fprintf(f, "$%d", n);
2020                         else {
2021                                 fprintf(f, "(*(struct %.*s*%s)body[%d])",
2022                                         p->body[n-1]->struct_name.len,
2023                                         p->body[n-1]->struct_name.txt,
2024                                         p->body[n-1]->isref ? "*":"", n-1);
2025                                 used[n-1] = use;
2026                         }
2027                 }
2028                 fputs("\n", f);
2029                 for (i = 0; i < p->body_size; i++) {
2030                         if (p->body[i]->struct_name.txt &&
2031                             p->body[i]->isref &&
2032                             used[i])
2033                                 // assume this has been copied out
2034                                 fprintf(f, "\t\t*(void**)body[%d] = NULL;\n", i);
2035                 }
2036                 free(used);
2037         }
2038
2039 ###### functions
2040
2041         static void gen_reduce(FILE *f, struct grammar *g, char *file)
2042         {
2043                 int i;
2044                 fprintf(f, "#line 0 \"gen_reduce\"\n");
2045                 fprintf(f, "static int do_reduce(int prod, void **body, struct token_config *config, void *ret)\n");
2046                 fprintf(f, "{\n");
2047                 fprintf(f, "\tint ret_size = 0;\n");
2048
2049                 fprintf(f, "\tswitch(prod) {\n");
2050                 for (i = 0; i < g->production_count; i++) {
2051                         struct production *p = g->productions[i];
2052                         fprintf(f, "\tcase %d:\n", i);
2053
2054                         if (p->code.txt)
2055                                 gen_code(p, f, g);
2056
2057                         if (p->head->struct_name.txt)
2058                                 fprintf(f, "\t\tret_size = sizeof(struct %.*s%s);\n",
2059                                         p->head->struct_name.len,
2060                                         p->head->struct_name.txt,
2061                                         p->head->isref ? "*":"");
2062
2063                         fprintf(f, "\t\tbreak;\n");
2064                 }
2065                 fprintf(f, "\t}\n\treturn ret_size;\n}\n\n");
2066         }
2067
2068 ### `do_free`
2069
2070 As each non-terminal can potentially cause a different type of data
2071 structure to be allocated and filled in, we need to be able to free it when
2072 done.
2073
2074 It is particularly important to have fine control over freeing during error
2075 recovery where individual stack frames might need to be freed.
2076
2077 For this, the grammar author is required to defined a `free_XX` function for
2078 each structure that is used by a non-terminal.  `do_free` will call whichever
2079 is appropriate given a symbol number, and will call `free` (as is
2080 appropriate for tokens on any terminal symbol.
2081
2082 ###### functions
2083
2084         static void gen_free(FILE *f, struct grammar *g)
2085         {
2086                 int i;
2087
2088                 fprintf(f, "#line 0 \"gen_free\"\n");
2089                 fprintf(f, "static void do_free(short sym, void *asn)\n");
2090                 fprintf(f, "{\n");
2091                 fprintf(f, "\tif (!asn) return;\n");
2092                 fprintf(f, "\tif (sym < %d) {\n", g->first_nonterm);
2093                 fprintf(f, "\t\tfree(asn);\n\t\treturn;\n\t}\n");
2094                 fprintf(f, "\tswitch(sym) {\n");
2095
2096                 for (i = 0; i < g->num_syms; i++) {
2097                         struct symbol *s = g->symtab[i];
2098                         if (!s ||
2099                             s->type != Nonterminal ||
2100                             s->struct_name.txt == NULL)
2101                                 continue;
2102
2103                         fprintf(f, "\tcase %d:\n", s->num);
2104                         if (s->isref) {
2105                                 fprintf(f, "\t\tfree_%.*s(*(void**)asn);\n",
2106                                         s->struct_name.len,
2107                                         s->struct_name.txt);
2108                                 fprintf(f, "\t\tfree(asn);\n");
2109                         } else
2110                                 fprintf(f, "\t\tfree_%.*s(asn);\n",
2111                                         s->struct_name.len,
2112                                         s->struct_name.txt);
2113                         fprintf(f, "\t\tbreak;\n");
2114                 }
2115                 fprintf(f, "\t}\n}\n\n");
2116         }
2117
2118 ## The main routine.
2119
2120 There are three key parts to the "main" function of parsergen: processing
2121 the arguments, loading the grammar file, and dealing with the grammar.
2122
2123 ### Argument processing.
2124
2125 Command line options allow the selection of analysis mode, name of output
2126 file, and whether or not a report should be generated.  By default we create
2127 a report only if no code output was requested.
2128
2129 The `parse_XX` function name uses the basename of the output file which
2130 should not have a suffix (`.c`).  `.c` is added to the given name for the
2131 code, and `.h` is added for the header (if header text is specifed in the
2132 grammar file).
2133
2134 ###### includes
2135         #include <getopt.h>
2136
2137 ###### declarations
2138         static const struct option long_options[] = {
2139                 { "LR0",        0, NULL, '0' },
2140                 { "LR05",       0, NULL, '5' },
2141                 { "SLR",        0, NULL, 'S' },
2142                 { "LALR",       0, NULL, 'L' },
2143                 { "LR1",        0, NULL, '1' },
2144                 { "tag",        1, NULL, 't' },
2145                 { "report",     0, NULL, 'R' },
2146                 { "output",     1, NULL, 'o' },
2147                 { NULL,         0, NULL, 0   }
2148         };
2149         const char *options = "05SL1t:Ro:";
2150
2151 ###### process arguments
2152         int opt;
2153         char *outfile = NULL;
2154         char *infile;
2155         char *name;
2156         char *tag = NULL;
2157         int report = 1;
2158         enum grammar_type type = LR05;
2159         while ((opt = getopt_long(argc, argv, options,
2160                                   long_options, NULL)) != -1) {
2161                 switch(opt) {
2162                 case '0':
2163                         type = LR0; break;
2164                 case '5':
2165                         type = LR05; break;
2166                 case 'S':
2167                         type = SLR; break;
2168                 case 'L':
2169                         type = LALR; break;
2170                 case '1':
2171                         type = LR1; break;
2172                 case 'R':
2173                         report = 2; break;
2174                 case 'o':
2175                         outfile = optarg; break;
2176                 case 't':
2177                         tag = optarg; break;
2178                 default:
2179                         fprintf(stderr, "Usage: parsergen ...\n");
2180                         exit(1);
2181                 }
2182         }
2183         if (optind < argc)
2184                 infile = argv[optind++];
2185         else {
2186                 fprintf(stderr, "No input file given\n");
2187                 exit(1);
2188         }
2189         if (outfile && report == 1)
2190                 report = 0;
2191         name = outfile;
2192         if (name && strchr(name, '/'))
2193                 name = strrchr(name, '/')+1;
2194
2195         if (optind < argc) {
2196                 fprintf(stderr, "Excess command line arguments\n");
2197                 exit(1);
2198         }
2199
2200 ### Loading the grammar file
2201
2202 To be able to run `mdcode` and `scanner` on the grammar we need to memory
2203 map it.
2204
2205 One we have extracted the code (with `mdcode`) we expect to find three
2206 sections: header, code, and grammar.  Anything else that is not
2207 excluded by the `--tag` option is an error.
2208
2209 "header" and "code" are optional, though it is hard to build a working
2210 parser with neither. "grammar" must be provided.
2211
2212 ###### includes
2213         #include <fcntl.h>
2214         #include <sys/mman.h>
2215         #include <errno.h>
2216
2217 ###### functions
2218         static int errs;
2219         static void pr_err(char *msg)
2220         {
2221                 errs++;
2222                 fprintf(stderr, "%s\n", msg);
2223         }
2224
2225 ###### load file
2226         struct section *table;
2227         int fd;
2228         int len;
2229         char *file;
2230         fd = open(infile, O_RDONLY);
2231         if (fd < 0) {
2232                 fprintf(stderr, "parsergen: cannot open %s: %s\n",
2233                         infile, strerror(errno));
2234                 exit(1);
2235         }
2236         len = lseek(fd, 0, 2);
2237         file = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
2238         table = code_extract(file, file+len, pr_err);
2239
2240         struct code_node *hdr = NULL;
2241         struct code_node *code = NULL;
2242         struct code_node *gram = NULL;
2243         for (s = table; s; s = s->next) {
2244                 struct text sec = s->section;
2245                 if (tag && !strip_tag(&sec, tag))
2246                         continue;
2247                 if (text_is(sec, "header"))
2248                         hdr = s->code;
2249                 else if (text_is(sec, "code"))
2250                         code = s->code;
2251                 else if (text_is(sec, "grammar"))
2252                         gram = s->code;
2253                 else {
2254                         fprintf(stderr, "Unknown content section: %.*s\n",
2255                                 s->section.len, s->section.txt);
2256                         rv |= 2;
2257                 }
2258         }
2259
2260 ### Processing the input
2261
2262 As we need to append an extention to a filename and then open it for
2263 writing, and we need to do this twice, it helps to have a separate function.
2264
2265 ###### functions
2266
2267         static FILE *open_ext(char *base, char *ext)
2268         {
2269                 char *fn = malloc(strlen(base) + strlen(ext) + 1);
2270                 FILE *f;
2271                 strcat(strcpy(fn, base), ext);
2272                 f = fopen(fn, "w");
2273                 free(fn);
2274                 return f;
2275         }
2276
2277 If we can read the grammar, then we analyse and optionally report on it.  If
2278 the report finds conflicts we will exit with an error status.
2279
2280 ###### process input
2281         struct grammar *g = NULL;
2282         if (gram == NULL) {
2283                 fprintf(stderr, "No grammar section provided\n");
2284                 rv |= 2;
2285         } else {
2286                 g = grammar_read(gram);
2287                 if (!g) {
2288                         fprintf(stderr, "Failure to parse grammar\n");
2289                         rv |= 2;
2290                 }
2291         }
2292         if (g) {
2293                 grammar_analyse(g, type);
2294                 if (report)
2295                         if (grammar_report(g, type))
2296                                 rv |= 1;
2297         }
2298
2299 If a headers section is defined, we write it out and include a declaration
2300 for the `parse_XX` function so it can be used from separate code.
2301
2302         if (rv == 0 && hdr && outfile) {
2303                 FILE *f = open_ext(outfile, ".h");
2304                 if (f) {
2305                         code_node_print(f, hdr, infile);
2306                         fprintf(f, "void *parse_%s(struct code_node *code, struct token_config *config, FILE *trace);\n",
2307                                 name);
2308                         fclose(f);
2309                 } else {
2310                         fprintf(stderr, "Cannot create %s.h\n",
2311                                 outfile);
2312                         rv |= 4;
2313                 }
2314         }
2315
2316 And if all goes well and an output file was provided, we create the `.c`
2317 file with the code section (if any) and the parser tables and function.
2318
2319         if (rv == 0 && outfile) {
2320                 FILE *f = open_ext(outfile, ".c");
2321                 if (f) {
2322                         if (code)
2323                                 code_node_print(f, code, infile);
2324                         gen_parser(f, g, infile, name);
2325                         fclose(f);
2326                 } else {
2327                         fprintf(stderr, "Cannot create %s.c\n",
2328                                 outfile);
2329                         rv |= 4;
2330                 }
2331         }
2332
2333 And that about wraps it up.  We need to set the locale so that UTF-8 is
2334 recognised properly, and link with `libicuuc` as `libmdcode` requires that.
2335
2336 ###### File: parsergen.mk
2337         parsergen : parsergen.o libscanner.o libmdcode.o
2338                 $(CC) $(CFLAGS) -o parsergen parsergen.o libscanner.o libmdcode.o -licuuc
2339
2340 ###### includes
2341         #include <locale.h>
2342
2343 ###### main
2344
2345         int main(int argc, char *argv[])
2346         {
2347                 struct section *s;
2348                 int rv = 0;
2349
2350                 setlocale(LC_ALL,"");
2351
2352                 ## process arguments
2353                 ## load file
2354                 ## process input
2355
2356                 return rv;
2357         }
2358
2359 ## The SHIFT/REDUCE parser
2360
2361 Having analysed the grammar and generated all the tables, we only need the
2362 shift/reduce engine to bring it all together.
2363
2364 ### Goto table lookup
2365
2366 The parser generator has nicely provided us with goto tables sorted by
2367 symbol number.  We need a binary search function to find a symbol in the
2368 table.
2369
2370 ###### parser functions
2371
2372         static int search(const struct state *l, int sym)
2373         {
2374                 int lo = 0;
2375                 int hi = l->go_to_cnt;
2376
2377                 if (hi == 0)
2378                         return -1;
2379                 while (lo + 1 < hi) {
2380                         int mid = (lo + hi) / 2;
2381                         if (l->go_to[mid].sym <= sym)
2382                                 lo = mid;
2383                         else
2384                                 hi = mid;
2385                 }
2386                 if (l->go_to[lo].sym == sym)
2387                         return l->go_to[lo].state;
2388                 else
2389                         return -1;
2390         }
2391
2392 ### The state stack.
2393
2394 The core data structure for the parser is the stack.  This tracks all the
2395 symbols that have been recognised or partially recognised.
2396
2397 The stack usually won't grow very large - maybe a few tens of entries.  So
2398 we dynamically resize and array as required but never bother to shrink it
2399 down again.
2400
2401 We keep the stack as two separate allocations.  One, `asn_stack` stores the
2402 "abstract syntax nodes" which are created by each reduction.  When we call
2403 `do_reduce` we need to pass an array of the `asn`s of the body of the
2404 production, and by keeping a separate `asn` stack, we can just pass a
2405 pointer into this stack.
2406
2407 The other allocation stores all other stack fields of which there are six.
2408 The `state` is the most important one and guides the parsing process.  The
2409 `sym` is nearly unnecessary.  However when we want to free entries from the
2410 `asn_stack`, it helps to know what type they are so we can call the right
2411 freeing function.  The symbol leads us to the right free function through
2412 `do_free`.
2413
2414 The `indents` count and the `starts_indented` flag track the line
2415 indents in the symbol.  These are used to allow indent information to
2416 guide parsing and error recovery.
2417
2418 `newline_permitted` keeps track of whether newlines should be ignored
2419 or not, and `starts_line` records if this state stated on a newline.
2420
2421 The stack is more properly seen as alternating states and symbols -
2422 states, like the 'DOT' in items, are between symbols.  Each frame in
2423 our stack holds a state and the symbol that was before it.  The
2424 bottom of stack holds the start state, but no symbol, as nothing came
2425 before the beginning.
2426
2427 ###### parser functions
2428
2429         struct parser {
2430                 struct frame {
2431                         short state;
2432                         short newline_permitted;
2433
2434                         short sym;
2435                         short starts_indented;
2436                         short indents;
2437                 } *stack;
2438                 void **asn_stack;
2439                 int stack_size;
2440                 int tos;
2441         };
2442
2443 #### Shift and pop
2444
2445 Two operations are needed on the stack - shift (which is like push) and pop.
2446
2447 Shift applies not only to terminals but also to non-terminals.  When we
2448 reduce a production we will pop off entries corresponding to the body
2449 symbols, then push on an item for the head of the production.  This last is
2450 exactly the same process as shifting in a terminal so we use the same
2451 function for both.  In both cases we provide a stack frame which
2452 contains the symbol to shift and related indent information.
2453
2454 To simplify other code we arrange for `shift` to fail if there is no `goto`
2455 state for the symbol.  This is useful in basic parsing due to our design
2456 that we shift when we can, and reduce when we cannot.  So the `shift`
2457 function reports if it could.
2458
2459 `shift` is also used to push state zero onto the stack, so if the
2460 stack is empty, it always chooses zero as the next state.
2461
2462 So `shift` finds the next state.  If that succeed it extends the allocations
2463 if needed and pushes all the information onto the stacks.
2464
2465 ###### parser functions
2466
2467         static int shift(struct parser *p, struct frame *next,
2468                          void *asn,
2469                          const struct state states[])
2470         {
2471                 // Push an entry onto the stack
2472                 int newstate = p->tos
2473                         ? search(&states[p->stack[p->tos-1].state],
2474                                  next->sym)
2475                         : 0;
2476                 if (newstate < 0)
2477                         return 0;
2478                 if (p->tos >= p->stack_size) {
2479                         p->stack_size += 10;
2480                         p->stack = realloc(p->stack, p->stack_size
2481                                            * sizeof(p->stack[0]));
2482                         p->asn_stack = realloc(p->asn_stack, p->stack_size
2483                                            * sizeof(p->asn_stack[0]));
2484                 }
2485                 next->state = newstate;
2486                 next->newline_permitted = 0;
2487                 if (p->tos)
2488                         next->newline_permitted =
2489                                 p->stack[p->tos-1].newline_permitted;
2490                 if (next->indents)
2491                         next->newline_permitted = 0;
2492                 if (states[newstate].starts_line)
2493                         next->newline_permitted = 1;
2494                 p->stack[p->tos] = *next;
2495                 p->asn_stack[p->tos] = asn;
2496                 p->tos++;
2497                 return 1;
2498         }
2499
2500 `pop` primarily moves the top of stack (`tos`) back down the required
2501 amount and frees any `asn` entries that need to be freed.  It also
2502 collects a summary of the indents in the symbols that are being
2503 removed. It is called _after_ we reduce a production, just before we
2504 `shift` the nonterminal in.
2505
2506 `pop` is only called if there are entries to remove, so `num` is never zero.
2507
2508 ###### parser functions
2509
2510         static void pop(struct parser *p, int num, struct frame *next,
2511                         void(*do_free)(short sym, void *asn))
2512         {
2513                 int i;
2514                 p->tos -= num;
2515                 next->starts_indented = p->stack[p->tos].starts_indented;
2516                 next->indents = 0;
2517                 for (i = 0; i < num; i++) {
2518                         next->indents += p->stack[p->tos+i].indents;
2519                         do_free(p->stack[p->tos+i].sym,
2520                                 p->asn_stack[p->tos+i]);
2521                 }
2522         }
2523
2524 ### Memory allocation
2525
2526 The `scanner` returns tokens in a local variable - we want them in allocated
2527 memory so they can live in the `asn_stack`.  Similarly the `asn` produced by
2528 a reduce is in a large buffer.  Both of these require some allocation and
2529 copying, hence `memdup` and `tokcopy`.
2530
2531 ###### parser includes
2532         #include <memory.h>
2533
2534 ###### parser functions
2535
2536         void *memdup(void *m, int len)
2537         {
2538                 void *ret;
2539                 if (len == 0)
2540                         return NULL;
2541                 ret = malloc(len);
2542                 memcpy(ret, m, len);
2543                 return ret;
2544         }
2545
2546         static struct token *tok_copy(struct token tk)
2547         {
2548                 struct token *new = malloc(sizeof(*new));
2549                 *new = tk;
2550                 return new;
2551         }
2552
2553 ### The heart of the parser.
2554
2555 Now we have the parser.  If we can shift, we do, though newlines and
2556 reducing indenting may block that.  If not and we can reduce we do.
2557 If the production we reduced was production zero, then we have
2558 accepted the input and can finish.
2559
2560 We return whatever `asn` was returned by reducing production zero.
2561
2562 If we can neither shift nor reduce we have an error to handle.  We pop
2563 single entries off the stack until we can shift the `TK_error` symbol, then
2564 drop input tokens until we find one we can shift into the new error state.
2565
2566 When we find `TK_in` and `TK_out` tokens which report indents we need
2567 to handle them directly as the grammar cannot express what we want to
2568 do with them.
2569
2570 `TK_in` tokens are easy: we simply update the `next` stack frame to
2571 record how many indents there are and that the next token started with
2572 an indent.
2573
2574 `TK_out` tokens must either be counted off against any pending indent,
2575 or must force reductions until there is a pending indent which isn't
2576 at the start of a production.
2577
2578 `TK_newline` tokens are ignored precisely if there has been an indent
2579 since the last state which could have been at the start of a line.
2580
2581 ###### parser includes
2582         #include "parser.h"
2583 ###### parser_run
2584         void *parser_run(struct token_state *tokens,
2585                          const struct state states[],
2586                          int (*do_reduce)(int, void**, struct token_config*, void*),
2587                          void (*do_free)(short, void*),
2588                          FILE *trace, const char *non_term[],
2589                          struct token_config *config)
2590         {
2591                 struct parser p = { 0 };
2592                 struct frame next = { 0 };
2593                 struct token *tk = NULL;
2594                 int accepted = 0;
2595                 void *ret = NULL;
2596
2597                 shift(&p, &next, NULL, states);
2598                 while (!accepted) {
2599                         struct token *err_tk;
2600                         struct frame *tos = &p.stack[p.tos-1];
2601                         if (!tk)
2602                                 tk = tok_copy(token_next(tokens));
2603                         next.sym = tk->num;
2604                         parser_trace(trace, &p, &next, tk, states, non_term, config->known_count);
2605
2606                         if (next.sym == TK_in) {
2607                                 next.starts_indented = 1;
2608                                 next.indents = 1;
2609                                 free(tk);
2610                                 tk = NULL;
2611                                 parser_trace_action(trace, "Record");
2612                                 continue;
2613                         }
2614                         if (next.sym == TK_out) {
2615                                 if (tos->indents > tos->starts_indented ||
2616                                     (tos->indents == 1 &&
2617                                      states[tos->state].reduce_size != 1)) {
2618                                         tos->indents -= 1;
2619                                         if (tos->indents <= tos->starts_indented) {
2620                                                 // no internal indent any more, reassess 'newline_permitted'
2621                                                 if (states[tos->state].starts_line)
2622                                                         tos->newline_permitted = 1;
2623                                                 else if (p.tos > 1)
2624                                                         tos->newline_permitted = p.stack[p.tos-2].newline_permitted;
2625                                         }
2626                                         free(tk);
2627                                         tk = NULL;
2628                                         parser_trace_action(trace, "Cancel");
2629                                         continue;
2630                                 }
2631                                 // fall through and force a REDUCE (as 'shift'
2632                                 // will fail).
2633                         }
2634                         if (next.sym == TK_newline) {
2635                                 if (! tos->newline_permitted) {
2636                                         free(tk);
2637                                         tk = NULL;
2638                                         parser_trace_action(trace, "Discard");
2639                                         continue;
2640                                 }
2641                         }
2642                         if (shift(&p, &next, tk, states)) {
2643                                 tk = NULL;
2644                                 next.starts_indented = 0;
2645                                 next.indents = 0;
2646                                 parser_trace_action(trace, "Shift");
2647                                 continue;
2648                         }
2649                         if (states[tos->state].reduce_prod >= 0) {
2650                                 void **body;
2651                                 void *res;
2652                                 const struct state *nextstate = &states[tos->state];
2653                                 int prod = nextstate->reduce_prod;
2654                                 int size = nextstate->reduce_size;
2655                                 int bufsize;
2656                                 static char buf[16*1024];
2657                                 struct frame frame;
2658                                 frame.sym = nextstate->reduce_sym;
2659
2660                                 body = p.asn_stack + (p.tos - size);
2661
2662                                 bufsize = do_reduce(prod, body, config, buf);
2663
2664                                 if (size)
2665                                         pop(&p, size, &frame, do_free);
2666                                 else {
2667                                         frame.indents = next.indents;
2668                                         frame.starts_indented = frame.indents;
2669                                         next.indents = 0;
2670                                         next.starts_indented = 0;
2671                                 }
2672                                 res = memdup(buf, bufsize);
2673                                 memset(buf, 0, bufsize);
2674                                 if (!shift(&p, &frame, res, states)) {
2675                                         if (prod != 0) abort();
2676                                         accepted = 1;
2677                                         ret = res;
2678                                 }
2679                                 parser_trace_action(trace, "Reduce");
2680                                 continue;
2681                         }
2682                         if (tk->num == TK_out) {
2683                                 // Indent problem - synthesise tokens to get us
2684                                 // out of here.
2685                                 struct frame frame = { 0 };
2686                                 fprintf(stderr, "Synthesize %d to handle indent problem\n", states[tos->state].shift_sym);
2687                                 frame.sym = states[tos->state].shift_sym;
2688                                 shift(&p, &frame, tok_copy(*tk), states);
2689                                 // FIXME need to report this error somehow
2690                                 parser_trace_action(trace, "Synthesize");
2691                                 continue;
2692                         }
2693                         /* Error. We walk up the stack until we
2694                          * find a state which will accept TK_error.
2695                          * We then shift in TK_error and see what state
2696                          * that takes us too.
2697                          * Then we discard input tokens until
2698                          * we find one that is acceptable.
2699                          */
2700                         parser_trace_action(trace, "ERROR");
2701
2702                         err_tk = tok_copy(*tk);
2703                         next.sym = TK_error;
2704                         while (shift(&p, &next, err_tk, states) == 0
2705                                && p.tos > 0)
2706                                 // discard this state
2707                                 pop(&p, 1, &next, do_free);
2708                         if (p.tos == 0) {
2709                                 free(err_tk);
2710                                 // no state accepted TK_error
2711                                 break;
2712                         }
2713                         tos = &p.stack[p.tos-1];
2714                         while (search(&states[tos->state], tk->num) < 0 &&
2715                                tk->num != TK_eof) {
2716                                 free(tk);
2717                                 tk = tok_copy(token_next(tokens));
2718                                 if (tk->num == TK_in)
2719                                         next.indents += 1;
2720                                 if (tk->num == TK_out) {
2721                                         if (next.indents == 0)
2722                                                 break;
2723                                         next.indents -= 1;
2724                                 }
2725                         }
2726                         if (p.tos == 0 && tk->num == TK_eof)
2727                                 break;
2728                 }
2729                 free(tk);
2730                 if (p.tos)
2731                         pop(&p, p.tos, &next, do_free);
2732                 free(p.asn_stack);
2733                 free(p.stack);
2734                 return ret;
2735         }
2736
2737 ###### exported functions
2738         void *parser_run(struct token_state *tokens,
2739                          const struct state states[],
2740                          int (*do_reduce)(int, void**, struct token_config*, void*),
2741                          void (*do_free)(short, void*),
2742                          FILE *trace, const char *non_term[],
2743                          struct token_config *config);
2744
2745 ### Tracing
2746
2747 Being able to visualize the parser in action can be invaluable when
2748 debugging the parser code, or trying to understand how the parse of a
2749 particular grammar progresses.  The stack contains all the important
2750 state, so just printing out the stack every time around the parse loop
2751 can make it possible to see exactly what is happening.
2752
2753 This doesn't explicitly show each SHIFT and REDUCE action.  However they
2754 are easily deduced from the change between consecutive lines, and the
2755 details of each state can be found by cross referencing the states list
2756 in the stack with the "report" that parsergen can generate.
2757
2758 For terminal symbols, we just dump the token.  For non-terminals we
2759 print the name of the symbol.  The look ahead token is reported at the
2760 end inside square brackets.
2761
2762 ###### parser functions
2763
2764         static char *reserved_words[] = {
2765                 [TK_error]        = "ERROR",
2766                 [TK_in]           = "IN",
2767                 [TK_out]          = "OUT",
2768                 [TK_newline]      = "NEWLINE",
2769                 [TK_eof]          = "$eof",
2770         };
2771         static void parser_trace_state(FILE *trace, struct frame *f, const struct state states[])
2772         {
2773                 fprintf(trace, "(%d", f->state);
2774                 if (states[f->state].starts_line)
2775                         fprintf(trace, "s");
2776                 if (f->newline_permitted)
2777                         fprintf(trace, "n");
2778                 fprintf(trace, ") ");
2779         }
2780
2781         void parser_trace(FILE *trace, struct parser *p, struct frame *n,
2782                           struct token *tk, const struct state states[],
2783                           const char *non_term[], int knowns)
2784         {
2785                 int i;
2786                 if (!trace)
2787                         return;
2788                 for (i = 0; i < p->tos; i++) {
2789                         struct frame *f = &p->stack[i];
2790                         if (i) {
2791                                 int sym = f->sym;
2792                                 if (sym < TK_reserved &&
2793                                     reserved_words[sym] != NULL)
2794                                         fputs(reserved_words[sym], trace);
2795                                 else if (sym < TK_reserved + knowns) {
2796                                         struct token *t = p->asn_stack[i];
2797                                         text_dump(trace, t->txt, 20);
2798                                 } else
2799                                         fputs(non_term[sym - TK_reserved - knowns],
2800                                               trace);
2801                                 if (f->indents)
2802                                         fprintf(trace, "%c%d", f->starts_indented?':':'.',
2803                                                 f->indents);
2804                                 fputs(" ", trace);
2805                         }
2806                         parser_trace_state(trace, f, states);
2807                 }
2808                 fprintf(trace, "[");
2809                 if (tk->num < TK_reserved &&
2810                     reserved_words[tk->num] != NULL)
2811                         fputs(reserved_words[tk->num], trace);
2812                 else
2813                         text_dump(trace, tk->txt, 20);
2814                 if (n->indents)
2815                         fprintf(trace, "%c%d", n->starts_indented?':':'.',
2816                                 n->indents);
2817                 fputs("]", trace);
2818         }
2819
2820         void parser_trace_action(FILE *trace, char *action)
2821         {
2822                 if (trace)
2823                         fprintf(trace, " - %s\n", action);
2824         }
2825
2826 # A Worked Example
2827
2828 The obvious example for a parser is a calculator.
2829
2830 As `scanner` provides number parsing function using `libgmp` is it not much
2831 work to perform arbitrary rational number calculations.
2832
2833 This calculator takes one expression, or an equality test per line.  The
2834 results are printed and if any equality test fails, the program exits with
2835 an error.
2836
2837 ###### File: parsergen.mk
2838         calc.c calc.h : parsergen parsergen.mdc
2839                 ./parsergen --tag calc -o calc parsergen.mdc
2840         calc : calc.o libparser.o libscanner.o libmdcode.o libnumber.o
2841                 $(CC) $(CFLAGS) -o calc calc.o libparser.o libscanner.o libmdcode.o libnumber.o -licuuc -lgmp
2842
2843 # calc: header
2844
2845         #include "number.h"
2846         // what do we use for a demo-grammar?  A calculator of course.
2847         struct number {
2848                 mpq_t val;
2849                 char tail[2];
2850                 int err;
2851         };
2852
2853 # calc: code
2854
2855         #include <stdlib.h>
2856         #include <unistd.h>
2857         #include <fcntl.h>
2858         #include <sys/mman.h>
2859         #include <stdio.h>
2860         #include <malloc.h>
2861         #include <gmp.h>
2862         #include "mdcode.h"
2863         #include "scanner.h"
2864         #include "number.h"
2865         #include "parser.h"
2866
2867         #include "calc.h"
2868
2869         static void free_number(struct number *n)
2870         {
2871                 mpq_clear(n->val);
2872                 free(n);
2873         }
2874
2875         int main(int argc, char *argv[])
2876         {
2877                 int fd = open(argv[1], O_RDONLY);
2878                 int len = lseek(fd, 0, 2);
2879                 char *file = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
2880                 struct section *s = code_extract(file, file+len, NULL);
2881                 struct token_config config = {
2882                         .ignored = (1 << TK_line_comment)
2883                                  | (1 << TK_block_comment)
2884                                  | (1 << TK_in)
2885                                  | (1 << TK_out),
2886                         .number_chars = ".,_+-",
2887                         .word_start = "",
2888                         .word_cont = "",
2889                 };
2890                 parse_calc(s->code, &config, argc > 2 ? stderr : NULL);
2891                 while (s) {
2892                         struct section *t = s->next;
2893                         code_free(s->code);
2894                         free(s);
2895                         s = t;
2896                 }
2897                 exit(0);
2898         }
2899
2900 # calc: grammar
2901
2902         Session -> Session Line
2903                 | Line
2904
2905         Line -> Expression NEWLINE ${ gmp_printf("Answer = %Qd\n", $1.val);
2906                                         { mpf_t fl; mpf_init2(fl, 20); mpf_set_q(fl, $1.val);
2907                                         gmp_printf("  or as a decimal: %Fg\n", fl);
2908                                         mpf_clear(fl);
2909                                         }
2910                                      }$
2911                 | Expression = Expression NEWLINE ${
2912                         if (mpq_equal($1.val, $3.val))
2913                                 gmp_printf("Both equal %Qd\n", $1.val);
2914                         else {
2915                                 gmp_printf("NOT EQUAL: %Qd\n      != : %Qd\n",
2916                                         $1.val, $3.val);
2917                                 exit(1);
2918                         }
2919                 }$
2920                 | NEWLINE ${ printf("Blank line\n"); }$
2921                 | ERROR NEWLINE ${ printf("Skipped a bad line\n"); }$
2922
2923         $number
2924         Expression -> Expression + Term ${ mpq_init($0.val); mpq_add($0.val, $1.val, $3.val); }$
2925                 | Expression - Term ${ mpq_init($0.val); mpq_sub($0.val, $1.val, $3.val); }$
2926                 | Term ${ mpq_init($0.val); mpq_set($0.val, $1.val); }$
2927
2928         Term -> Term * Factor ${ mpq_init($0.val); mpq_mul($0.val, $1.val, $3.val); }$
2929                 | Term / Factor ${ mpq_init($0.val); mpq_div($0.val, $1.val, $3.val); }$
2930                 | Factor ${ mpq_init($0.val); mpq_set($0.val, $1.val); }$
2931
2932         Factor -> NUMBER ${ if (number_parse($0.val, $0.tail, $1.txt) == 0) mpq_init($0.val); }$
2933                 | ( Expression ) ${ mpq_init($0.val); mpq_set($0.val, $2.val); }$