10 enum ValueType { VAL_NUM, VAL_VEC, VAL_STR };
19 typedef bool (*Func)(ParserState*);
35 std::stack<Value> val;
36 std::map<std::string, Value> var;
37 std::map<std::string, FuncDesc> func;
39 std::map<std::string, Gear*> gears;
40 std::stack<Gear*> cur_gear;
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);
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);
58 static bool nextchar(ParserState *ps);
59 static void putback(ParserState *ps, char c);
61 static void errmsg(ParserState *ps, const char *fmt, ...);
62 static void expected(ParserState *ps, const char *str);
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);
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);
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);
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);
83 static bool func_adjacent(ParserState *ps);
86 bool parse_machine(Machine *mcn, const char *fname)
88 FILE *fp = fopen(fname, "rb");
101 // init built-in function table
102 set_func(&pstate, "adjacent", func_adjacent, 2);
105 bool res = machine(&pstate);
110 static bool machine(ParserState *ps)
112 char tok[MAX_ID_LEN + 1];
113 if(strcmp(get_ident(ps, tok, sizeof tok), "machine") != 0) {
114 expected(ps, "machine");
119 while(ps->nextc != '}') {
128 static bool expect(ParserState *ps, char c)
131 char buf[2] = {0, 0};
140 static bool statement(ParserState *ps)
142 char id[MAX_ID_LEN + 1];
143 if(!get_ident(ps, id, sizeof id)) {
147 if(strcmp(id, "gear") == 0) {
148 if(!expect(ps, '{')) {
152 Gear *gear = begin_gear(ps);
153 if(!gear) return false;
155 update_gear_vars(ps, gear);
157 while(ps->nextc != '}') {
170 if(strcmp(id, "motor") == 0) {
171 if(!expect(ps, '{')) {
175 errmsg(ps, "nested motors not allowed");
179 ps->cur_motor = new Motor;
180 update_motor_vars(ps, ps->cur_motor);
182 while(ps->nextc != '}') {
189 ps->mcn->add_motor(ps->cur_motor->drive, ps->cur_motor->speed);
190 delete ps->cur_motor;
195 if(ps->nextc == '=') {
197 if(!expression(ps)) {
202 set_var(ps, id, ps->val.top());
207 expected(ps, "expression");
211 static bool expression(ParserState *ps)
216 static bool term(ParserState *ps)
218 if(ps->nextc == '+') {
220 return expression(ps);
222 if(ps->nextc == '-') {
224 if(!expression(ps)) {
228 Value &v = ps->val.top();
239 expected(ps, "number or vector after an unary -");
244 if(isalpha(ps->nextc)) {
245 char buf[MAX_ID_LEN];
246 if(!get_ident(ps, buf, sizeof buf)) {
250 if(ps->nextc == '(') {
251 if(!function(ps, buf)) {
254 } else if(have_var(ps, buf)) {
255 ps->val.push(get_var(ps, buf));
257 errmsg(ps, "unknown identifier: %s", buf);
262 if(isdigit(ps->nextc)) {
264 if(!get_number(ps, &num)) {
274 if(ps->nextc == '[') {
277 if(ps->nextc == '"') {
278 char buf[MAX_ID_LEN];
279 if(!get_string(ps, buf, sizeof buf)) {
290 expected(ps, "term");
294 static bool vector(ParserState *ps)
297 if(!expect(ps, '[') ||
306 if(ps->nextc == ']') {
310 if(!expect(ps, ',') || !expression(ps) || !expect(ps, ']')) {
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");
334 static bool function(ParserState *ps, const char *name)
336 if(!expect(ps, '(')) {
340 if(!have_func(ps, name)) {
341 errmsg(ps, "unknown function: %s", name);
346 while(ps->nextc != ')') {
347 if(nargs && !expect(ps, ',')) {
350 if(!expression(ps)) {
357 int arity = get_func_arity(ps, name);
359 errmsg(ps, "function %s expects %d arguments", name, arity);
362 Func func = get_func(ps, name);
366 errmsg(ps, "function %s failed", name);
372 static char *get_ident(ParserState *ps, char *buf, int bsz)
375 if(!isalpha(ps->nextc)) {
376 expected(ps, "identifier");
379 while(isalnum(ps->nextc) || ps->nextc == '_') {
387 printf("get_ident -> \"%s\"\n", buf);
391 static bool get_number(ParserState *ps, float *num)
393 char buf[256], *ptr = buf, *end = buf + sizeof buf;
394 bool found_point = false;
396 if(!isdigit(ps->nextc)) {
397 expected(ps, "number");
401 while(isdigit(ps->nextc) || (ps->nextc == '.' && !found_point)) {
405 if(ps->nextc == '.') {
413 printf("get_number -> %f\n", *num);
417 static char *get_string(ParserState *ps, char *buf, int bsz)
420 if(!expect(ps, '"')) {
424 while(ps->nextc != -1 && ps->nextc != '"') {
429 if((ps->nextc = fgetc(ps->fp)) == '\n') {
435 if(ps->nextc == -1) {
440 printf("get_string -> \"%s\"\n", buf);
444 static bool skip_line(ParserState *ps)
447 while((c = fgetc(ps->fp)) != -1 && c != '\n');
449 ps->nextc = fgetc(ps->fp);
455 static bool nextchar(ParserState *ps)
457 if(ps->savedc != -1) {
458 ps->nextc = ps->savedc;
463 while((ps->nextc = fgetc(ps->fp)) != -1) {
464 if(ps->nextc == '#') {
470 if(!isspace(ps->nextc)) {
473 if(ps->nextc == '\n') {
478 /*if(ps->nextc != -1) {
479 printf("DBG: nextchar -> %c\n", ps->nextc);
481 printf("DBG: nextchar -> EOF\n");
483 return ps->nextc != -1;
486 static void putback(ParserState *ps, char c)
488 ps->savedc = ps->nextc;
492 static void errmsg(ParserState *ps, const char *fmt, ...)
494 fprintf(stderr, "%s line %d error: ", ps->fname, ps->nline);
498 vfprintf(stderr, fmt, ap);
504 static void expected(ParserState *ps, const char *str)
506 errmsg(ps, "expected: %s", str);
510 static void set_var(ParserState *ps, const char *name, const Value &value)
512 ps->var[name] = value;
514 Gear *gear = this_gear(ps);
516 set_gear_var(gear, name, value);
520 set_motor_var(ps, ps->cur_motor, name, value);
524 static bool have_var(ParserState *ps, const char *name)
526 return ps->var.find(name) != ps->var.end();
529 static const Value &get_var(ParserState *ps, const char *name)
531 return ps->var[name];
534 static void set_func(ParserState *ps, const char *name, Func func, int nargs)
539 ps->func[name] = fdesc;
542 static bool have_func(ParserState *ps, const char *name)
544 return ps->func.find(name) != ps->func.end();
547 static Func get_func(ParserState *ps, const char *name)
549 return ps->func[name].func;
552 static int get_func_arity(ParserState *ps, const char *name)
554 return ps->func[name].arity;
557 static void print_value(const Value &val, FILE *fp)
561 fprintf(fp, "%f", val.v[0]);
565 fprintf(fp, "[%f %f %f %f]", val.v[0], val.v[1], val.v[2], val.v[3]);
569 fprintf(fp, "\"%s\"", val.s.c_str());
573 fprintf(fp, "<invalid>");
577 // Gear-specific stuff
579 static Gear *begin_gear(ParserState *ps)
581 Gear *res = new Gear;
582 ps->cur_gear.push(res);
586 static bool end_gear(ParserState *ps)
588 if(ps->cur_gear.empty()) {
589 errmsg(ps, "parser error: unbalanced end_gear");
592 Gear *gear = ps->cur_gear.top();
595 printf("DBG: end_gear: %s\n", gear->name.c_str());
597 if(gear->name.empty() || ps->gears[gear->name]) {
599 sprintf(buf, "gear%04d", (int)ps->gears.size());
602 printf("DBG: adding gear: %s\n", gear->name.c_str());
603 ps->gears[gear->name] = gear;
604 ps->mcn->add_gear(gear);
608 static Gear *this_gear(ParserState *ps)
610 return ps->cur_gear.empty() ? 0 : ps->cur_gear.top();
613 static void update_gear_vars(ParserState *ps, Gear *gear)
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);
622 #define ASSERT_TYPE(v, t) \
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); \
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])
635 static bool set_gear_var(Gear *gear, const char *name, const Value &val)
637 if(strcmp(name, "name") == 0) {
638 ASSERT_TYPE(val, VAL_STR);
641 } else if(strcmp(name, "position") == 0) {
642 ASSERT_TYPE(val, VAL_VEC);
643 gear->pos = VVEC3(val);
645 } else if(strcmp(name, "plane") == 0) {
646 ASSERT_TYPE(val, VAL_VEC);
647 gear->axis = VVEC3(val);
648 gear->pdist = val.v[3];
650 } else if(strcmp(name, "thickness") == 0) {
651 ASSERT_TYPE(val, VAL_NUM);
652 gear->thickness = val.v[0];
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
658 } else if(strcmp(name, "teeth_length") == 0) {
659 ASSERT_TYPE(val, VAL_NUM);
660 gear->teeth_length = val.v[0];
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
666 } else if(strcmp(name, "color") == 0) {
667 ASSERT_TYPE(val, VAL_VEC);
668 gear->color = VVEC3(val);
670 } else if(strcmp(name, "roughness") == 0) {
671 ASSERT_TYPE(val, VAL_NUM);
672 gear->roughness = val.v[0];
684 static void update_motor_vars(ParserState *ps, Motor *motor)
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);
693 static bool set_motor_var(ParserState *ps, Motor *motor, const char *name, const Value &val)
695 if(strcmp(name, "drive") == 0) {
696 ASSERT_TYPE(val, VAL_STR);
697 Gear *gear = ps->gears[val.s];
699 errmsg(ps, "undefined gear: %s", val.s.c_str());
702 int idx = ps->mcn->get_gear_index(gear);
706 } else if(strcmp(name, "speed") == 0) {
707 ASSERT_TYPE(val, VAL_NUM);
708 motor->speed = val.v[0];
717 // built-in functions
718 static bool func_adjacent(ParserState *ps)
720 Value val_dir = ps->val.top(); ps->val.pop();
721 Value val_gear_name = ps->val.top(); ps->val.pop();
723 if(val_gear_name.type != VAL_STR) {
724 expected(ps, "gear name (string) as 1st arg to adjacent");
727 if(val_dir.type != VAL_VEC) {
728 expected(ps, "direction vector as 2nd arg to adjacent");
732 Gear *gthis = this_gear(ps);
734 errmsg(ps, "adjacent: called outside of a gear block");
738 Gear *gother = ps->gears[val_gear_name.s];
740 errmsg(ps, "adjacent: gear \"%s\" not found", val_gear_name.s.c_str());
744 Vec3 dir = Vec3(val_dir.v[0], val_dir.v[1], val_dir.v[2]);
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);