1
0
mirror of git://projects.qi-hardware.com/cae-tools.git synced 2024-12-23 09:17:42 +02:00
cae-tools/cameo/lang.y
Werner Almesberger 68d5eff7cd cameo: split numbers into dimensions and "bare" numbers
- lang.l, lang.y (MIL2MM): moved unit conversion from lang.l to lang.y
- lang.l, lang.y: instead of returning dimensions and numbers as NUMBER,
  return as NUM_EXP_<unit> for numbers with an explicit unit, and as
  NUM_IMP_<unit> if the unit is implied
- lang.y (dimen): perform unit conversion as needed
- lang.y (number): never convert and only accept implicit dimensions
- lang.y: change all uses of NUMBER to "dimen", except for the
  multipliers in "array", where we can now use "number"
- lang.y: removed comment about "array" only working in metric mode
2010-12-14 19:50:53 -03:00

254 lines
3.7 KiB
Plaintext

%{
/*
* lang.y - Toolpath adaptation language
*
* Written 2010 by Werner Almesberger
* Copyright 2010 by Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdlib.h>
#include "path.h"
#include "ops.h"
#include "gnuplot.h"
#include "gerber.h"
#include "y.tab.h"
static double xo = 0, yo = 0, zo = 0;
static struct path *paths = NULL;
#define MIL2MM(mil) ((mil)/1000*25.4)
static void add_paths(struct path *new)
{
struct path **anchor = &paths;
while (*anchor)
anchor = &(*anchor)->next;
*anchor = new;
}
static void translate(double x, double y, double z)
{
struct path *path;
struct point *p;
for (path = paths; path; path = path->next)
for (p = path->first; p; p = p->next) {
p->x += x;
p->y += y;
p->z += z;
}
}
static double ref_pick_1(int ref, double a, double b)
{
switch (ref) {
case 0:
return a;
case 1:
return (a+b)/2;
case 2:
return b;
default:
abort();
}
}
static void ref_pick_xy(int ref, double xa, double ya, double xb, double yb,
double *x, double *y)
{
*x = ref_pick_1((ref-1) % 3, xa, xb);
*y = ref_pick_1((ref-1)/3, ya, yb);
}
static void align(int ref, double x, double y)
{
const struct path *path;
const struct point *p;
double xa = 0, ya = 0, xb = 0, yb = 0;
double xr, yr, xd, yd;
int first = 1;
for (path = paths; path; path = path->next)
for (p = path->first; p; p = p->next) {
if (first || p->x < xa)
xa = p->x;
if (first || p->x > xb)
xb = p->x;
if (first || p->y < ya)
ya = p->y;
if (first || p->y > yb)
yb = p->y;
first = 0;
}
ref_pick_xy(ref, xa, ya, xb, yb, &xr, &yr);
xd = x-xr;
yd = y-yr;
translate(xd, yd, 0);
xo += xd;
yo += yd;
}
%}
%union {
double num;
char *str;
};
%token TOK_ALIGN TOK_ARRAY TOK_CLEAR TOK_RESET TOK_TOOL
%token TOK_TRANSLATE TOK_Z
%token TOK_GERBER TOK_GNUPLOT TOK_WRITE
%token TOK_DOG
%token <num> NUM_EXP_MIL NUM_EXP_MM NUM_IMP_MIL NUM_IMP_MM REF
%token <str> STRING
%type <str> opt_filename
%type <num> dimen number
%%
all:
| command all
;
command:
TOK_ALIGN REF dimen dimen
{
align((int) $2, $3, $4);
}
| TOK_ALIGN REF dimen dimen dimen dimen
{
int ref = $2;
double x, y;
if ($3 > $5)
yyerror("left edge > right edge");
if ($4 > $6)
yyerror("bottom > top");
ref_pick_xy(ref, $3, $4, $5, $6, &x, &y);
align(ref, x, y);
}
| TOK_ARRAY dimen dimen number number
{
double x = $2*$4;
double y = $3*$5;
translate(x, y, 0);
}
| TOK_CLEAR
{
struct path *next;
while (paths) {
next = paths->next;
path_free(paths);
paths = next;
}
}
| TOK_RESET
{
xo = yo = 0;
}
| TOK_TOOL
{
tool_comp_paths(paths, 0);
}
| TOK_TOOL TOK_DOG
{
tool_comp_paths(paths, 1);
}
| TOK_TRANSLATE dimen dimen
{
translate($2, $3, 0);
xo += $2;
yo += $3;
}
| TOK_Z dimen
{
zo += $2;
}
| TOK_Z dimen dimen
{
zo += $3-$2;
}
| TOK_GERBER dimen opt_filename
{
add_paths(gerber_read($3, $2/2));
translate(xo, yo, 0);
}
| TOK_GNUPLOT dimen opt_filename
{
add_paths(gnuplot_read($3, $2/2));
translate(xo, yo, 0);
}
| TOK_WRITE opt_filename
{
translate(0, 0, zo);
gnuplot_write($2, paths);
translate(0, 0, -zo);
}
;
opt_filename:
{
$$ = NULL;
}
| STRING
{
$$ = $1;
}
;
dimen:
NUM_EXP_MM
{
$$ = $1;
}
| NUM_IMP_MM
{
$$ = $1;
}
| NUM_EXP_MIL
{
$$ = MIL2MM($1);
}
| NUM_IMP_MIL
{
$$ = MIL2MM($1);
}
;
number:
NUM_IMP_MIL
{
$$ = $1;
}
| NUM_IMP_MM
{
$$ = $1;
}
;