Add support for simple conditionals
[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 <vector>
7
8 #include "inapt.h"
9 #include "util.h"
10
11 using namespace std;
12
13 #define xstrndup strndup
14
15 %%{
16     machine inapt;
17
18     action pkgstart { ts = p; }
19
20     action add_list {
21         inapt_action *tmp_action = new inapt_action;
22         tmp_action->package = xstrndup(ts, p - ts);
23         tmp_action->action = curaction;
24         tmp_action->linenum = curline;
25         tmp_action->filename = curfile;
26         cur_context->actions.push_back(tmp_action);
27     }
28
29     action install {
30         curaction = inapt_action::INSTALL;
31     }
32
33     action remove {
34         curaction = inapt_action::REMOVE;
35     }
36
37     action newline {
38         curline += 1;
39     }
40
41     action misc_error {
42         fprintf(stderr, "%s: %d: Syntax Error\n", curfile, curline);
43     }
44
45     newline = '\n' %newline;
46     comment = '#' (any - newline)* newline;
47     whitespace = [\t\v\f\r ] | comment | newline;
48     package_name = ((lower | digit) (lower | digit | '+' | '-' | '.')+) >pkgstart;
49     package_list = ((whitespace+ package_name)+ %add_list whitespace*);
50     cmd_install = ('install' @install package_list ';');
51     cmd_remove = ('remove' @remove package_list ';');
52     simple_cmd = cmd_install | cmd_remove;
53     cmd_if = 'if' whitespace+ alpha+ whitespace+ simple_cmd whitespace* ('else' whitespace+ simple_cmd)?;
54     statement = simple_cmd | cmd_if;
55     cmd_list = (statement | whitespace)* ; #$err(misc_error);
56     main := cmd_list;
57 }%%
58
59 %% write data;
60
61 #define BUFSIZE 128
62
63 void parser(const char *filename, inapt_context *top_context)
64 {
65     static char buf[BUFSIZE];
66     int fd;
67     int cs, have = 0;
68     int done = 0;
69     int curline = 1;
70     char *ts = 0, *te = 0;
71     inapt_context *cur_context = top_context;
72     //int stack[100];
73     //int top = 0; /* TODO: resize */
74
75     const char *curfile = filename;
76     enum inapt_action::action_t curaction = inapt_action::UNSET;
77
78     if (filename) {
79         fd = open(filename, O_RDONLY);
80         if (fd < 0)
81             fatalpe("open: %s", filename);
82     } else {
83         curfile = "stdin";
84         fd = 0;
85     }
86
87     %% write init;
88
89     while ( !done ) {
90         char *p = buf + have, *pe, *eof = 0;
91         int len, space = BUFSIZE - have;
92
93         if (space == 0) {
94             fprintf(stderr, "OUT OF BUFFER SPACE\n");
95             exit(1);
96         }
97
98         len = read(fd, p, space);
99         if (len < 0) {
100             fprintf(stderr, "IO ERROR\n");
101             exit(1);
102         }
103         pe = p + len;
104
105         if (!len) {
106             eof = pe;
107             done = 1;
108         }
109
110         %% write exec;
111
112         if (cs == inapt_error) {
113             fprintf(stderr, "PARSE ERROR\n");
114             exit(1);
115         }
116
117         have = 0;
118
119         if (ts) {
120             have = pe - ts;
121             memmove(buf, ts, have);
122             te = buf + (te - ts);
123             ts = buf;
124         }
125     }
126
127     if (cs < inapt_first_final) {
128        fprintf(stderr, "UNEXPECTED EOF\n");
129        exit(1);
130     }
131 }