Fail loudly on invalid parser output
[mspang/inapt.git] / parser.rl
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <vector>
5
6 #include "inapt.h"
7
8 using namespace std;
9
10 #define xstrndup strndup
11
12 %%{
13     machine inapt;
14
15     action pkgstart { ts = p; }
16
17     action add_list {
18       tmp_action.package = xstrndup(ts, p - ts);
19       tmp_action.action = curaction;
20       tmp_action.linenum = curline;
21       tmp_action.filename = curfile;
22       actions->push_back(tmp_action);
23     }
24
25     action install {
26         curaction = inapt_action::INSTALL;
27     }
28
29     action remove {
30         curaction = inapt_action::REMOVE;
31     }
32
33     action misc_error {
34         fprintf(stderr, "%s: %d: Syntax Error\n", curfile, curline);
35     }
36
37     newline = '\n' %{ curline += 1; };
38     comment = '#' (any - newline)* newline;
39     whitespace = [\t\v\f\r ] | comment | newline;
40     package_name = ((lower | digit) (lower | digit | '+' | '-' | '.')+) >pkgstart;
41     package_list = ((whitespace+ package_name)+ %add_list whitespace*);
42     cmd_install = ('install' package_list ';') >install;
43     cmd_remove = ('remove' package_list ';') >remove;
44     main := (cmd_install | cmd_remove | whitespace)* $err(misc_error);
45 }%%
46
47 %% write data;
48
49 #define BUFSIZE 128
50
51 void scanner(vector<inapt_action> *actions)
52 {
53     static char buf[BUFSIZE];
54     int cs, have = 0;
55     int done = 0;
56     int curline = 1;
57     char *ts = 0, *te = 0;
58
59     inapt_action tmp_action;
60     const char *curfile = "stdin";
61     enum inapt_action::action_t curaction = inapt_action::UNSET;
62
63     %% write init;
64
65     while ( !done ) {
66         char *p = buf + have, *pe, *eof = 0;
67         int len, space = BUFSIZE - have;
68
69         if (space == 0) {
70             fprintf(stderr, "OUT OF BUFFER SPACE\n");
71             exit(1);
72         }
73
74         len = fread(p, 1, space, stdin);
75         pe = p + len;
76
77         if (len < space) {
78             eof = pe;
79             done = 1;
80         }
81
82         %% write exec;
83
84         if (cs == inapt_error) {
85             fprintf(stderr, "PARSE ERROR\n");
86             exit(1);
87         }
88
89         have = 0;
90
91         if (ts) {
92             have = pe - ts;
93             memmove(buf, ts, have);
94             te = buf + (te - ts);
95             ts = buf;
96         }
97     }
98
99     if (cs < inapt_first_final) {
100        fprintf(stderr, "UNEXPECTED EOF\n");
101        exit(1);
102     }
103 }