7 enum ValueType { VAL_NUM, VAL_VEC, VAL_STR };
23 std::stack<Value> val;
24 std::map<std::string, Value> var;
25 std::string last_mod_var;
27 std::map<std::string, Gear*> gears;
32 static bool machine(ParserState *ps);
33 static bool expect(ParserState *ps, char c);
34 static bool statement(ParserState *ps);
35 static bool ident(ParserState *ps, std::string *s);
36 static bool gear(ParserState *ps);
37 static bool expression(ParserState *ps);
39 static char *get_ident(ParserState *ps, char *buf, int bsz);
41 static bool nextchar(ParserState *ps);
42 static void putback(ParserState *ps, char c);
44 static void expected(ParserState *ps, const char *str);
46 static void set_var(ParserState *ps, const char *name, const Value &value);
47 static bool have_var(ParserState *ps, const char *name);
48 static const Value &get_var(ParserState *ps, const char *name);
50 static void update_gear_vars(ParserState *ps, Gear *gear);
51 static bool set_gear_var(Gear *gear, const char *name, const Value &val);
53 bool parse_machine(Machine *mcn, const char *fname)
55 FILE *fp = fopen(fname, "rb");
64 pstate.nextc = fgetc(fp); // prime the parser
67 bool res = machine(&pstate);
72 static bool machine(ParserState *ps)
74 char tok[MAX_ID_LEN + 1];
75 if(strcmp(get_ident(ps, tok, sizeof tok), "machine") != 0) {
76 expected(ps, "machine");
81 while(ps->nextc != '}') {
90 static bool expect(ParserState *ps, int c)
102 static bool statement(ParserState *ps)
104 char id[MAX_ID_LEN + 1];
105 if(!get_ident(ps, id, sizeof id)) {
109 if(strcmp(id, "gear") == 0) {
110 if(!get_ident(ps, id, sizeof id)) {
111 fprintf(stderr, "gear name missing\n");
116 Gear *gear = new Gear;
118 ps->gears[id] = gear;
119 update_gear_vars(ps, gear);
121 while(ps->nextc != '}') {
125 update_gear_vars(ps, gear);
129 ps->mcn->add_gear(gear);
132 if(ps->nextc == '=') {
134 if(!expression(ps)) {
139 set_var(ps, id, ps->val.top());
141 ps->last_mod_var = id;
145 static bool expression(ParserState *ps)
150 static char *get_ident(ParserState *ps, char *buf, int bsz)
153 if(!isalpha(ps->nextc)) {
154 expected(ps, "identifier");
157 while((isalnum(ps->nextc) || ps->nextc == '_')) {
168 static bool skip_line(FILE *fp)
171 while((c = fgetc(fp)) != -1 && c != '\n');
175 static bool nextchar(ParserState *ps)
177 if(ps->savedc != -1) {
178 ps->nextc = ps->savedc;
183 while((ps->nextc = fgetc(ps->fp)) != -1) {
184 if(ps->nextc == '#') {
185 if(!skip_line(ps->fp)) {
190 if(!isspace(ps->nextc)) {
193 if(ps->nextc == '\n') {
198 return ps->nextc != -1;
201 static void putback(ParserState *ps, char c)
203 ps->savedc = ps->nextc;
207 static void expected(ParserState *ps, const char *str)
209 fprintf(stderr, "%s line %d error, expected: %s\n", ps->fname, ps->nline, str);
213 static void set_var(ParserState *ps, const char *name, const Value &value)
215 ps->var[name] = value;
218 static bool have_var(ParserState *ps, const char *name)
220 return ps->var.find(name) != ps->var.end();
223 static const Value &get_var(ParserState *ps, const char *name)
225 return ps->var[name];
228 static void print_value(const Value &val, FILE *fp)
232 fprintf(fp, "%f", val.v[0]);
236 fprintf(fp, "[%f %f %f %f]", val.v[0], val.v[1], val.v[2], val.v[3]);
240 fprintf(fp, "\"%s\"", val.str);
244 fprintf(fp, "<invalid>");
248 // Gear-specific stuff
250 static void update_gear_vars(ParserState *ps, Gear *gear)
252 if(!ps->last_mod_var.empty()) {
253 const char *name = ps->last_mod_var.c_str();
254 set_gear_var(gear, name, get_var(ps, name));
255 ps->last_mod_var.clear();
259 std::map<std::string, Value>::const_iterator it = ps->var.begin();
260 while(it != ps->var.end()) {
261 set_gear_var(gear, it->first.c_str(), it->second);
267 #define ASSERT_TYPE(v, t) \
269 if((v).type != (t)) { \
270 fprintf(stderr, "type mismatch while trying to set %s to value: ", name); \
271 print_value(val, stderr); \
272 fputc('\n', stderr); \
277 #define VVEC3(val) Vec3((val).v[0], (val).v[1], (val).v[2])
278 #define VVEC4(val) Vec4((val).v[0], (val).v[1], (val).v[2], (val).v[3])
280 static bool set_gear_var(Gear *gear, const char *name, const Value &val)
282 if(strcmp(name, "position") == 0) {
283 ASSERT_TYPE(val, VAL_VEC);
284 gear->pos = VVEC3(val);
286 } else if(strcmp(name, "plane") == 0) {
287 ASSERT_TYPE(val, VAL_VEC);
288 gear->axis = VVEC3(val);
289 gear->pdist = val.v[3];
291 } else if(strcmp(name, "thickness") == 0) {
292 ASSERT_TYPE(val, VAL_NUM);
293 gear->thickness = val.v[0];
295 } else if(strcmp(name, "teeth") == 0) {
296 ASSERT_TYPE(val, VAL_NUM);
297 gear->set_teeth(val.v[0]); // set teeth and recalc radius
299 } else if(strcmp(name, "teeth_length") == 0) {
300 ASSERT_TYPE(val, VAL_NUM);
301 gear->teeth_length = val.v[0];
303 } else if(strcmp(name, "pitch") == 0) {
304 ASSERT_TYPE(val, VAL_NUM);
305 gear->set_teeth(gear->nteeth, val.v[0]); // set pitch and recalc radius
307 } else if(strcmp(name, "color") == 0) {
308 ASSERT_TYPE(val, VAL_VEC);
309 gear->color = VVEC3(val);
311 } else if(strcmp(name, "roughness") == 0) {
312 ASSERT_TYPE(val, VAL_NUM);
313 gear->roughness = val.v[0];