1 |
root |
1.1 |
#header << |
2 |
|
|
#include "config.h" |
3 |
|
|
|
4 |
|
|
#include <cmath> |
5 |
|
|
#include <list> |
6 |
|
|
|
7 |
|
|
#include "lsys.h" |
8 |
|
|
#include "util.h" |
9 |
|
|
|
10 |
|
|
#define PURIFY(a,b) |
11 |
|
|
|
12 |
|
|
void parse_file (FILE *file, const string &path, lsys &l) t_err; |
13 |
|
|
void parse_file (const string &path, lsys &l) t_err; |
14 |
|
|
|
15 |
|
|
extern list<string> include_dirs; |
16 |
|
|
>> |
17 |
|
|
|
18 |
|
|
<< |
19 |
|
|
#include <sstream> |
20 |
|
|
#include <cstdio> |
21 |
|
|
|
22 |
|
|
#include "DLGLexer.h" |
23 |
|
|
|
24 |
|
|
list<string> include_dirs; |
25 |
|
|
|
26 |
|
|
void parse_file (FILE *file, const string &path, lsys &l) t_err |
27 |
|
|
{ |
28 |
|
|
DLGFileInput in (file); |
29 |
|
|
DLGLexer scanner (&in); |
30 |
|
|
ANTLRTokenBuffer pipe (&scanner); |
31 |
|
|
ANTLRCommonToken token; |
32 |
|
|
scanner.setToken (&token); |
33 |
|
|
Parser parser (&pipe); |
34 |
|
|
parser.init (); |
35 |
|
|
|
36 |
|
|
parser.current_file = path; |
37 |
|
|
parser.parse_file (l); |
38 |
|
|
} |
39 |
|
|
|
40 |
|
|
void parse_file (const string &path, lsys &l) t_err |
41 |
|
|
{ |
42 |
|
|
string ipath(path); |
43 |
|
|
list<string>::const_iterator i = include_dirs.begin (); |
44 |
|
|
FILE *f; |
45 |
|
|
|
46 |
|
|
while (!(f = fopen (ipath.c_str (), "r"))) |
47 |
|
|
{ |
48 |
|
|
ipath += ".l"; |
49 |
|
|
if ((f = fopen (ipath.c_str (), "r"))) |
50 |
|
|
break; |
51 |
|
|
|
52 |
|
|
if (i == include_dirs.end ()) |
53 |
|
|
throw error ("unable to find or open file '" + path + "'"); |
54 |
|
|
|
55 |
|
|
ipath = *i + "/" + path; |
56 |
|
|
i++; |
57 |
|
|
} |
58 |
|
|
|
59 |
|
|
struct filebuf |
60 |
|
|
{ |
61 |
|
|
FILE *f; |
62 |
|
|
filebuf (FILE * file) : f (file) {}; |
63 |
|
|
~filebuf () { fclose (f); }; |
64 |
|
|
} auto_close(f); |
65 |
|
|
|
66 |
|
|
parse_file (f, ipath, l); |
67 |
|
|
} |
68 |
|
|
>> |
69 |
|
|
|
70 |
|
|
#lexclass COMMENT |
71 |
|
|
|
72 |
|
|
#token "\n" << skip(); newline(); set_endcol(0); >> |
73 |
|
|
#token "\*/" << mode(START); skip(); >> |
74 |
|
|
#token "~[]" << skip(); >> |
75 |
|
|
|
76 |
|
|
#lexclass QW_STRING |
77 |
|
|
|
78 |
|
|
#token Name "\"" << replchar('\0'); mode(START); >> |
79 |
|
|
#token "\\\"" << replchar('\"'); more(); >> |
80 |
|
|
#token "~[]" << more(); >> |
81 |
|
|
|
82 |
|
|
#lexclass START |
83 |
|
|
|
84 |
|
|
#token "/\*" << mode(COMMENT); skip(); >> |
85 |
|
|
#token "\"" << skip(); mode(QW_STRING); >> |
86 |
|
|
|
87 |
|
|
#token "//~[\n]*" << skip(); >> |
88 |
|
|
#token "#~[\n]*" << skip(); >> |
89 |
|
|
#token "\n" << skip(); newline(); set_endcol(0); >> |
90 |
|
|
#token "[\ ]+" << skip(); >> |
91 |
|
|
#token "\t" << skip(); _endcol = ((_endcol-1) & ~7) + 8; >> |
92 |
|
|
|
93 |
|
|
#token Name "[a-zA-Z][a-z0-9_]*" |
94 |
|
|
#token Number "[0-9]+{\.[0-9]+}" |
95 |
|
|
|
96 |
|
|
class Parser { |
97 |
|
|
<< |
98 |
|
|
public: |
99 |
|
|
string current_file; |
100 |
|
|
protected: |
101 |
|
|
void syn(_ANTLRTokenPtr tok, ANTLRChar *egroup, SetWordType *eset, |
102 |
|
|
ANTLRTokenType etok, int k); |
103 |
|
|
|
104 |
|
|
bool istok (_ANTLRTokenPtr tok, const char *s) |
105 |
|
|
{ return strcmp (tok->getText(), s) == 0; }; |
106 |
|
|
|
107 |
|
|
file_pos here () |
108 |
|
|
{ return file_pos (current_file, LT(1)->getLine (), -1); }; |
109 |
|
|
>> |
110 |
|
|
|
111 |
|
|
#lexclass START |
112 |
|
|
|
113 |
|
|
parse_file[lsys &l] |
114 |
|
|
: parse_lsys[l] "@" |
115 |
|
|
; |
116 |
|
|
|
117 |
|
|
parse_lsys[lsys &l] |
118 |
|
|
: ( statement[$l] )+ | |
119 |
|
|
; |
120 |
|
|
|
121 |
|
|
statement[lsys &l] |
122 |
|
|
: << string s; lsys *m = 0; /* calm down gcc */ >> |
123 |
|
|
<< istok(LT(1), "include") >>? . |
124 |
|
|
( |
125 |
|
|
qw_str:Name |
126 |
|
|
<< |
127 |
|
|
::parse_file ($qw_str->getText(), l); |
128 |
|
|
>> |
129 |
|
|
| |
130 |
|
|
"\(" br_str:Name "\)" |
131 |
|
|
<< |
132 |
|
|
m = new lsys; |
133 |
|
|
::parse_file ($br_str->getText (), *m); |
134 |
|
|
l.add_lsys (m); |
135 |
|
|
>> |
136 |
|
|
) |
137 |
|
|
| << istok(LT(1), "ruleset") >>? . |
138 |
|
|
{ module_name>[s] } |
139 |
|
|
"\(" |
140 |
|
|
<< m = new lsys; >> |
141 |
|
|
parse_lsys[*m] |
142 |
|
|
<< l.add_lsys (m); >> |
143 |
|
|
"\)" |
144 |
|
|
| << istok(LT(1), "define") >>? . |
145 |
|
|
module_name>[s] expr_any[$l.defines[s]] ";" |
146 |
|
|
| << istok(LT(1), "ignore") >>? . |
147 |
|
|
( module_ref>[s] << $l.ignore_module.insert (s); >> )+ ";" |
148 |
|
|
| << !istok(LT(1), ")") >>? /* why is this predicate necessary? */ |
149 |
|
|
parse_rule[$l] |
150 |
|
|
; |
151 |
|
|
|
152 |
|
|
parse_rule[lsys &l] |
153 |
|
|
: << rule r; |
154 |
|
|
r.constraint = module (1); r.iterations.is_expr = 1; |
155 |
|
|
r.iterations = module (0); r.iterations.is_expr = 1; |
156 |
|
|
>> |
157 |
|
|
parse_modvec[r.pre] |
158 |
|
|
( "\<" parse_module[*(module *)&r] |
159 |
|
|
| << |
160 |
|
|
if (r.pre.size () == 0) |
161 |
|
|
throw error ("symbol to be replaced must be a single module, not an empty sequence", LT(1)->getLine ()); |
162 |
|
|
else if (r.pre.size () != 1) |
163 |
|
|
throw error ("symbol to be replaced must be a single module, not more", r.pre.first ()); |
164 |
|
|
else |
165 |
|
|
{ |
166 |
|
|
*(module *)&r = r.pre.first (); |
167 |
|
|
r.pre.erase (); |
168 |
|
|
} |
169 |
|
|
>> |
170 |
|
|
) |
171 |
|
|
{ "\>" parse_modvec[r.post] } |
172 |
|
|
{ ":" expr_numeric[r.constraint] } |
173 |
|
|
"=>" ( parse_modvec[r.repl] | /* empty */ ) |
174 |
|
|
{ "," expr_numeric[r.iterations] } |
175 |
|
|
";" |
176 |
|
|
<< $l.add_rule(r); >> |
177 |
|
|
; |
178 |
|
|
|
179 |
|
|
parse_modvec[module_vec &v] |
180 |
|
|
: << module m; >> |
181 |
|
|
( parse_module[m] << $v.push_back (m); >> )+ |
182 |
|
|
; |
183 |
|
|
|
184 |
|
|
parse_module[module &m] |
185 |
|
|
: << module v; |
186 |
|
|
m.erase (); |
187 |
|
|
>> |
188 |
|
|
module_head[$m] { |
189 |
|
|
"\(" |
190 |
|
|
expr_any[v] << $m.push_back (v); v.erase (); >> |
191 |
|
|
( "," expr_any[v] << $m.push_back (v); v.erase (); >> )* |
192 |
|
|
"\)" |
193 |
|
|
} |
194 |
|
|
; |
195 |
|
|
|
196 |
|
|
module_head[module &m] |
197 |
|
|
: n:Number << $m = module (atof ($n->getText ())); $m.where = here (); >> |
198 |
|
|
| module_ref>[$m.str] << $m.is_num = 0; $m.where = here (); >> |
199 |
|
|
; |
200 |
|
|
|
201 |
|
|
module_name>[string s] |
202 |
|
|
: a:Name << $s = $a->getText(); >> |
203 |
|
|
; |
204 |
|
|
|
205 |
|
|
module_ref>[string s] |
206 |
|
|
: module_name>[$s] |
207 |
|
|
| "\\" << $s = "\\"; >> |
208 |
|
|
| "\+" << $s = "+"; >> |
209 |
|
|
| "\-" << $s = "-"; >> |
210 |
|
|
| "\*" << $s = "*"; >> |
211 |
|
|
| "\/" << $s = "/"; >> |
212 |
|
|
| "\^" << $s = "^"; >> |
213 |
|
|
| "\{" << $s = "{"; >> |
214 |
|
|
| "\}" << $s = "}"; >> |
215 |
|
|
| "\." << $s = "."; >> |
216 |
|
|
| "\|" << $s = "|"; >> |
217 |
|
|
| "\~" << $s = "~"; >> |
218 |
|
|
| "\[" << $s = "["; >> |
219 |
|
|
| "\]" << $s = "]"; >> |
220 |
|
|
| "\!" << $s = "!"; >> |
221 |
|
|
| "\&" << $s = "&"; >> |
222 |
|
|
| "\%" << $s = "%"; >> |
223 |
|
|
; |
224 |
|
|
|
225 |
|
|
expr_any[module &v] |
226 |
|
|
: expr_numeric[$v] |
227 |
|
|
| expr_modvec[$v] |
228 |
|
|
; |
229 |
|
|
|
230 |
|
|
expr_modvec[module &v] |
231 |
|
|
: "\"" parse_modvec[$v] << $v.str.erase (); $v.is_expr = 0; >> "\"" |
232 |
|
|
| "\'" parse_modvec[$v] << $v.str.erase (); $v.is_expr = 0; >> |
233 |
|
|
; |
234 |
|
|
|
235 |
|
|
expr_numeric[module &v] |
236 |
|
|
: expr_0[$v] << $v.is_expr = 1; >> |
237 |
|
|
; |
238 |
|
|
|
239 |
|
|
expr_0[module &v] |
240 |
|
|
: << module r; >> |
241 |
|
|
expr_1[$v] ( "\&\&" expr_2[r] << $v = module ("&&", $v, r); >> |
242 |
|
|
| "\|\|" expr_2[r] << $v = module ("||", $v, r); >> |
243 |
|
|
)* |
244 |
|
|
| "\!" expr_1[r] << $v = module ("!", r); >> |
245 |
|
|
; |
246 |
|
|
|
247 |
|
|
expr_1[module &v] |
248 |
|
|
: << module r; >> |
249 |
|
|
expr_2[$v] { "\>" expr_2[r] << $v = module (">" , $v, r); >> |
250 |
|
|
| ">=" expr_2[r] << $v = module (">=", $v, r); >> |
251 |
|
|
| "==" expr_2[r] << $v = module ("==", $v, r); >> |
252 |
|
|
| "=" expr_2[r] << $v = module ("==", $v, r); >> |
253 |
|
|
| "!=" expr_2[r] << $v = module ("!=", $v, r); >> |
254 |
|
|
| "\<" expr_2[r] << $v = module ("<" , $v, r); >> |
255 |
|
|
| "<=" expr_2[r] << $v = module ("<=", $v, r); >> |
256 |
|
|
} |
257 |
|
|
; |
258 |
|
|
|
259 |
|
|
expr_2[module &v] |
260 |
|
|
: << module r; >> |
261 |
|
|
<< $v = module (0); >> |
262 |
|
|
{expr_3[$v]} ( "\+" expr_3[r] << $v = module ("+", $v, r); >> |
263 |
|
|
| "\-" expr_3[r] << $v = module ("-", $v, r); >> |
264 |
|
|
)* |
265 |
|
|
; |
266 |
|
|
|
267 |
|
|
expr_3[module &v] |
268 |
|
|
: << module r; >> |
269 |
|
|
expr_4[$v] ( "\*" expr_4[r] << $v = module ("*", $v, r); >> |
270 |
|
|
| "\/" expr_4[r] << $v = module ("/", $v, r); >> |
271 |
|
|
| "\%" expr_4[r] << $v = module ("%", $v ,r); >> |
272 |
|
|
)* |
273 |
|
|
; |
274 |
|
|
|
275 |
|
|
expr_4[module &v] |
276 |
|
|
: << module r; >> |
277 |
|
|
expr_5[$v] ( "\^" expr_5[r] << $v = module ("^", $v, r); >> |
278 |
|
|
)* |
279 |
|
|
; |
280 |
|
|
|
281 |
|
|
expr_5[module &v] |
282 |
|
|
: "\(" expr_0[$v] << $v.where = here (); >> "\)" |
283 |
|
|
| expr_atom[$v] |
284 |
|
|
; |
285 |
|
|
|
286 |
|
|
expr_atom[module &v] |
287 |
|
|
: num:Number << $v = module (atof ($num->getText ())); $v.where = here (); >> |
288 |
|
|
| expr_module[$v] |
289 |
|
|
; |
290 |
|
|
|
291 |
|
|
expr_module[module &m] |
292 |
|
|
: << module v; |
293 |
|
|
m.erase (); |
294 |
|
|
m.where = here (); |
295 |
|
|
>> |
296 |
|
|
module_name>[$m.str] { |
297 |
|
|
"\(" |
298 |
|
|
expr_any[v] << $m.push_back (v); v.erase (); >> |
299 |
|
|
( "," expr_any[v] << $m.push_back (v); v.erase (); >> )* |
300 |
|
|
"\)" |
301 |
|
|
} |
302 |
|
|
; |
303 |
|
|
|
304 |
|
|
} |
305 |
|
|
|
306 |
|
|
<< |
307 |
|
|
void Parser::syn (_ANTLRTokenPtr tok, ANTLRChar * egroup, SetWordType * eset, |
308 |
|
|
ANTLRTokenType etok, int k) |
309 |
|
|
{ |
310 |
|
|
ostringstream msg; |
311 |
|
|
|
312 |
|
|
syntaxErrCount++; |
313 |
|
|
|
314 |
|
|
msg << current_file << ":" << LT (1)->getLine () << ": syntax error at \"" << LT (1)->getText (); |
315 |
|
|
|
316 |
|
|
if (etok || eset) |
317 |
|
|
{ |
318 |
|
|
if (k == 1) |
319 |
|
|
msg << " missing"; |
320 |
|
|
else |
321 |
|
|
{ |
322 |
|
|
msg << "; \"" << LT (1)->getText () << "\" not"; |
323 |
|
|
if (set_deg (eset) > 1) |
324 |
|
|
msg << " in"; |
325 |
|
|
} |
326 |
|
|
|
327 |
|
|
if (set_deg (eset) > 0) |
328 |
|
|
{ |
329 |
|
|
SetWordType *p = eset; |
330 |
|
|
SetWordType *endp = &(p[bsetsize]); |
331 |
|
|
unsigned e = 0; |
332 |
|
|
|
333 |
|
|
if (set_deg (eset) > 1) |
334 |
|
|
msg << " {"; |
335 |
|
|
do |
336 |
|
|
{ |
337 |
|
|
register SetWordType t = *p; |
338 |
|
|
register SetWordType *b = &(bitmask[0]); |
339 |
|
|
do |
340 |
|
|
{ |
341 |
|
|
if (t & *b) |
342 |
|
|
msg << " " << token_tbl[e]; |
343 |
|
|
e++; |
344 |
|
|
} |
345 |
|
|
while (++b < &(bitmask[sizeof (SetWordType) * 8])); |
346 |
|
|
} |
347 |
|
|
while (++p < endp); |
348 |
|
|
if (set_deg (eset) > 1) |
349 |
|
|
msg << " }"; |
350 |
|
|
} |
351 |
|
|
else |
352 |
|
|
msg << " " << token_tbl[etok]; |
353 |
|
|
|
354 |
|
|
if (strlen (egroup) > 0) |
355 |
|
|
msg << " in " << egroup; |
356 |
|
|
|
357 |
|
|
msg << endl; |
358 |
|
|
throw error (msg.str ()); |
359 |
|
|
} |
360 |
|
|
} |
361 |
|
|
>> |
362 |
|
|
|
363 |
|
|
|
364 |
|
|
|
365 |
|
|
|
366 |
|
|
|