parser sortof-works
[antikythera] / src / mparser.cc
1 #include <stdio.h>
2 #include <stdarg.h>
3 #include <assert.h>
4 #include <string>
5 #include <map>
6 #include <stack>
7 #include "mparser.h"
8 #include "machine.h"
9
10 enum ValueType { VAL_NUM, VAL_VEC, VAL_STR };
11 struct Value {
12         ValueType type;
13         std::string s;
14         float v[4];
15 };
16
17 struct ParserState;
18
19 typedef bool (*Func)(ParserState*);
20
21 struct FuncDesc {
22         Func func;
23         int arity;
24 };
25
26 struct ParserState {
27         FILE *fp;
28         const char *fname;
29         int nline, nerrors;
30         Machine *mcn;
31
32         int nextc;
33         int savedc;
34
35         std::stack<Value> val;
36         std::map<std::string, Value> var;
37         std::map<std::string, FuncDesc> func;
38
39         std::map<std::string, Gear*> gears;
40         std::stack<Gear*> cur_gear;
41         Motor *cur_motor;
42 };
43
44 #define MAX_ID_LEN      31
45
46 static bool machine(ParserState *ps);
47 static bool expect(ParserState *ps, char c);
48 static bool statement(ParserState *ps);
49 static bool expression(ParserState *ps);
50 static bool term(ParserState *ps);
51 static bool vector(ParserState *ps);
52 static bool function(ParserState *ps, const char *name);
53
54 static char *get_ident(ParserState *ps, char *buf, int bsz);
55 static bool get_number(ParserState *ps, float *num);
56 static char *get_string(ParserState *ps, char *buf, int bsz);
57
58 static bool nextchar(ParserState *ps);
59 static void putback(ParserState *ps, char c);
60
61 static void errmsg(ParserState *ps, const char *fmt, ...);
62 static void expected(ParserState *ps, const char *str);
63
64 static void set_var(ParserState *ps, const char *name, const Value &value);
65 static bool have_var(ParserState *ps, const char *name);
66 static const Value &get_var(ParserState *ps, const char *name);
67
68 static void set_func(ParserState *ps, const char *name, Func func, int nargs = 0);
69 static bool have_func(ParserState *ps, const char *name);
70 static Func get_func(ParserState *ps, const char *name);
71 static int get_func_arity(ParserState *ps, const char *name);
72
73 static Gear *begin_gear(ParserState *ps);
74 static bool end_gear(ParserState *ps);
75 static Gear *this_gear(ParserState *ps);
76 static void update_gear_vars(ParserState *ps, Gear *gear);
77 static bool set_gear_var(Gear *gear, const char *name, const Value &val);
78
79 static void update_motor_vars(ParserState *ps, Motor *motor);
80 static bool set_motor_var(ParserState *ps, Motor *motor, const char *name, const Value &val);
81
82 // built-in functions
83 static bool func_adjacent(ParserState *ps);
84
85
86 bool parse_machine(Machine *mcn, const char *fname)
87 {
88         FILE *fp = fopen(fname, "rb");
89         if(!fp) return false;
90
91         ParserState pstate;
92         pstate.fname = fname;
93         pstate.nline = 1;
94         pstate.nerrors = 0;
95         pstate.fp = fp;
96         pstate.mcn = mcn;
97         pstate.nextc = 0;
98         pstate.savedc = -1;
99         pstate.cur_motor = 0;
100
101         // init built-in function table
102         set_func(&pstate, "adjacent", func_adjacent, 2);
103
104         nextchar(&pstate);
105         bool res = machine(&pstate);
106         fclose(fp);
107         return res;
108 }
109
110 static bool machine(ParserState *ps)
111 {
112         char tok[MAX_ID_LEN + 1];
113         if(strcmp(get_ident(ps, tok, sizeof tok), "machine") != 0) {
114                 expected(ps, "machine");
115                 return false;
116         }
117         expect(ps, '{');
118
119         while(ps->nextc != '}') {
120                 if(!statement(ps)) {
121                         return false;
122                 }
123         }
124         expect(ps, '}');
125         return true;
126 }
127
128 static bool expect(ParserState *ps, char c)
129 {
130         if(c != ps->nextc) {
131                 char buf[2] = {0, 0};
132                 buf[0] = c;
133                 expected(ps, buf);
134                 return false;
135         }
136         nextchar(ps);
137         return true;
138 }
139
140 static bool statement(ParserState *ps)
141 {
142         char id[MAX_ID_LEN + 1];
143         if(!get_ident(ps, id, sizeof id)) {
144                 return false;
145         }
146
147         if(strcmp(id, "gear") == 0) {
148                 if(!expect(ps, '{')) {
149                         return false;
150                 }
151
152                 Gear *gear = begin_gear(ps);
153                 if(!gear) return false;
154
155                 update_gear_vars(ps, gear);
156
157                 while(ps->nextc != '}') {
158                         if(!statement(ps)) {
159                                 return false;
160                         }
161                 }
162                 expect(ps, '}');
163
164                 if(!end_gear(ps)) {
165                         return false;
166                 }
167                 return true;
168         }
169
170         if(strcmp(id, "motor") == 0) {
171                 if(!expect(ps, '{')) {
172                         return false;
173                 }
174                 if(ps->cur_motor) {
175                         errmsg(ps, "nested motors not allowed");
176                         return false;
177                 }
178
179                 ps->cur_motor = new Motor;
180                 update_motor_vars(ps, ps->cur_motor);
181
182                 while(ps->nextc != '}') {
183                         if(!statement(ps)) {
184                                 return false;
185                         }
186                 }
187                 expect(ps, '}');
188
189                 ps->mcn->add_motor(ps->cur_motor->drive, ps->cur_motor->speed);
190                 delete ps->cur_motor;
191                 ps->cur_motor = 0;
192                 return true;
193         }
194
195         if(ps->nextc == '=') {
196                 expect(ps, '=');
197                 if(!expression(ps)) {
198                         return false;
199                 }
200                 expect(ps, ';');
201
202                 set_var(ps, id, ps->val.top());
203                 ps->val.pop();
204                 return true;
205         }
206
207         expected(ps, "expression");
208         return false;
209 }
210
211 static bool expression(ParserState *ps)
212 {
213         return term(ps);
214 }
215
216 static bool term(ParserState *ps)
217 {
218         if(ps->nextc == '+') {
219                 expect(ps, '+');
220                 return expression(ps);
221         }
222         if(ps->nextc == '-') {
223                 expect(ps, '-');
224                 if(!expression(ps)) {
225                         return false;
226                 }
227
228                 Value &v = ps->val.top();
229                 switch(v.type) {
230                 case VAL_VEC:
231                         v.v[3] = -v.v[3];
232                         v.v[2] = -v.v[2];
233                         v.v[1] = -v.v[1];
234                 case VAL_NUM:
235                         v.v[0] = -v.v[0];
236                         break;
237
238                 default:
239                         expected(ps, "number or vector after an unary -");
240                         return false;
241                 }
242                 return true;
243         }
244         if(isalpha(ps->nextc)) {
245                 char buf[MAX_ID_LEN];
246                 if(!get_ident(ps, buf, sizeof buf)) {
247                         return false;
248                 }
249
250                 if(ps->nextc == '(') {
251                         if(!function(ps, buf)) {
252                                 return false;
253                         }
254                 } else if(have_var(ps, buf)) {
255                         ps->val.push(get_var(ps, buf));
256                 } else {
257                         errmsg(ps, "unknown identifier: %s", buf);
258                         return false;
259                 }
260                 return true;
261         }
262         if(isdigit(ps->nextc)) {
263                 float num;
264                 if(!get_number(ps, &num)) {
265                         return false;
266                 }
267
268                 Value v;
269                 v.type = VAL_NUM;
270                 v.v[0] = num;
271                 ps->val.push(v);
272                 return true;
273         }
274         if(ps->nextc == '[') {
275                 return vector(ps);
276         }
277         if(ps->nextc == '"') {
278                 char buf[MAX_ID_LEN];
279                 if(!get_string(ps, buf, sizeof buf)) {
280                         return false;
281                 }
282
283                 Value v;
284                 v.type = VAL_STR;
285                 v.s = buf;
286                 ps->val.push(v);
287                 return true;
288         }
289
290         expected(ps, "term");
291         return false;
292 }
293
294 static bool vector(ParserState *ps)
295 {
296         int nelem;
297         if(!expect(ps, '[') ||
298                         !expression(ps) ||
299                         !expect(ps, ',') ||
300                         !expression(ps) ||
301                         !expect(ps, ',') ||
302                         !expression(ps)) {
303                 return false;
304         }
305
306         if(ps->nextc == ']') {
307                 expect(ps, ']');
308                 nelem = 3;
309         } else {
310                 if(!expect(ps, ',') || !expression(ps) || !expect(ps, ']')) {
311                         return false;
312                 }
313                 nelem = 4;
314         }
315
316         Value vec;
317         vec.type = VAL_VEC;
318         vec.v[3] = 1.0f;
319
320         for(int i=0; i<nelem; i++) {
321                 const Value &tmp = ps->val.top();
322                 if(tmp.type != VAL_NUM) {
323                         expected(ps, "numbers as vector elements");
324                         return false;
325                 }
326                 vec.v[i] = tmp.v[0];
327                 ps->val.pop();
328         }
329
330         ps->val.push(vec);
331         return true;
332 }
333
334 static bool function(ParserState *ps, const char *name)
335 {
336         if(!expect(ps, '(')) {
337                 return false;
338         }
339
340         if(!have_func(ps, name)) {
341                 errmsg(ps, "unknown function: %s", name);
342                 return false;
343         }
344
345         int nargs = 0;
346         while(ps->nextc != ')') {
347                 if(nargs && !expect(ps, ',')) {
348                         return false;
349                 }
350                 if(!expression(ps)) {
351                         return false;
352                 }
353                 ++nargs;
354         }
355         expect(ps, ')');
356
357         int arity = get_func_arity(ps, name);
358         if(arity != nargs) {
359                 errmsg(ps, "function %s expects %d arguments", name, arity);
360                 return false;
361         }
362         Func func = get_func(ps, name);
363         assert(func);
364
365         if(!func(ps)) {
366                 errmsg(ps, "function %s failed", name);
367                 return false;
368         }
369         return true;
370 }
371
372 static char *get_ident(ParserState *ps, char *buf, int bsz)
373 {
374         char *ptr = buf;
375         if(!isalpha(ps->nextc)) {
376                 expected(ps, "identifier");
377                 return 0;
378         }
379         while(isalnum(ps->nextc) || ps->nextc == '_') {
380                 if(bsz > 1) {
381                         *ptr++ = ps->nextc;
382                         --bsz;
383                 }
384                 nextchar(ps);
385         }
386         *ptr = 0;
387         printf("get_ident -> \"%s\"\n", buf);
388         return buf;
389 }
390
391 static bool get_number(ParserState *ps, float *num)
392 {
393         char buf[256], *ptr = buf, *end = buf + sizeof buf;
394         bool found_point = false;
395
396         if(!isdigit(ps->nextc)) {
397                 expected(ps, "number");
398                 return false;
399         }
400
401         while(isdigit(ps->nextc) || (ps->nextc == '.' && !found_point)) {
402                 if(ptr < end) {
403                         *ptr++ = ps->nextc;
404                 }
405                 if(ps->nextc == '.') {
406                         found_point = true;
407                 }
408                 nextchar(ps);
409         }
410         *ptr = 0;
411
412         *num = atof(buf);
413         printf("get_number -> %f\n", *num);
414         return true;
415 }
416
417 static char *get_string(ParserState *ps, char *buf, int bsz)
418 {
419         char *ptr = buf;
420         if(!expect(ps, '"')) {
421                 return 0;
422         }
423
424         while(ps->nextc != -1 && ps->nextc != '"') {
425                 if(bsz > 1) {
426                         *ptr++ = ps->nextc;
427                         --bsz;
428                 }
429                 if((ps->nextc = fgetc(ps->fp)) == '\n') {
430                         ++ps->nline;
431                 }
432         }
433         *ptr = 0;
434
435         if(ps->nextc == -1) {
436                 return 0;
437         }
438         nextchar(ps);
439
440         printf("get_string -> \"%s\"\n", buf);
441         return buf;
442 }
443
444 static bool skip_line(ParserState *ps)
445 {
446         int c;
447         while((c = fgetc(ps->fp)) != -1 && c != '\n');
448         if(c != -1) {
449                 ps->nextc = fgetc(ps->fp);
450                 return true;
451         }
452         return false;
453 }
454
455 static bool nextchar(ParserState *ps)
456 {
457         if(ps->savedc != -1) {
458                 ps->nextc = ps->savedc;
459                 ps->savedc = -1;
460                 return true;
461         }
462
463         while((ps->nextc = fgetc(ps->fp)) != -1) {
464                 if(ps->nextc == '#') {
465                         if(!skip_line(ps)) {
466                                 return false;
467                         }
468                         ++ps->nline;
469                 }
470                 if(!isspace(ps->nextc)) {
471                         break;
472                 }
473                 if(ps->nextc == '\n') {
474                         ++ps->nline;
475                 }
476         }
477
478         /*if(ps->nextc != -1) {
479                 printf("DBG: nextchar -> %c\n", ps->nextc);
480         } else {
481                 printf("DBG: nextchar -> EOF\n");
482         }*/
483         return ps->nextc != -1;
484 }
485
486 static void putback(ParserState *ps, char c)
487 {
488         ps->savedc = ps->nextc;
489         ps->nextc = c;
490 }
491
492 static void errmsg(ParserState *ps, const char *fmt, ...)
493 {
494         fprintf(stderr, "%s line %d error: ", ps->fname, ps->nline);
495
496         va_list ap;
497         va_start(ap, fmt);
498         vfprintf(stderr, fmt, ap);
499         va_end(ap);
500
501         fputc('\n', stderr);
502 }
503
504 static void expected(ParserState *ps, const char *str)
505 {
506         errmsg(ps, "expected: %s", str);
507         ++ps->nerrors;
508 }
509
510 static void set_var(ParserState *ps, const char *name, const Value &value)
511 {
512         ps->var[name] = value;
513
514         Gear *gear = this_gear(ps);
515         if(gear) {
516                 set_gear_var(gear, name, value);
517         }
518
519         if(ps->cur_motor) {
520                 set_motor_var(ps, ps->cur_motor, name, value);
521         }
522 }
523
524 static bool have_var(ParserState *ps, const char *name)
525 {
526         return ps->var.find(name) != ps->var.end();
527 }
528
529 static const Value &get_var(ParserState *ps, const char *name)
530 {
531         return ps->var[name];
532 }
533
534 static void set_func(ParserState *ps, const char *name, Func func, int nargs)
535 {
536         FuncDesc fdesc;
537         fdesc.func = func;
538         fdesc.arity = nargs;
539         ps->func[name] = fdesc;
540 }
541
542 static bool have_func(ParserState *ps, const char *name)
543 {
544         return ps->func.find(name) != ps->func.end();
545 }
546
547 static Func get_func(ParserState *ps, const char *name)
548 {
549         return ps->func[name].func;
550 }
551
552 static int get_func_arity(ParserState *ps, const char *name)
553 {
554         return ps->func[name].arity;
555 }
556
557 static void print_value(const Value &val, FILE *fp)
558 {
559         switch(val.type) {
560         case VAL_NUM:
561                 fprintf(fp, "%f", val.v[0]);
562                 break;
563
564         case VAL_VEC:
565                 fprintf(fp, "[%f %f %f %f]", val.v[0], val.v[1], val.v[2], val.v[3]);
566                 break;
567
568         case VAL_STR:
569                 fprintf(fp, "\"%s\"", val.s.c_str());
570                 break;
571
572         default:
573                 fprintf(fp, "<invalid>");
574         }
575 }
576
577 // Gear-specific stuff
578
579 static Gear *begin_gear(ParserState *ps)
580 {
581         Gear *res = new Gear;
582         ps->cur_gear.push(res);
583         return res;
584 }
585
586 static bool end_gear(ParserState *ps)
587 {
588         if(ps->cur_gear.empty()) {
589                 errmsg(ps, "parser error: unbalanced end_gear");
590                 return false;
591         }
592         Gear *gear = ps->cur_gear.top();
593         ps->cur_gear.pop();
594
595         printf("DBG: end_gear: %s\n", gear->name.c_str());
596
597         if(gear->name.empty() || ps->gears[gear->name]) {
598                 char buf[32];
599                 sprintf(buf, "gear%04d", (int)ps->gears.size());
600                 gear->name = buf;
601         }
602         printf("DBG: adding gear: %s\n", gear->name.c_str());
603         ps->gears[gear->name] = gear;
604         ps->mcn->add_gear(gear);
605         return true;
606 }
607
608 static Gear *this_gear(ParserState *ps)
609 {
610         return ps->cur_gear.empty() ? 0 : ps->cur_gear.top();
611 }
612
613 static void update_gear_vars(ParserState *ps, Gear *gear)
614 {
615         std::map<std::string, Value>::const_iterator it = ps->var.begin();
616         while(it != ps->var.end()) {
617                 set_gear_var(gear, it->first.c_str(), it->second);
618                 ++it;
619         }
620 }
621
622 #define ASSERT_TYPE(v, t) \
623         do { \
624                 if((v).type != (t)) { \
625                         fprintf(stderr, "type mismatch while trying to set %s to value: ", name); \
626                         print_value(val, stderr); \
627                         fputc('\n', stderr); \
628                         return false; \
629                 } \
630         } while(0)
631
632 #define VVEC3(val) Vec3((val).v[0], (val).v[1], (val).v[2])
633 #define VVEC4(val) Vec4((val).v[0], (val).v[1], (val).v[2], (val).v[3])
634
635 static bool set_gear_var(Gear *gear, const char *name, const Value &val)
636 {
637         if(strcmp(name, "name") == 0) {
638                 ASSERT_TYPE(val, VAL_STR);
639                 gear->name = val.s;
640
641         } else if(strcmp(name, "position") == 0) {
642                 ASSERT_TYPE(val, VAL_VEC);
643                 gear->pos = VVEC3(val);
644
645         } else if(strcmp(name, "plane") == 0) {
646                 ASSERT_TYPE(val, VAL_VEC);
647                 gear->axis = VVEC3(val);
648                 gear->pdist = val.v[3];
649
650         } else if(strcmp(name, "thickness") == 0) {
651                 ASSERT_TYPE(val, VAL_NUM);
652                 gear->thickness = val.v[0];
653
654         } else if(strcmp(name, "teeth") == 0) {
655                 ASSERT_TYPE(val, VAL_NUM);
656                 gear->set_teeth(val.v[0]);      // set teeth and recalc radius
657
658         } else if(strcmp(name, "teeth_length") == 0) {
659                 ASSERT_TYPE(val, VAL_NUM);
660                 gear->teeth_length = val.v[0];
661
662         } else if(strcmp(name, "pitch") == 0) {
663                 ASSERT_TYPE(val, VAL_NUM);
664                 gear->set_teeth(gear->nteeth, val.v[0]); // set pitch and recalc radius
665
666         } else if(strcmp(name, "color") == 0) {
667                 ASSERT_TYPE(val, VAL_VEC);
668                 gear->color = VVEC3(val);
669
670         } else if(strcmp(name, "roughness") == 0) {
671                 ASSERT_TYPE(val, VAL_NUM);
672                 gear->roughness = val.v[0];
673
674         } else {
675                 return false;
676         }
677
678         return true;
679 }
680
681
682 // motor stuff
683
684 static void update_motor_vars(ParserState *ps, Motor *motor)
685 {
686         std::map<std::string, Value>::const_iterator it = ps->var.begin();
687         while(it != ps->var.end()) {
688                 set_motor_var(ps, motor, it->first.c_str(), it->second);
689                 ++it;
690         }
691 }
692
693 static bool set_motor_var(ParserState *ps, Motor *motor, const char *name, const Value &val)
694 {
695         if(strcmp(name, "drive") == 0) {
696                 ASSERT_TYPE(val, VAL_STR);
697                 Gear *gear = ps->gears[val.s];
698                 if(!gear) {
699                         errmsg(ps, "undefined gear: %s", val.s.c_str());
700                         return false;
701                 }
702                 int idx = ps->mcn->get_gear_index(gear);
703                 assert(idx >= 0);
704                 motor->drive = idx;
705
706         } else if(strcmp(name, "speed") == 0) {
707                 ASSERT_TYPE(val, VAL_NUM);
708                 motor->speed = val.v[0];
709
710         } else {
711                 return false;
712         }
713         return true;
714 }
715
716
717 // built-in functions
718 static bool func_adjacent(ParserState *ps)
719 {
720         Value val_dir = ps->val.top(); ps->val.pop();
721         Value val_gear_name = ps->val.top(); ps->val.pop();
722
723         if(val_gear_name.type != VAL_STR) {
724                 expected(ps, "gear name (string) as 1st arg to adjacent");
725                 return false;
726         }
727         if(val_dir.type != VAL_VEC) {
728                 expected(ps, "direction vector as 2nd arg to adjacent");
729                 return false;
730         }
731
732         Gear *gthis = this_gear(ps);
733         if(!gthis) {
734                 errmsg(ps, "adjacent: called outside of a gear block");
735                 return false;
736         }
737
738         Gear *gother = ps->gears[val_gear_name.s];
739         if(!gother) {
740                 errmsg(ps, "adjacent: gear \"%s\" not found", val_gear_name.s.c_str());
741                 return false;
742         }
743
744         Vec3 dir = Vec3(val_dir.v[0], val_dir.v[1], val_dir.v[2]);
745
746         float sum_radii = gthis->radius + gother->radius;
747         float avg_teeth_len = (gthis->teeth_length + gother->teeth_length) * 0.5;
748         Vec3 pos = gother->pos + normalize(dir) * (sum_radii - avg_teeth_len * 0.75);
749
750         Value res;
751         res.type = VAL_VEC;
752         res.v[0] = pos.x;
753         res.v[1] = pos.y;
754         res.v[2] = pos.z;
755         ps->val.push(res);
756         return true;
757 }