Root/
Source at commit 377b7f81193685f23c93546767a059e194419446 created 8 years 7 days ago. By Werner Almesberger, fped.c: new option -m (for -p and -P) to suppress showing measurements | |
---|---|
1 | %{ |
2 | /* |
3 | * fpd.y - FootPrint Definition language |
4 | * |
5 | * Written 2009-2012 by Werner Almesberger |
6 | * Copyright 2009-2012 by Werner Almesberger |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or |
11 | * (at your option) any later version. |
12 | */ |
13 | |
14 | |
15 | #include <stdlib.h> |
16 | #include <string.h> |
17 | |
18 | #include "util.h" |
19 | #include "error.h" |
20 | #include "coord.h" |
21 | #include "expr.h" |
22 | #include "obj.h" |
23 | #include "meas.h" |
24 | #include "gui_status.h" |
25 | #include "gui_inst.h" /* for %meas */ |
26 | #include "dump.h" |
27 | #include "tsort.h" |
28 | #include "fpd.h" |
29 | |
30 | #include "y.tab.h" |
31 | |
32 | |
33 | struct expr *expr_result; |
34 | const char *var_id; |
35 | struct value *var_value_list; |
36 | |
37 | |
38 | static struct frame *curr_frame; |
39 | static struct table *curr_table; |
40 | static struct row *curr_row; |
41 | |
42 | static struct vec *last_vec = NULL; |
43 | |
44 | static struct table **next_table; |
45 | static struct loop **next_loop; |
46 | static struct vec **next_vec; |
47 | static struct obj **next_obj; |
48 | |
49 | static int n_vars, n_values; |
50 | |
51 | static const char *id_sin, *id_cos, *id_sqrt, *id_floor; |
52 | |
53 | static struct tsort *tsort; |
54 | |
55 | |
56 | /* ----- lookup functions -------------------------------------------------- */ |
57 | |
58 | |
59 | static struct frame *find_frame(const char *name) |
60 | { |
61 | struct frame *f; |
62 | |
63 | for (f = frames->next; f; f = f->next) |
64 | if (f->name == name) |
65 | return f; |
66 | return NULL; |
67 | } |
68 | |
69 | |
70 | static struct vec *find_vec(const struct frame *frame, const char *name) |
71 | { |
72 | struct vec *v; |
73 | |
74 | for (v = frame->vecs; v; v = v->next) |
75 | if (v->name == name) |
76 | return v; |
77 | return NULL; |
78 | } |
79 | |
80 | |
81 | static struct obj *find_obj(const struct frame *frame, const char *name) |
82 | { |
83 | struct obj *obj; |
84 | |
85 | for (obj = frame->objs; obj; obj = obj->next) |
86 | if (obj->name == name) |
87 | return obj; |
88 | return NULL; |
89 | } |
90 | |
91 | |
92 | static int find_label(const struct frame *frame, const char *name) |
93 | { |
94 | if (find_vec(frame, name)) |
95 | return 1; |
96 | if (find_obj(frame, name)) |
97 | return 1; |
98 | return 0; |
99 | } |
100 | |
101 | |
102 | static struct var *find_var(const struct frame *frame, const char *name) |
103 | { |
104 | const struct table *table; |
105 | struct var *var; |
106 | struct loop *loop; |
107 | |
108 | for (table = frame->tables; table; table = table->next) |
109 | for (var = table->vars; var; var = var->next) |
110 | if (!var->key && var->name == name) |
111 | return var; |
112 | for (loop = frame->loops; loop; loop = loop->next) |
113 | if (loop->var.name == name) |
114 | return &loop->var; |
115 | return NULL; |
116 | } |
117 | |
118 | |
119 | /* ----- item creation ----------------------------------------------------- */ |
120 | |
121 | |
122 | static void set_frame(struct frame *frame) |
123 | { |
124 | curr_frame = frame; |
125 | next_table = &frame->tables; |
126 | next_loop = &frame->loops; |
127 | next_vec = &frame->vecs; |
128 | next_obj = &frame->objs; |
129 | last_vec = NULL; |
130 | } |
131 | |
132 | |
133 | static void make_var(const char *id, int key, struct expr *expr) |
134 | { |
135 | struct table *table; |
136 | |
137 | table = zalloc_type(struct table); |
138 | table->vars = zalloc_type(struct var); |
139 | table->vars->name = id; |
140 | table->vars->frame = curr_frame; |
141 | table->vars->table = table; |
142 | table->vars->key = key; |
143 | table->rows = zalloc_type(struct row); |
144 | table->rows->table = table; |
145 | table->rows->values = zalloc_type(struct value); |
146 | table->rows->values->expr = expr; |
147 | table->rows->values->row = table->rows; |
148 | table->active_row = table->rows; |
149 | *next_table = table; |
150 | next_table = &table->next; |
151 | } |
152 | |
153 | |
154 | static void make_loop(const char *id, struct expr *from, struct expr *to) |
155 | { |
156 | struct loop *loop; |
157 | |
158 | loop = alloc_type(struct loop); |
159 | loop->var.name = id; |
160 | loop->var.next = NULL; |
161 | loop->var.frame = curr_frame; |
162 | loop->var.table = NULL; |
163 | loop->from.expr = from; |
164 | loop->from.row = NULL; |
165 | loop->from.next = NULL; |
166 | loop->to.expr = to; |
167 | loop->to.row = NULL; |
168 | loop->to.next = NULL; |
169 | loop->next = NULL; |
170 | loop->active = 0; |
171 | loop->initialized = 0; |
172 | *next_loop = loop; |
173 | next_loop = &loop->next; |
174 | } |
175 | |
176 | |
177 | static struct obj *new_obj(enum obj_type type) |
178 | { |
179 | struct obj *obj; |
180 | |
181 | obj = alloc_type(struct obj); |
182 | obj->type = type; |
183 | obj->name = NULL; |
184 | obj->frame = curr_frame; |
185 | obj->next = NULL; |
186 | obj->lineno = lineno; |
187 | return obj; |
188 | } |
189 | |
190 | |
191 | /* ---- frame qualifiers --------------------------------------------------- */ |
192 | |
193 | |
194 | static int duplicate_qualifier(const struct frame_qual *a, |
195 | const struct frame_qual *b) |
196 | { |
197 | if (!b) |
198 | return 0; |
199 | if (a != b && a->frame == b->frame) { |
200 | yyerrorf("duplicate qualifier \"%s\"", a->frame->name); |
201 | return 1; |
202 | } |
203 | if (b && duplicate_qualifier(a, b->next)) |
204 | return 1; |
205 | return duplicate_qualifier(a->next, a->next); |
206 | } |
207 | |
208 | |
209 | static int can_reach(const struct frame *curr, const struct frame_qual *qual, |
210 | const struct frame *end) |
211 | { |
212 | const struct obj *obj; |
213 | |
214 | if (curr == end) |
215 | return !qual; |
216 | |
217 | /* |
218 | * Don't recurse for removing the qualifier alone. We require a frame |
219 | * reference step as well, so that things like foo.foo.foo.bar.vec |
220 | * aren't allowed. |
221 | * |
222 | * Since a duplicate qualifier can never work, we test for this error |
223 | * explicitly in "duplicate_qualifier". |
224 | */ |
225 | if (qual && curr == qual->frame) |
226 | qual = qual->next; |
227 | |
228 | for (obj = curr->objs; obj; obj = obj->next) |
229 | if (obj->type == ot_frame) |
230 | if (can_reach(obj->u.frame.ref, qual, end)) |
231 | return 1; |
232 | return 0; |
233 | } |
234 | |
235 | |
236 | static int check_qbase(struct qbase *qbase) |
237 | { |
238 | if (duplicate_qualifier(qbase->qualifiers, qbase->qualifiers)) |
239 | return 0; |
240 | |
241 | if (!can_reach(frames, qbase->qualifiers, qbase->vec->frame)) |
242 | yywarn("not all qualifiers can be reached"); |
243 | return 1; |
244 | } |
245 | |
246 | |
247 | /* ----- debugging directives ---------------------------------------------- */ |
248 | |
249 | |
250 | static int dbg_delete(const char *frame_name, const char *name) |
251 | { |
252 | struct vec *vec; |
253 | struct obj *obj; |
254 | struct frame *frame; |
255 | |
256 | if (!frame_name) { |
257 | frame = curr_frame; |
258 | } else { |
259 | frame = find_frame(frame_name); |
260 | if (!frame) { |
261 | yyerrorf("unknown frame \"%s\"", frame_name); |
262 | return 0; |
263 | } |
264 | } |
265 | vec = find_vec(frame, name); |
266 | if (vec) { |
267 | delete_vec(vec); |
268 | return 1; |
269 | } |
270 | obj = find_obj(frame, name); |
271 | if (obj) { |
272 | delete_obj(obj); |
273 | return 1; |
274 | } |
275 | if (!frame_name) { |
276 | frame = find_frame(name); |
277 | if (frame) { |
278 | if (curr_frame == frame) { |
279 | yyerrorf("a frame can't delete itself"); |
280 | return 0; |
281 | } |
282 | delete_frame(frame); |
283 | return 1; |
284 | } |
285 | } |
286 | if (frame_name) |
287 | yyerrorf("unknown item \"%s.%s\"", frame_name, name); |
288 | else |
289 | yyerrorf("unknown item \"%s\"", name); |
290 | return 0; |
291 | } |
292 | |
293 | |
294 | static int dbg_move(const char *name, int anchor, const char *dest) |
295 | { |
296 | struct vec *to, *vec; |
297 | struct obj *obj; |
298 | struct vec **anchors[3]; |
299 | int n_anchors; |
300 | |
301 | to = find_vec(curr_frame, dest); |
302 | if (!to) { |
303 | yyerrorf("unknown vector \"%s\"", dest); |
304 | return 0; |
305 | } |
306 | vec = find_vec(curr_frame, name); |
307 | if (vec) { |
308 | if (anchor) { |
309 | yyerrorf("invalid anchor (%d > 0)", anchor); |
310 | return 0; |
311 | } |
312 | vec->base = to; |
313 | return 1; |
314 | } |
315 | obj = find_obj(curr_frame, name); |
316 | if (!obj) { |
317 | yyerrorf("unknown item \"%s\"", name); |
318 | return 0; |
319 | } |
320 | n_anchors = obj_anchors(obj, anchors); |
321 | if (anchor >= n_anchors) { |
322 | yyerrorf("invalid anchor (%d > %d)", anchor, n_anchors-1); |
323 | return 0; |
324 | } |
325 | *anchors[anchor] = to; |
326 | return 1; |
327 | } |
328 | |
329 | |
330 | /* |
331 | * @@@ This is very similar to what we do in rule "obj". Consider merging. |
332 | */ |
333 | |
334 | /* |
335 | * We need to pass base_frame and base_vec, not just the vector (with the |
336 | * frame implied) since we can also reference the frame's origin, whose |
337 | * "vector" is NULL. |
338 | */ |
339 | |
340 | static int dbg_link_frame(const char *frame_name, |
341 | struct frame *base_frame, struct vec *base_vec) |
342 | { |
343 | struct frame *frame; |
344 | struct obj *obj; |
345 | |
346 | assert(!base_vec || base_vec->frame == base_frame); |
347 | frame = find_frame(frame_name); |
348 | if (!frame) { |
349 | yyerrorf("unknown frame \"%s\"", frame_name); |
350 | return 0; |
351 | } |
352 | /* this can only fail in %frame */ |
353 | if (is_parent_of(frame, base_frame)) { |
354 | yyerrorf("frame \"%s\" is a parent of \"%s\"", |
355 | frame->name, base_frame->name); |
356 | return 0; |
357 | } |
358 | obj = new_obj(ot_frame); |
359 | obj->base = base_vec; |
360 | obj->frame = base_frame; |
361 | obj->u.frame.ref = frame; |
362 | connect_obj(base_frame, obj); |
363 | if (!frame->active_ref) |
364 | frame->active_ref = obj; |
365 | return 1; |
366 | } |
367 | |
368 | |
369 | int dbg_print(const struct expr *expr, const struct frame *frame) |
370 | { |
371 | const char *s; |
372 | struct num num; |
373 | |
374 | s = eval_str(expr, frame); |
375 | if (s) { |
376 | printf("%s\n", s); |
377 | return 1; |
378 | } |
379 | num = eval_num(expr, frame); |
380 | if (is_undef(num)) |
381 | return 0; |
382 | printf("%lg%s\n", num.n, str_unit(num)); |
383 | return 1; |
384 | } |
385 | |
386 | |
387 | static int dbg_meas(const char *name) |
388 | { |
389 | const struct obj *obj; |
390 | const struct inst *inst; |
391 | struct coord a1, b1; |
392 | char *s; |
393 | |
394 | obj = find_obj(frames, name); |
395 | if (!obj) { |
396 | yyerrorf("unknown object \"%s\"", name); |
397 | return 0; |
398 | } |
399 | |
400 | /* from fped.c:main */ |
401 | |
402 | if (!pkg_name) |
403 | pkg_name = stralloc("_"); |
404 | reporter = report_to_stderr; |
405 | if (!instantiate()) |
406 | return 0; |
407 | |
408 | inst = find_meas_hint(obj); |
409 | if (!inst) { |
410 | yyerrorf("measurement \"%s\" was not instantiated", name); |
411 | return 0; |
412 | } |
413 | |
414 | project_meas(inst, &a1, &b1); |
415 | s = format_len(obj->u.meas.label ? obj->u.meas.label : "", |
416 | dist_point(a1, b1), curr_unit); |
417 | printf("%s\n", s); |
418 | free(s); |
419 | |
420 | return 1; |
421 | } |
422 | |
423 | |
424 | %} |
425 | |
426 | |
427 | %union { |
428 | struct num num; |
429 | int flag; |
430 | char *str; |
431 | const char *id; |
432 | struct expr *expr; |
433 | struct frame *frame; |
434 | struct table *table; |
435 | struct var *var; |
436 | struct row *row; |
437 | struct value *value; |
438 | struct vec *vec; |
439 | struct obj *obj; |
440 | enum pad_type pt; |
441 | enum meas_type mt; |
442 | struct { |
443 | int inverted; |
444 | int max; |
445 | } mo; |
446 | struct { |
447 | struct frame *frame; |
448 | struct vec *vec; |
449 | } qvec; |
450 | struct qbase { |
451 | struct vec *vec; |
452 | struct frame_qual *qualifiers; |
453 | } qbase; |
454 | }; |
455 | |
456 | |
457 | %token START_FPD START_EXPR START_VAR START_VALUES |
458 | %token TOK_SET TOK_LOOP TOK_PACKAGE TOK_FRAME TOK_TABLE TOK_VEC |
459 | %token TOK_PAD TOK_RPAD TOK_HOLE TOK_RECT TOK_LINE TOK_CIRC TOK_ARC |
460 | %token TOK_MEAS TOK_MEASX TOK_MEASY TOK_UNIT |
461 | %token TOK_NEXT TOK_NEXT_INVERTED TOK_MAX TOK_MAX_INVERTED |
462 | %token TOK_DBG_DEL TOK_DBG_MOVE TOK_DBG_FRAME |
463 | %token TOK_DBG_PRINT TOK_DBG_IPRINT |
464 | %token TOK_DBG_DUMP TOK_DBG_EXIT TOK_DBG_TSORT TOK_DBG_MEAS |
465 | %token TOK_ALLOW_HOLES TOK_ALLOW_OVERLAP TOK_ALLOW_TOUCH |
466 | |
467 | %token <num> NUMBER |
468 | %token <str> STRING |
469 | %token <id> ID LABEL |
470 | |
471 | %type <table> table |
472 | %type <var> vars var |
473 | %type <row> rows |
474 | %type <value> row value opt_value_list |
475 | %type <vec> vec base |
476 | %type <obj> object obj meas unlabeled_meas |
477 | %type <expr> expr opt_expr add_expr mult_expr unary_expr primary_expr |
478 | %type <num> opt_num |
479 | %type <flag> opt_key |
480 | %type <frame> frame_qualifier |
481 | %type <str> opt_string |
482 | %type <pt> pad_type |
483 | %type <mt> meas_type |
484 | %type <mo> meas_op |
485 | %type <qvec> qualified_base |
486 | %type <qbase> qbase qbase_unchecked |
487 | |
488 | %% |
489 | |
490 | all: |
491 | START_FPD |
492 | { |
493 | frames = zalloc_type(struct frame); |
494 | set_frame(frames); |
495 | id_sin = unique("sin"); |
496 | id_cos = unique("cos"); |
497 | id_sqrt = unique("sqrt"); |
498 | id_floor = unique("floor"); |
499 | } |
500 | fpd |
501 | | START_EXPR expr |
502 | { |
503 | expr_result = $2; |
504 | } |
505 | | START_VAR ID opt_value_list |
506 | { |
507 | var_id = $2; |
508 | var_value_list = $3; |
509 | } |
510 | | START_VALUES row |
511 | { |
512 | var_value_list = $2; |
513 | } |
514 | ; |
515 | |
516 | fpd: |
517 | frame_defs part_name opt_setup opt_frame_items opt_measurements |
518 | | frame_defs setup opt_frame_items opt_measurements |
519 | | frame_defs frame_items opt_measurements |
520 | | frame_defs opt_measurements |
521 | ; |
522 | |
523 | part_name: |
524 | TOK_PACKAGE STRING |
525 | { |
526 | const char *p; |
527 | |
528 | if (!*$2) { |
529 | yyerrorf("invalid package name"); |
530 | YYABORT; |
531 | } |
532 | for (p = $2; *p; *p++) |
533 | if (*p < 32 || *p > 126) { |
534 | yyerrorf("invalid package name"); |
535 | YYABORT; |
536 | } |
537 | pkg_name = $2; |
538 | } |
539 | ; |
540 | |
541 | opt_setup: |
542 | | setup |
543 | ; |
544 | |
545 | setup: |
546 | unit |
547 | | allow_pads |
548 | | allow_holes |
549 | | unit allow_pads |
550 | | unit allow_pads allow_holes |
551 | | unit allow_holes |
552 | | unit allow_holes allow_pads |
553 | | allow_pads unit |
554 | | allow_pads unit allow_holes |
555 | | allow_holes unit |
556 | | allow_holes unit allow_pads |
557 | ; |
558 | |
559 | unit: |
560 | TOK_UNIT ID |
561 | { |
562 | if (!strcmp($2, "mm")) |
563 | curr_unit = curr_unit_mm; |
564 | else if (!strcmp($2, "mil")) |
565 | curr_unit = curr_unit_mil; |
566 | else if (!strcmp($2, "auto")) |
567 | curr_unit = curr_unit_auto; |
568 | else { |
569 | yyerrorf("unrecognized unit \"%s\"", $2); |
570 | YYABORT; |
571 | } |
572 | } |
573 | ; |
574 | |
575 | allow_pads: |
576 | TOK_ALLOW_TOUCH |
577 | { |
578 | allow_overlap = ao_touch; |
579 | } |
580 | | TOK_ALLOW_OVERLAP |
581 | { |
582 | allow_overlap = ao_any; |
583 | } |
584 | ; |
585 | |
586 | allow_holes: |
587 | TOK_ALLOW_HOLES |
588 | { |
589 | holes_linked = 0; |
590 | } |
591 | ; |
592 | |
593 | frame_defs: |
594 | | frame_defs frame_def |
595 | ; |
596 | |
597 | frame_def: |
598 | TOK_FRAME ID '{' |
599 | { |
600 | if (find_frame($2)) { |
601 | yyerrorf("duplicate frame \"%s\"", $2); |
602 | YYABORT; |
603 | } |
604 | curr_frame = zalloc_type(struct frame); |
605 | curr_frame->name = $2; |
606 | set_frame(curr_frame); |
607 | curr_frame->next = frames->next; |
608 | frames->next = curr_frame; |
609 | } |
610 | opt_frame_items '}' |
611 | { |
612 | set_frame(frames); |
613 | } |
614 | ; |
615 | |
616 | opt_frame_items: |
617 | | frame_items |
618 | ; |
619 | |
620 | frame_items: |
621 | frame_item |
622 | | frame_item frame_items |
623 | ; |
624 | |
625 | frame_item: |
626 | table |
627 | | TOK_SET opt_key ID '=' expr |
628 | { |
629 | if (!$2 && find_var(curr_frame, $3)) { |
630 | yyerrorf("duplicate variable \"%s\"", $3); |
631 | YYABORT; |
632 | } |
633 | make_var($3, $2, $5); |
634 | } |
635 | | TOK_LOOP ID '=' expr ',' expr |
636 | { |
637 | if (find_var(curr_frame, $2)) { |
638 | yyerrorf("duplicate variable \"%s\"", $2); |
639 | YYABORT; |
640 | } |
641 | make_loop($2, $4, $6); |
642 | } |
643 | | vec |
644 | | LABEL vec |
645 | { |
646 | if (find_label(curr_frame, $1)) { |
647 | yyerrorf("duplicate label \"%s\"", $1); |
648 | YYABORT; |
649 | } |
650 | $2->name = $1; |
651 | } |
652 | | object |
653 | | LABEL object |
654 | { |
655 | if (find_label(curr_frame, $1)) { |
656 | yyerrorf("duplicate label \"%s\"", $1); |
657 | YYABORT; |
658 | } |
659 | $2->name = $1; |
660 | } |
661 | | debug_item |
662 | ; |
663 | |
664 | debug_item: |
665 | TOK_DBG_DEL ID |
666 | { |
667 | if (!dbg_delete(NULL, $2)) |
668 | YYABORT; |
669 | } |
670 | | TOK_DBG_DEL ID '.' ID |
671 | { |
672 | if (!dbg_delete($2, $4)) |
673 | YYABORT; |
674 | } |
675 | | TOK_DBG_MOVE ID opt_num ID |
676 | { |
677 | if (!dbg_move($2, $3.n, $4)) |
678 | YYABORT; |
679 | } |
680 | | TOK_DBG_FRAME ID qualified_base |
681 | { |
682 | if (!dbg_link_frame($2, $3.frame, $3.vec)) |
683 | YYABORT; |
684 | } |
685 | | TOK_DBG_PRINT expr |
686 | { |
687 | if (!dbg_print($2, curr_frame)) |
688 | YYABORT; |
689 | } |
690 | | TOK_DBG_MEAS ID |
691 | { |
692 | if (!dbg_meas($2)) |
693 | YYABORT; |
694 | } |
695 | | TOK_DBG_DUMP |
696 | { |
697 | if (!dump(stdout, NULL)) { |
698 | perror("stdout"); |
699 | exit(1); |
700 | } |
701 | } |
702 | | TOK_DBG_EXIT |
703 | { |
704 | exit(0); |
705 | } |
706 | | TOK_DBG_TSORT '{' |
707 | { |
708 | tsort = begin_tsort(); |
709 | } |
710 | sort_items '}' |
711 | { |
712 | void **sort, **walk; |
713 | |
714 | sort = end_tsort(tsort); |
715 | for (walk = sort; *walk; walk++) |
716 | printf("%s\n", (char *) *walk); |
717 | free(sort); |
718 | } |
719 | ; |
720 | |
721 | sort_items: |
722 | | sort_items '+' ID |
723 | { |
724 | add_node(tsort, (void *) $3, 0); |
725 | } |
726 | | sort_items '-' ID |
727 | { |
728 | add_node(tsort, (void *) $3, 1); |
729 | } |
730 | | sort_items ID ID opt_num |
731 | { |
732 | struct node *a, *b; |
733 | |
734 | /* order is important here ! */ |
735 | a = add_node(tsort, (void *) $2, 0); |
736 | b = add_node(tsort, (void *) $3, 0); |
737 | add_edge(a, b, $4.n); |
738 | } |
739 | ; |
740 | |
741 | table: |
742 | TOK_TABLE |
743 | { |
744 | $<table>$ = zalloc_type(struct table); |
745 | *next_table = $<table>$; |
746 | curr_table = $<table>$; |
747 | n_vars = 0; |
748 | } |
749 | '{' vars '}' rows |
750 | { |
751 | $$ = $<table>2; |
752 | $$->vars = $4; |
753 | $$->rows = $6; |
754 | $$->active_row = $6; |
755 | next_table = &$$->next; |
756 | } |
757 | ; |
758 | |
759 | vars: |
760 | var |
761 | { |
762 | $$ = $1; |
763 | } |
764 | | vars ',' var |
765 | { |
766 | struct var **walk; |
767 | |
768 | $$ = $1; |
769 | for (walk = &$$; *walk; walk = &(*walk)->next); |
770 | *walk = $3; |
771 | } |
772 | ; |
773 | |
774 | var: |
775 | opt_key ID |
776 | { |
777 | if (!$1 && find_var(curr_frame, $2)) { |
778 | yyerrorf("duplicate variable \"%s\"", $2); |
779 | YYABORT; |
780 | } |
781 | $$ = zalloc_type(struct var); |
782 | $$->name = $2; |
783 | $$->frame = curr_frame; |
784 | $$->table = curr_table; |
785 | $$->key = $1; |
786 | $$->next = NULL; |
787 | n_vars++; |
788 | } |
789 | ; |
790 | |
791 | opt_key: |
792 | { |
793 | $$ = 0; |
794 | } |
795 | | '?' |
796 | { |
797 | $$ = 1; |
798 | } |
799 | ; |
800 | |
801 | rows: |
802 | { |
803 | $$ = NULL; |
804 | } |
805 | | '{' |
806 | { |
807 | $<row>$ = alloc_type(struct row); |
808 | $<row>$->table = curr_table; |
809 | curr_row = $<row>$;; |
810 | n_values = 0; |
811 | } |
812 | row '}' |
813 | { |
814 | if (n_vars != n_values) { |
815 | yyerrorf("table has %d variables but row has " |
816 | "%d values", n_vars, n_values); |
817 | YYABORT; |
818 | } |
819 | $<row>2->values = $3; |
820 | } |
821 | rows |
822 | { |
823 | $$ = $<row>2; |
824 | $$->next = $6; |
825 | } |
826 | ; |
827 | |
828 | row: |
829 | value |
830 | { |
831 | $$ = $1; |
832 | } |
833 | | row ',' value |
834 | { |
835 | struct value **walk; |
836 | |
837 | $$ = $1; |
838 | for (walk = &$$; *walk; walk = &(*walk)->next); |
839 | *walk = $3; |
840 | } |
841 | ; |
842 | |
843 | value: |
844 | expr |
845 | { |
846 | $$ = alloc_type(struct value); |
847 | $$->expr = $1; |
848 | $$->row = curr_row; |
849 | $$->next = NULL; |
850 | n_values++; |
851 | } |
852 | ; |
853 | |
854 | vec: |
855 | TOK_VEC base '(' expr ',' expr ')' |
856 | { |
857 | $$ = alloc_type(struct vec); |
858 | $$->nul_tag = 0; |
859 | $$->name = NULL; |
860 | $$->base = $2; |
861 | $$->x = $4; |
862 | $$->y = $6; |
863 | $$->frame = curr_frame; |
864 | $$->next = NULL; |
865 | last_vec = $$; |
866 | *next_vec = $$; |
867 | next_vec = &$$->next; |
868 | } |
869 | ; |
870 | |
871 | base: |
872 | '@' |
873 | { |
874 | $$ = NULL; |
875 | } |
876 | | '.' |
877 | { |
878 | $$ = last_vec; |
879 | if (!$$) { |
880 | yyerrorf(". without predecessor"); |
881 | YYABORT; |
882 | } |
883 | } |
884 | | ID |
885 | { |
886 | $$ = find_vec(curr_frame, $1); |
887 | if (!$$) |
888 | $$ = (struct vec *) $1; |
889 | } |
890 | ; |
891 | |
892 | qualified_base: |
893 | base |
894 | { |
895 | $$.frame = curr_frame; |
896 | $$.vec = $1; |
897 | } |
898 | | frame_qualifier '@' |
899 | { |
900 | $$.frame = $1; |
901 | $$.vec = NULL; |
902 | } |
903 | | frame_qualifier ID |
904 | { |
905 | $$.frame = $1; |
906 | $$.vec = find_vec($1, $2); |
907 | if (!$$.vec) { |
908 | yyerrorf("unknown vector \"%s.%s\"", |
909 | $1->name, $2); |
910 | YYABORT; |
911 | } |
912 | } |
913 | ; |
914 | |
915 | frame_qualifier: |
916 | ID '.' |
917 | { |
918 | $$ = find_frame($1); |
919 | if (!$$) { |
920 | yyerrorf("unknown frame \"%s\"", $1); |
921 | YYABORT; |
922 | } |
923 | } |
924 | ; |
925 | |
926 | object: |
927 | obj |
928 | { |
929 | $$ = $1; |
930 | *next_obj = $1; |
931 | next_obj = &$1->next; |
932 | } |
933 | ; |
934 | |
935 | obj: |
936 | TOK_PAD STRING base base pad_type |
937 | { |
938 | $$ = new_obj(ot_pad); |
939 | $$->base = $3; |
940 | $$->u.pad.name = $2; |
941 | $$->u.pad.other = $4; |
942 | $$->u.pad.rounded = 0; |
943 | $$->u.pad.type = $5; |
944 | } |
945 | | TOK_RPAD STRING base base pad_type |
946 | { |
947 | $$ = new_obj(ot_pad); |
948 | $$->base = $3; |
949 | $$->u.pad.name = $2; |
950 | $$->u.pad.other = $4; |
951 | $$->u.pad.rounded = 1; |
952 | $$->u.pad.type = $5; |
953 | } |
954 | | TOK_HOLE base base |
955 | { |
956 | $$ = new_obj(ot_hole); |
957 | $$->base = $2; |
958 | $$->u.hole.other = $3; |
959 | } |
960 | | TOK_RECT base base opt_expr |
961 | { |
962 | $$ = new_obj(ot_rect); |
963 | $$->base = $2; |
964 | $$->u.rect.other = $3; |
965 | $$->u.rect.width = $4; |
966 | } |
967 | | TOK_LINE base base opt_expr |
968 | { |
969 | $$ = new_obj(ot_line); |
970 | $$->base = $2; |
971 | $$->u.line.other = $3; |
972 | $$->u.line.width = $4; |
973 | } |
974 | | TOK_CIRC base base opt_expr |
975 | { |
976 | $$ = new_obj(ot_arc); |
977 | $$->base = $2; |
978 | $$->u.arc.start = $3; |
979 | $$->u.arc.end = $3; |
980 | $$->u.arc.width = $4; |
981 | } |
982 | | TOK_ARC base base base opt_expr |
983 | { |
984 | $$ = new_obj(ot_arc); |
985 | $$->base = $2; |
986 | $$->u.arc.start = $3; |
987 | $$->u.arc.end = $4; |
988 | $$->u.arc.width = $5; |
989 | } |
990 | | TOK_FRAME ID |
991 | { |
992 | $<num>$.n = lineno; |
993 | } |
994 | base |
995 | { |
996 | $$ = new_obj(ot_frame); |
997 | $$->base = $4; |
998 | $$->u.frame.ref = find_frame($2); |
999 | if (!$$->u.frame.ref) { |
1000 | yyerrorf("unknown frame \"%s\"", $2); |
1001 | YYABORT; |
1002 | } |
1003 | if (!$$->u.frame.ref->active_ref) |
1004 | $$->u.frame.ref->active_ref = $$; |
1005 | $$->u.frame.lineno = $<num>3.n; |
1006 | } |
1007 | | TOK_DBG_IPRINT expr |
1008 | { |
1009 | $$ = new_obj(ot_iprint); |
1010 | $$->base = NULL; |
1011 | $$->u.iprint.expr = $2; |
1012 | } |
1013 | ; |
1014 | |
1015 | pad_type: |
1016 | { |
1017 | $$ = pt_normal; |
1018 | } |
1019 | | ID |
1020 | { |
1021 | if (!strcmp($1, "bare")) |
1022 | $$ = pt_bare; |
1023 | else if (!strcmp($1, "trace")) |
1024 | $$ = pt_trace; |
1025 | else if (!strcmp($1, "paste")) |
1026 | $$ = pt_paste; |
1027 | else if (!strcmp($1, "mask")) |
1028 | $$ = pt_mask; |
1029 | else { |
1030 | yyerrorf("unknown pad type \"%s\"", $1); |
1031 | YYABORT; |
1032 | } |
1033 | } |
1034 | ; |
1035 | |
1036 | opt_measurements: |
1037 | | measurements |
1038 | ; |
1039 | |
1040 | measurements: |
1041 | unlabeled_meas /* @@@ hack */ |
1042 | { |
1043 | *next_obj = $1; |
1044 | next_obj = &$1->next; |
1045 | } |
1046 | | measurements meas |
1047 | { |
1048 | *next_obj = $2; |
1049 | next_obj = &$2->next; |
1050 | } |
1051 | | measurements debug_item |
1052 | ; |
1053 | |
1054 | meas: |
1055 | unlabeled_meas |
1056 | { |
1057 | $$ = $1; |
1058 | } |
1059 | | LABEL unlabeled_meas |
1060 | { |
1061 | $$ = $2; |
1062 | if (find_label(curr_frame, $1)) { |
1063 | yyerrorf("duplicate label \"%s\"", $1); |
1064 | YYABORT; |
1065 | } |
1066 | $$->name = $1; |
1067 | } |
1068 | ; |
1069 | |
1070 | unlabeled_meas: |
1071 | meas_type opt_string qbase meas_op qbase opt_expr |
1072 | { |
1073 | struct meas *meas; |
1074 | |
1075 | $$ = new_obj(ot_meas); |
1076 | meas = &$$->u.meas; |
1077 | meas->type = $4.max ? $1+3 : $1; |
1078 | meas->label = $2; |
1079 | $$->base = $3.vec; |
1080 | meas->low_qual = $3.qualifiers; |
1081 | meas->inverted = $4.inverted; |
1082 | meas->high = $5.vec; |
1083 | meas->high_qual = $5.qualifiers; |
1084 | meas->offset = $6; |
1085 | $$->next = NULL; |
1086 | } |
1087 | ; |
1088 | |
1089 | qbase: |
1090 | qbase_unchecked |
1091 | { |
1092 | $$ = $1; |
1093 | if (!check_qbase(&$$)) |
1094 | YYABORT; |
1095 | } |
1096 | ; |
1097 | |
1098 | qbase_unchecked: |
1099 | ID |
1100 | { |
1101 | $$.vec = find_vec(frames, $1); |
1102 | if (!$$.vec) { |
1103 | yyerrorf("unknown vector \"%s\"", $1); |
1104 | YYABORT; |
1105 | } |
1106 | $$.qualifiers = NULL; |
1107 | } |
1108 | | ID '.' ID |
1109 | { |
1110 | const struct frame *frame; |
1111 | |
1112 | frame = find_frame($1); |
1113 | $$.vec = frame ? find_vec(frame, $3) : NULL; |
1114 | if (!$$.vec) { |
1115 | yyerrorf("unknown vector \"%s.%s\"", $1, $3); |
1116 | YYABORT; |
1117 | } |
1118 | $$.qualifiers = NULL; |
1119 | } |
1120 | | ID '/' qbase |
1121 | { |
1122 | const struct frame *frame; |
1123 | struct frame_qual *qual; |
1124 | |
1125 | $$ = $3; |
1126 | frame = find_frame($1); |
1127 | if (!frame) { |
1128 | yyerrorf("unknown frame \"%s\"", $1); |
1129 | YYABORT; |
1130 | } else { |
1131 | qual = alloc_type(struct frame_qual); |
1132 | qual->frame = frame; |
1133 | qual->next = $$.qualifiers; |
1134 | $$.qualifiers = qual; |
1135 | } |
1136 | } |
1137 | ; |
1138 | |
1139 | meas_type: |
1140 | TOK_MEAS |
1141 | { |
1142 | $$ = mt_xy_next; |
1143 | } |
1144 | | TOK_MEASX |
1145 | { |
1146 | $$ = mt_x_next; |
1147 | } |
1148 | | TOK_MEASY |
1149 | { |
1150 | $$ = mt_y_next; |
1151 | } |
1152 | ; |
1153 | |
1154 | meas_op: |
1155 | TOK_NEXT |
1156 | { |
1157 | $$.max = 0; |
1158 | $$.inverted = 0; |
1159 | } |
1160 | | TOK_NEXT_INVERTED |
1161 | { |
1162 | $$.max = 0; |
1163 | $$.inverted = 1; |
1164 | } |
1165 | | TOK_MAX |
1166 | { |
1167 | $$.max = 1; |
1168 | $$.inverted = 0; |
1169 | } |
1170 | | TOK_MAX_INVERTED |
1171 | { |
1172 | $$.max = 1; |
1173 | $$.inverted = 1; |
1174 | } |
1175 | ; |
1176 | |
1177 | opt_num: |
1178 | { |
1179 | $$.n = 0; |
1180 | } |
1181 | | NUMBER |
1182 | { |
1183 | $$ = $1; |
1184 | } |
1185 | ; |
1186 | |
1187 | opt_string: |
1188 | { |
1189 | $$ = NULL; |
1190 | } |
1191 | | STRING |
1192 | { |
1193 | $$ = $1; |
1194 | } |
1195 | ; |
1196 | |
1197 | opt_expr: |
1198 | { |
1199 | $$ = NULL; |
1200 | } |
1201 | | expr |
1202 | { |
1203 | $$ = $1; |
1204 | } |
1205 | ; |
1206 | |
1207 | expr: |
1208 | add_expr |
1209 | { |
1210 | $$ = $1; |
1211 | } |
1212 | ; |
1213 | |
1214 | add_expr: |
1215 | mult_expr |
1216 | { |
1217 | $$ = $1; |
1218 | } |
1219 | | add_expr '+' mult_expr |
1220 | { |
1221 | $$ = binary_op(op_add, $1, $3); |
1222 | } |
1223 | | add_expr '-' mult_expr |
1224 | { |
1225 | $$ = binary_op(op_sub, $1, $3); |
1226 | } |
1227 | ; |
1228 | |
1229 | mult_expr: |
1230 | unary_expr |
1231 | { |
1232 | $$ = $1; |
1233 | } |
1234 | | mult_expr '*' unary_expr |
1235 | { |
1236 | $$ = binary_op(op_mult, $1, $3); |
1237 | } |
1238 | | mult_expr '/' unary_expr |
1239 | { |
1240 | $$ = binary_op(op_div, $1, $3); |
1241 | } |
1242 | ; |
1243 | |
1244 | unary_expr: |
1245 | primary_expr |
1246 | { |
1247 | $$ = $1; |
1248 | } |
1249 | | '-' primary_expr |
1250 | { |
1251 | $$ = binary_op(op_minus, $2, NULL); |
1252 | } |
1253 | ; |
1254 | |
1255 | primary_expr: |
1256 | NUMBER |
1257 | { |
1258 | $$ = new_op(op_num); |
1259 | $$->u.num = $1; |
1260 | } |
1261 | | ID |
1262 | { |
1263 | $$ = new_op(op_var); |
1264 | $$->u.var = $1; |
1265 | } |
1266 | | STRING |
1267 | { |
1268 | $$ = new_op(op_string); |
1269 | $$->u.str = $1; |
1270 | } |
1271 | | '(' expr ')' |
1272 | { |
1273 | $$ = $2; |
1274 | } |
1275 | | ID '(' expr ')' |
1276 | { |
1277 | if ($1 == id_sin) |
1278 | $$ = binary_op(op_sin, $3, NULL); |
1279 | else if ($1 == id_cos) |
1280 | $$ = binary_op(op_cos, $3, NULL); |
1281 | else if ($1 == id_sqrt) |
1282 | $$ = binary_op(op_sqrt, $3, NULL); |
1283 | else if ($1 == id_floor) |
1284 | $$ = binary_op(op_floor, $3, NULL); |
1285 | else { |
1286 | yyerrorf("unknown function \"%s\"", $1); |
1287 | YYABORT; |
1288 | } |
1289 | } |
1290 | ; |
1291 | |
1292 | /* special sub-grammar */ |
1293 | |
1294 | opt_value_list: |
1295 | { |
1296 | $$ = NULL; |
1297 | } |
1298 | | '=' row |
1299 | { |
1300 | $$ = $2; |
1301 | } |
1302 | ; |
1303 |
Branches:
master