Stop building the DFA image automatically
[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; # | '{' @{ fcall block; };
53 #    cmd_if = 'if' whitespace+ alpha+ whitespace+ simple_cmd whitespace* ('else' whitespace+ simple_cmd)?;
54     cmd_if = 'if' whitespace+ alpha+ whitespace* '{' @{ fcall block; } whitespace* ('else' whitespace* '{' @{ fcall block; })?;
55     statement = simple_cmd | cmd_if;
56     cmd_list = (statement | whitespace)* $err(misc_error);
57     main := cmd_list;
58     block := cmd_list '}' @{ fret; };
59 }%%
60
61 %% write data;
62
63 #define BUFSIZE 128
64
65 void parser(const char *filename, inapt_context *top_context)
66 {
67     static char buf[BUFSIZE];
68     int fd;
69     int cs, have = 0;
70     int done = 0;
71     int curline = 1;
72     char *ts = 0, *te = 0;
73     inapt_context *cur_context = top_context;
74     int stack[100];
75     int top = 0; /* TODO: resize */
76
77     const char *curfile = filename;
78     enum inapt_action::action_t curaction = inapt_action::UNSET;
79
80     if (filename) {
81         fd = open(filename, O_RDONLY);
82         if (fd < 0)
83             fatalpe("open: %s", filename);
84     } else {
85         curfile = "stdin";
86         fd = 0;
87     }
88
89     %% write init;
90
91     while ( !done ) {
92         char *p = buf + have, *pe, *eof = 0;
93         int len, space = BUFSIZE - have;
94
95         if (space == 0) {
96             fprintf(stderr, "OUT OF BUFFER SPACE\n");
97             exit(1);
98         }
99
100         len = read(fd, p, space);
101         if (len < 0) {
102             fprintf(stderr, "IO ERROR\n");
103             exit(1);
104         }
105         pe = p + len;
106
107         if (!len) {
108             eof = pe;
109             done = 1;
110         }
111
112         %% write exec;
113
114         if (cs == inapt_error) {
115             fprintf(stderr, "PARSE ERROR\n");
116             exit(1);
117         }
118
119         have = 0;
120
121         if (ts) {
122             have = pe - ts;
123             memmove(buf, ts, have);
124             te = buf + (te - ts);
125             ts = buf;
126         }
127     }
128
129     if (cs < inapt_first_final) {
130        fprintf(stderr, "UNEXPECTED EOF\n");
131        exit(1);
132     }
133 }