| 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 |
|