| 1 |
/* |
| 2 |
* representation of l-systems and their evaluation |
| 3 |
* |
| 4 |
* the order of definitions here is the most crucial I've ever encountered |
| 5 |
* => maybe this indicates design problem? |
| 6 |
*/ |
| 7 |
|
| 8 |
#ifndef lsys_h |
| 9 |
#define lsys_h |
| 10 |
|
| 11 |
#include <set> |
| 12 |
#include <map> |
| 13 |
|
| 14 |
#include <vector> |
| 15 |
#include <string> |
| 16 |
#include <sstream> |
| 17 |
#include <cstdio> |
| 18 |
#include <list> |
| 19 |
#include <string> |
| 20 |
|
| 21 |
#include "util.h" |
| 22 |
|
| 23 |
//#include <tr1/unordered_set> |
| 24 |
|
| 25 |
#if 0 |
| 26 |
template<> |
| 27 |
struct hash<string> |
| 28 |
{ |
| 29 |
size_t operator()(const string &s) const t_no |
| 30 |
{ |
| 31 |
size_t h = 0; |
| 32 |
|
| 33 |
for(string::const_iterator i = s.begin (); i != s.end (); ++i) |
| 34 |
h = h*5 + *i; |
| 35 |
|
| 36 |
return h; |
| 37 |
} |
| 38 |
}; |
| 39 |
#endif |
| 40 |
|
| 41 |
#define hash_map map |
| 42 |
|
| 43 |
struct file_pos { |
| 44 |
string path; |
| 45 |
int line; |
| 46 |
int col; |
| 47 |
|
| 48 |
file_pos (const string &p = string (), int l = -1, int c = -1) t_no |
| 49 |
: path(p), line(l), col(c) {}; |
| 50 |
}; |
| 51 |
|
| 52 |
template<typename T> |
| 53 |
struct auto_vec : shared_vector<T> { |
| 54 |
const T &first () const t_no { return shared< vector<T> >::obj->front (); }; |
| 55 |
const T &second() const t_no { return shared< vector<T> >::obj->operator[](1); }; |
| 56 |
const T &third () const t_no { return shared< vector<T> >::obj->operator[](2); }; |
| 57 |
const T &fourth() const t_no { return shared< vector<T> >::obj->operator[](3); }; |
| 58 |
}; |
| 59 |
|
| 60 |
typedef auto_vec<module> module_vec; |
| 61 |
|
| 62 |
struct module : module_vec { |
| 63 |
double num; |
| 64 |
string str; |
| 65 |
int is_expr:1; |
| 66 |
int is_num:1; |
| 67 |
|
| 68 |
file_pos where; |
| 69 |
|
| 70 |
module() t_no |
| 71 |
: is_expr(0), is_num(0) { }; |
| 72 |
module(double d) t_no |
| 73 |
: num(d), is_expr(0), is_num(1) { char s[79]; sprintf (s, "%g", d); str = s; }; |
| 74 |
module(const string &n) t_no |
| 75 |
: str(n), is_expr(0), is_num(0) { }; |
| 76 |
module(const string &n, const module &arg1) t_no |
| 77 |
: str(n), is_expr(0), is_num(0) { push_back (arg1); }; |
| 78 |
module(const string &n, const module &arg1, const module &arg2) t_no |
| 79 |
: str(n), is_expr(0), is_num(0) { push_back (arg1); push_back (arg2); }; |
| 80 |
|
| 81 |
module_vec wrap () const t_no |
| 82 |
{ module_vec w; w.push_back (*this); return w; }; |
| 83 |
|
| 84 |
void erase () t_no |
| 85 |
{ str = ""; num = 0; is_expr = is_num = 0; module_vec::erase (); }; |
| 86 |
|
| 87 |
bool is_func (const string &func) const t_no; |
| 88 |
bool is_func (const string &func, double &arg1) const t_no; |
| 89 |
bool is_func (const string &func, string &arg1, double &arg2) const t_no; |
| 90 |
bool is_func (const string &func, string &arg1, string &arg2) const t_no; |
| 91 |
bool is_func (const string &func, string &arg1, module &arg2) const t_no; |
| 92 |
|
| 93 |
operator double() const t_err; |
| 94 |
operator const string &() const t_no { return str; }; |
| 95 |
operator string () t_no { return str; }; |
| 96 |
|
| 97 |
bool match (const module &m) const { return m.str == str && m.size () == size (); }; |
| 98 |
|
| 99 |
friend bool operator <(const module &a, const module &b) t_no; |
| 100 |
}; |
| 101 |
|
| 102 |
bool operator <(const module &a, const module &b) t_no; |
| 103 |
|
| 104 |
typedef map<string, module> module_map; |
| 105 |
typedef map<string, module&> module_ref_map; |
| 106 |
typedef module_vec::const_iterator module_pos; |
| 107 |
|
| 108 |
struct rule : public module { |
| 109 |
module_vec pre; |
| 110 |
module_vec post; |
| 111 |
module constraint; |
| 112 |
|
| 113 |
module_vec repl; |
| 114 |
module iterations; |
| 115 |
}; |
| 116 |
|
| 117 |
typedef hash_map<string, list<rule> > rule_map; |
| 118 |
|
| 119 |
struct lsys : public module { |
| 120 |
lsys *parent; |
| 121 |
hash_map<string, lsys *> sub_lsys; // "local" lsystems |
| 122 |
|
| 123 |
set<string> ignore_module; |
| 124 |
rule_map rules; |
| 125 |
module_map defines; |
| 126 |
|
| 127 |
struct arg_spec { |
| 128 |
string str; |
| 129 |
int nargs; |
| 130 |
int arg; |
| 131 |
}; |
| 132 |
set<arg_spec> arg_is_numeric; |
| 133 |
|
| 134 |
lsys () t_no; |
| 135 |
~lsys () t_no; |
| 136 |
|
| 137 |
bool match_rule (const rule &r, const module_vec &v, module_pos i, module_map &vars) const t_err; |
| 138 |
|
| 139 |
private:void mark_numeric (const map<string, arg_spec> &which, const module &v) t_no; |
| 140 |
public: void add_rule (rule r) t_err; |
| 141 |
void add_lsys (lsys *l) t_err; |
| 142 |
|
| 143 |
module expand (const module_map &c, const module &v) const t_err; |
| 144 |
|
| 145 |
bool eval (module_vec &v) const t_err; // true, if changed |
| 146 |
module_vec operator ()(const module_vec &v) const t_no |
| 147 |
{ module_vec res (v); eval (res); return res; }; |
| 148 |
|
| 149 |
public: double eval_numeric (const module &expr, module_map context) const t_err; |
| 150 |
}; |
| 151 |
|
| 152 |
bool operator <(const lsys::arg_spec &a, const lsys::arg_spec &b) t_no; |
| 153 |
|
| 154 |
double eval_expr (const module &expr, |
| 155 |
const module_map &locals = module_map (), |
| 156 |
const module_map &globals = module_map ()) t_err; |
| 157 |
|
| 158 |
// otherwise needed a forward reference; |
| 159 |
inline module::operator double() const t_err |
| 160 |
{ return eval_expr (*this); } |
| 161 |
|
| 162 |
ostream &operator <<(ostream &o, const file_pos &p) t_no; |
| 163 |
ostream &operator <<(ostream &o, const module_vec &v) t_no; |
| 164 |
ostream &operator <<(ostream &o, const module &m) t_no; |
| 165 |
ostream &operator <<(ostream &o, const rule &r) t_no; |
| 166 |
ostream &operator <<(ostream &o, const lsys &l) t_no; |
| 167 |
|
| 168 |
#endif |