Remove the error action
[mspang/inapt.git] / parser.rl
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <ctype.h>
7 #include <vector>
8
9 #include "inapt.h"
10 #include "util.h"
11
12 using namespace std;
13
14 #define MAXDEPTH 3
15
16 %%{
17     machine inapt;
18
19     action pkgstart { ts = p; }
20
21     action add_list {
22         inapt_action *tmp_action = new inapt_action;
23         tmp_action->package = xstrndup(ts, p - ts);
24         tmp_action->action = curaction;
25         tmp_action->linenum = curline;
26         tmp_action->filename = curfile;
27         cur_context->actions.push_back(tmp_action);
28     }
29
30     action install {
31         curaction = inapt_action::INSTALL;
32     }
33
34     action remove {
35         curaction = inapt_action::REMOVE;
36     }
37
38     action newline {
39         curline += 1;
40     }
41
42     action start_block {
43         if (depth++ < MAXDEPTH) {
44             fcall main;
45         } else {
46             fatal("%s: %d: Syntax Error: Nesting Too Deep at '}'", curfile, curline);
47         }
48     }
49
50     action end_block {
51         if (depth--) {
52             fret;
53         } else {
54             fatal("%s: %d: Syntax Error: Unexpected '}'", curfile, curline);
55         }
56     }
57
58     newline = '\n' @newline;
59     comment = '#' (any - '\n')* newline;
60     whitespace = [\t\v\f\r ] | comment | newline;
61     package_name = ((lower | digit) (lower | digit | '+' | '-' | '.')+) >pkgstart;
62     package_list = ((whitespace+ package_name)+ %add_list whitespace*);
63     cmd_install = ('install' @install package_list ';');
64     cmd_remove = ('remove' @remove package_list ';');
65     simple_cmd = cmd_install | cmd_remove;
66     start_block = '{' @start_block;
67     end_block = '}' @end_block;
68     cmd_if = 'if' whitespace+ alpha+ whitespace* start_block whitespace* ('else' whitespace* start_block)?;
69     cmd_list = (simple_cmd | cmd_if | whitespace)* end_block?;
70     main := cmd_list;
71 }%%
72
73 %% write data;
74
75 #define BUFSIZE 128
76
77 void badsyntax(const char *filename, int lineno, char badchar, const char *message) {
78     if (!message) {
79         if (badchar == '\n')
80             message = "Unexpected newline";
81         else if (isspace(badchar))
82             message = "Unexpected whitespace";
83         else
84             message = "Syntax error";
85     }
86
87     if (isprint(badchar) && !isspace(badchar))
88         fatal("%s: %d: %s at '%c'", filename, lineno, message, badchar);
89     else
90         fatal("%s: %d: %s", filename, lineno, message);
91 }
92
93 void parser(const char *filename, inapt_context *top_context)
94 {
95     static char buf[BUFSIZE];
96     int fd;
97     int cs, have = 0;
98     int done = 0;
99     int curline = 1;
100     char *ts = 0, *te = 0;
101     inapt_context *cur_context = top_context;
102     int stack[MAXDEPTH];
103     int top = 0; /* TODO: resize */
104     int depth = 0;
105
106     const char *curfile = filename;
107     enum inapt_action::action_t curaction = inapt_action::UNSET;
108
109     if (filename) {
110         fd = open(filename, O_RDONLY);
111         if (fd < 0)
112             fatalpe("open: %s", filename);
113     } else {
114         curfile = "stdin";
115         fd = 0;
116     }
117
118     %% write init;
119
120     while ( !done ) {
121         char *p = buf + have, *pe, *eof = 0;
122         int len, space = BUFSIZE - have;
123
124         if (space == 0) {
125             fprintf(stderr, "OUT OF BUFFER SPACE\n");
126             exit(1);
127         }
128
129         len = read(fd, p, space);
130         if (len < 0) {
131             fprintf(stderr, "IO ERROR\n");
132             exit(1);
133         }
134         pe = p + len;
135
136         if (!len) {
137             eof = pe;
138             done = 1;
139         }
140
141         %% write exec;
142
143         if (cs == inapt_error)
144             badsyntax(curfile, curline, *p, NULL);
145
146         have = 0;
147
148         if (ts) {
149             have = pe - ts;
150             memmove(buf, ts, have);
151             te = buf + (te - ts);
152             ts = buf;
153         }
154     }
155
156     if (cs < inapt_first_final) {
157        fprintf(stderr, "UNEXPECTED EOF\n");
158        exit(1);
159     }
160
161     if (depth)
162         badsyntax(curfile, curline, 0, "Unclosed block at EOF");
163 }