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