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