Root/cameo/lang.y

1%{
2/*
3 * lang.y - Toolpath adaptation language
4 *
5 * Written 2010-2013, 2015 by Werner Almesberger
6 * Copyright 2010-2013, 2015 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 <stdio.h>
17#include <math.h>
18
19#include "path.h"
20#include "ops.h"
21#include "area.h"
22#include "gnuplot.h"
23#include "gerber.h"
24#include "excellon.h"
25
26#include "y.tab.h"
27
28
29static double xo = 0, yo = 0, zo = 0; /* origin */
30static double rot = 0;
31static struct path *paths = NULL;
32static struct path *remain = NULL;
33
34
35#define MIL2MM(mil) ((mil)/1000*25.4)
36
37
38static void add_paths(struct path *new)
39{
40    struct path **anchor = &paths;
41
42    while (*anchor)
43        anchor = &(*anchor)->next;
44    *anchor = new;
45}
46
47
48static void translate(struct path *list, double x, double y, double z)
49{
50    struct path *path;
51    struct point *p;
52
53    for (path = list; path; path = path->next)
54        for (p = path->first; p; p = p->next) {
55            p->x += x;
56            p->y += y;
57            p->z += z;
58        }
59}
60
61
62static void rotate(struct path *list, double angle)
63{
64    double m[2][2], tmp;
65    struct point *p;
66
67    angle = angle/180.0*M_PI;
68    m[0][0] = cos(angle);
69    m[0][1] = -sin(angle);
70    m[1][0] = -m[0][1];
71    m[1][1] = m[0][0];
72    while (list) {
73        for (p = list->first; p; p = p->next) {
74            tmp = p->x*m[0][0]+p->y*m[0][1];
75            p->y = p->x*m[1][0]+p->y*m[1][1];
76            p->x = tmp;
77        }
78        list = list->next;
79    }
80}
81
82
83static void flip(struct path *list, enum axis axis, double center)
84{
85    const struct path *path;
86    struct point *p;
87
88    for (path = list; path; path = path->next)
89        for (p = path->first; p; p = p->next) {
90            if (axis == axis_x)
91                p->x = 2*center-p->x;
92            else
93                p->y = 2*center-p->y;
94        }
95}
96
97
98
99static void flip_center(struct path *list, enum axis axis)
100{
101    double min = 0, max = 0;
102    double coord;
103    const struct path *path;
104    const struct point *p;
105    int first = 1;
106
107    for (path = list; path; path = path->next)
108        for (p = path->first; p; p = p->next) {
109            coord = axis == axis_x ? p->x : p->y;
110            if (first || coord < min)
111                min = coord;
112            if (first || coord > max)
113                max = coord;
114            first = 0;
115        }
116    flip(list, axis, (min+max)/2);
117}
118
119
120static double ref_pick_1(int ref, double a, double b)
121{
122    switch (ref) {
123    case 0:
124        return a;
125    case 1:
126        return (a+b)/2;
127    case 2:
128        return b;
129    default:
130        abort();
131    }
132}
133
134
135static void ref_pick_xy(int ref, double xa, double ya, double xb, double yb,
136    double *x, double *y)
137{
138    *x = ref_pick_1((ref-1) % 3, xa, xb);
139    *y = ref_pick_1((ref-1)/3, ya, yb);
140}
141
142
143static void bbox(const struct path *path,
144    double *xa, double *ya, double *xb, double *yb)
145{
146    const struct point *p;
147    int first = 1;
148
149    *xa = *ya = *xb = *yb = 0;
150
151    while (path) {
152        for (p = path->first; p; p = p->next) {
153            if (first || p->x < *xa)
154                *xa = p->x;
155            if (first || p->x > *xb)
156                *xb = p->x;
157            if (first || p->y < *ya)
158                *ya = p->y;
159            if (first || p->y > *yb)
160                *yb = p->y;
161            first = 0;
162        }
163        path = path->next;
164    }
165}
166
167
168static void align(int ref, double x, double y)
169{
170    double xa = 0, ya = 0, xb = 0, yb = 0;
171    double xr, yr, xd, yd;
172    int first = 1;
173
174    bbox(paths, &xa, &ya, &xb, &yb);
175
176    ref_pick_xy(ref, xa, ya, xb, yb, &xr, &yr);
177    xd = x-xr;
178    yd = y-yr;
179
180    translate(paths, xd, yd, 0);
181    xo += xd;
182    yo += yd;
183}
184
185
186static void clear_paths(void)
187{
188    struct path *next;
189
190    while (paths) {
191        next = paths->next;
192        path_free(paths);
193        paths = next;
194    }
195}
196
197
198static struct path **classify(struct path **anchor, struct path *path)
199{
200    struct path **walk, *next;
201
202    if (!path)
203        return &(*anchor)->next;
204    for (walk = &paths; *walk; walk = &(*walk)->next);
205    *walk = path;
206    next = (*anchor)->next;
207    path_free(*anchor);
208    *anchor = next;
209    return anchor;
210}
211
212
213%}
214
215
216%union {
217    double num;
218    char *str;
219    int flag;
220    enum {
221        OO_DOG = 1 << 0,
222        OO_INSIDE = 1 << 1,
223    } oopt;
224    enum axis {
225        axis_x,
226        axis_y
227    } axis;
228};
229
230
231%token TOK_ALIGN TOK_AREA TOK_ARRAY TOK_CLEAR TOK_DRILL TOK_EMPTY
232%token TOK_FLIP TOK_KEEP TOK_MILL TOK_OFFSET TOK_OPTIMIZE
233%token TOK_OUTSIDE TOK_PURGE TOK_REMAINDER
234%token TOK_REMOVE TOK_RESET
235%token TOK_REVERSE TOK_ROTATE TOK_STATS TOK_STL TOK_TRANSLATE
236%token TOK_X TOK_Y TOK_Z
237%token TOK_APPEND TOK_GERBER TOK_GNUPLOT TOK_EXCELLON TOK_WRITE
238%token TOK_WRITE_GERBER
239%token TOK_DOG TOK_INSIDE TOK_ANY
240
241%token <num> NUM_EXP_MIL NUM_EXP_MM NUM_IMP_MIL NUM_IMP_MM REF
242%token <str> STRING
243
244%type <str> opt_filename
245%type <num> dimen number opt_dimen x_size y_size
246%type <flag> opt_any
247%type <oopt> offset_options offset_option
248%type <axis> axis
249
250%%
251
252all:
253    | command all
254    ;
255
256command:
257    TOK_ALIGN REF dimen dimen
258        {
259            align((int) $2, $3, $4);
260        }
261    | TOK_ALIGN REF dimen dimen dimen dimen
262        {
263            int ref = $2;
264            double x, y;
265
266            if ($3 > $5)
267                yyerror("left edge > right edge");
268            if ($4 > $6)
269                yyerror("bottom > top");
270
271            ref_pick_xy(ref, $3, $4, $5, $6, &x, &y);
272            align(ref, x, y);
273        }
274    | TOK_ARRAY x_size y_size number number
275        {
276            double x = $2*$4;
277            double y = $3*$5;
278
279            translate(paths, x, y, 0);
280            xo += x;
281            yo += y;
282        }
283    | TOK_CLEAR
284        {
285            clear_paths();
286        }
287    | TOK_RESET
288        {
289            xo = yo = rot = 0;
290        }
291    | TOK_OFFSET offset_options
292        {
293            struct path *new;
294
295            new = tool_comp_paths(paths,
296                !!($2 & OO_DOG), !!($2 & OO_INSIDE));
297            clear_paths();
298            paths = new;
299        }
300    | TOK_OPTIMIZE
301        {
302            paths = optimize_paths(paths);
303        }
304    | TOK_OUTSIDE
305        {
306            struct path *a;
307            struct path *b;
308
309            for (a = paths; a; a = a->next) {
310                for (b = paths; b; b = b->next)
311                    if (a != b && path_is_inside(a, b))
312                        break;
313                if (!b)
314                    a->outside = 1;
315            }
316        }
317    | TOK_REVERSE
318        {
319            struct path *tmp;
320
321            tmp = reverse_paths(paths);
322            clear_paths();
323            paths = tmp;
324        }
325    | TOK_ROTATE number
326        {
327            rotate(paths, $2);
328            rot += $2;
329        }
330    | TOK_FLIP axis
331        {
332            flip_center(paths, $2);
333        }
334    | TOK_FLIP axis dimen
335        {
336            flip(paths, $2, $3);
337        }
338    | TOK_STATS
339        {
340            path_stats(paths);
341        }
342    | TOK_TRANSLATE dimen dimen
343        {
344            translate(paths, $2, $3, 0);
345            xo += $2;
346            yo += $3;
347        }
348    | TOK_Z dimen
349        {
350            zo += $2;
351        }
352    | TOK_Z dimen dimen
353        {
354            zo += $3-$2;
355        }
356    | TOK_GERBER dimen opt_filename
357        {
358            struct path *new;
359
360            new = gerber_read($3, $2/2);
361            rotate(new, rot);
362            translate(new, xo, yo, 0);
363            add_paths(new);
364        }
365    | TOK_GNUPLOT dimen opt_filename
366        {
367            struct path *new;
368
369            new = gnuplot_read($3, $2/2);
370            rotate(new, rot);
371            translate(new, xo, yo, 0);
372            add_paths(new);
373        }
374    | TOK_EXCELLON opt_filename
375        {
376            struct path *new;
377
378            new = excellon_read($2);
379            rotate(new, rot);
380            translate(new, xo, yo, 0);
381            add_paths(new);
382        }
383    | TOK_WRITE opt_filename
384        {
385            translate(paths, 0, 0, zo);
386            gnuplot_write($2, paths);
387            translate(paths, 0, 0, -zo);
388        }
389    | TOK_WRITE_GERBER opt_filename
390        {
391            gerber_write($2, paths);
392        }
393    | TOK_APPEND opt_filename
394        {
395            translate(paths, 0, 0, zo);
396            gnuplot_append($2, paths);
397            translate(paths, 0, 0, -zo);
398        }
399    | TOK_DRILL dimen opt_comma dimen
400        {
401            struct path **walk;
402
403            remain = paths;
404            paths = NULL;
405            walk = &remain;
406            while (*walk)
407                walk =
408                    classify(walk, try_drill(*walk, $2, $4));
409        }
410    | TOK_AREA dimen
411        {
412            struct path *tmp;
413
414            tmp = area(paths, $2);
415            clear_paths();
416            paths = tmp;
417        }
418    | TOK_STL opt_filename
419        {
420            stl($2, paths);
421        }
422    | TOK_MILL opt_any dimen dimen
423        {
424            struct path **walk;
425
426            remain = paths;
427            paths = NULL;
428            walk = &remain;
429            while (*walk)
430                walk = classify(walk,
431                    try_mill(*walk, $3, $4, $2));
432        }
433    | TOK_REMAINDER
434        {
435            clear_paths();
436            paths = remain;
437            remain = NULL;
438        }
439    | TOK_EMPTY
440        {
441            if (paths)
442                yyerror("path list is not empty");
443        }
444    | TOK_KEEP dimen dimen dimen dimen
445        {
446            struct path *tmp;
447
448            tmp = select_paths(paths, $2, $3, $4, $5, 1);
449            clear_paths();
450            paths = tmp;
451        }
452    | TOK_REMOVE dimen dimen dimen dimen
453        {
454            struct path *tmp;
455
456            tmp = select_paths(paths, $2, $3, $4, $5, 0);
457            clear_paths();
458            paths = tmp;
459        }
460    | TOK_PURGE opt_dimen
461        {
462            struct path *tmp;
463
464            tmp = purge_paths(paths, $2);
465            clear_paths();
466            paths = tmp;
467        }
468    ;
469
470opt_filename:
471        {
472            $$ = NULL;
473        }
474    | STRING
475        {
476            $$ = $1;
477        }
478    ;
479
480dimen:
481    NUM_EXP_MM
482        {
483            $$ = $1;
484        }
485    | NUM_IMP_MM
486        {
487            $$ = $1;
488        }
489    | NUM_EXP_MIL
490        {
491            $$ = MIL2MM($1);
492        }
493    | NUM_IMP_MIL
494        {
495            $$ = MIL2MM($1);
496        }
497    ;
498
499opt_dimen:
500        {
501            $$ = 0;
502        }
503    | dimen
504        {
505            $$ = $1;
506        }
507    ;
508
509x_size:
510    dimen
511        {
512            $$ = $1;
513        }
514    | '+' dimen
515        {
516            double xa, ya, xb, yb;
517
518            bbox(paths, &xa, &ya, &xb, &yb);
519            $$ = xb-xa+$2;
520        }
521    ;
522
523y_size:
524    dimen
525        {
526            $$ = $1;
527        }
528    | '+' dimen
529        {
530            double xa, ya, xb, yb;
531
532            bbox(paths, &xa, &ya, &xb, &yb);
533            $$ = yb-ya+$2;
534        }
535    ;
536
537number:
538    NUM_IMP_MIL
539        {
540            $$ = $1;
541        }
542    | NUM_IMP_MM
543        {
544            $$ = $1;
545        }
546    ;
547
548offset_options:
549        {
550            $$ = 0;
551        }
552    | offset_option offset_options
553        {
554            $$ = $1 | $2;
555
556        }
557    ;
558
559offset_option:
560    TOK_DOG
561        {
562            $$ = OO_DOG;
563        }
564    | TOK_INSIDE
565        {
566            $$ = OO_INSIDE;
567        }
568    ;
569
570axis:
571    TOK_X
572        {
573            $$ = axis_x;
574        }
575    | TOK_Y
576        {
577            $$ = axis_y;
578        }
579    ;
580
581opt_comma:
582    | ','
583    ;
584
585opt_any:
586        {
587            $$ = 0;
588        }
589    | TOK_ANY
590        {
591            $$ = 1;
592        }
593    ;
594

Archive Download this file

Branches:
master



interactive