xref: /plan9/sys/src/cmd/grap/grap.y (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
13e12c5d1SDavid du Colombier %{
23e12c5d1SDavid du Colombier #include <stdio.h>
33e12c5d1SDavid du Colombier #include <math.h>
43e12c5d1SDavid du Colombier #include <stdlib.h>
53e12c5d1SDavid du Colombier #include <string.h>
63e12c5d1SDavid du Colombier #include "grap.h"
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier #define	RAND_MAX 32767	/* if your rand() returns bigger, change this too */
9*7dd7cddfSDavid du Colombier 
103e12c5d1SDavid du Colombier extern int yylex(void);
11*7dd7cddfSDavid du Colombier extern int yyparse(void);
123e12c5d1SDavid du Colombier 
133e12c5d1SDavid du Colombier %}
143e12c5d1SDavid du Colombier 
153e12c5d1SDavid du Colombier %token	<i>	FRAME TICKS GRID LABEL COORD
163e12c5d1SDavid du Colombier %token	<i>	LINE ARROW CIRCLE DRAW NEW PLOT NEXT
173e12c5d1SDavid du Colombier %token	<p>	PIC
183e12c5d1SDavid du Colombier %token	<i>	COPY THRU UNTIL
193e12c5d1SDavid du Colombier %token	<i>	FOR FROM TO BY AT WITH
203e12c5d1SDavid du Colombier %token	<i>	IF
213e12c5d1SDavid du Colombier %token	<p>	GRAPH THEN ELSE DOSTR
223e12c5d1SDavid du Colombier %token	<i>	DOT DASH INVIS SOLID
233e12c5d1SDavid du Colombier %token	<i>	TEXT JUST SIZE
243e12c5d1SDavid du Colombier %token	<i>	LOG EXP SIN COS ATAN2 SQRT RAND MAX MIN INT PRINT SPRINTF
253e12c5d1SDavid du Colombier %token	<i>	X Y SIDE IN OUT OFF UP DOWN ACROSS
263e12c5d1SDavid du Colombier %token	<i>	HEIGHT WIDTH RADIUS
273e12c5d1SDavid du Colombier %token	<f>	NUMBER
283e12c5d1SDavid du Colombier %token	<op>	NAME VARNAME DEFNAME
293e12c5d1SDavid du Colombier %token	<p>	STRING
303e12c5d1SDavid du Colombier %token	<i>	ST '(' ')' ','
313e12c5d1SDavid du Colombier 
323e12c5d1SDavid du Colombier %right	<f>	'='
333e12c5d1SDavid du Colombier %left	<f>	OR
343e12c5d1SDavid du Colombier %left	<f>	AND
353e12c5d1SDavid du Colombier %nonassoc <f>	GT LT LE GE EQ NE
363e12c5d1SDavid du Colombier %left	<f>	'+' '-'
373e12c5d1SDavid du Colombier %left	<f>	'*' '/' '%'
383e12c5d1SDavid du Colombier %right	<f>	UMINUS NOT
393e12c5d1SDavid du Colombier %right	<f>	'^'
403e12c5d1SDavid du Colombier 
413e12c5d1SDavid du Colombier %type	<f>	expr optexpr if_expr number assign
423e12c5d1SDavid du Colombier %type	<i>	optop
433e12c5d1SDavid du Colombier %type	<p>	optstring if
443e12c5d1SDavid du Colombier %type	<op>	optname iterator name
453e12c5d1SDavid du Colombier %type	<pt>	point
463e12c5d1SDavid du Colombier %type	<i>	side optside numlist comma linetype drawtype
473e12c5d1SDavid du Colombier %type	<ap>	linedesc optdesc stringlist string stringattr sattrlist exprlist
483e12c5d1SDavid du Colombier %type	<i>	frameitem framelist coordlog
49*7dd7cddfSDavid du Colombier %type	<f>	string_expr
503e12c5d1SDavid du Colombier 
513e12c5d1SDavid du Colombier %%
523e12c5d1SDavid du Colombier 
533e12c5d1SDavid du Colombier top:
543e12c5d1SDavid du Colombier 	  graphseq		{ if (codegen && !synerr) graph((char *) 0); }
553e12c5d1SDavid du Colombier 	| /* empty */		{ codegen = 0; }
563e12c5d1SDavid du Colombier 	| error			{ codegen = 0; ERROR "syntax error" WARNING; }
573e12c5d1SDavid du Colombier 	;
583e12c5d1SDavid du Colombier 
593e12c5d1SDavid du Colombier graphseq:
603e12c5d1SDavid du Colombier 	  statlist
613e12c5d1SDavid du Colombier 	| graph statlist
623e12c5d1SDavid du Colombier 	| graphseq graph statlist
633e12c5d1SDavid du Colombier 	;
643e12c5d1SDavid du Colombier graph:
653e12c5d1SDavid du Colombier 	  GRAPH			{ graph($1); endstat(); }
663e12c5d1SDavid du Colombier 	;
673e12c5d1SDavid du Colombier 
683e12c5d1SDavid du Colombier statlist:
693e12c5d1SDavid du Colombier 	  ST
703e12c5d1SDavid du Colombier 	| stat ST		{ endstat(); }
713e12c5d1SDavid du Colombier 	| statlist stat ST	{ endstat(); }
723e12c5d1SDavid du Colombier 	;
733e12c5d1SDavid du Colombier 
743e12c5d1SDavid du Colombier stat:
753e12c5d1SDavid du Colombier 	  FRAME framelist	{ codegen = 1; }
763e12c5d1SDavid du Colombier 	| ticks			{ codegen = 1; }
773e12c5d1SDavid du Colombier 	| grid			{ codegen = 1; }
783e12c5d1SDavid du Colombier 	| label			{ codegen = 1; }
793e12c5d1SDavid du Colombier 	| coord
803e12c5d1SDavid du Colombier 	| plot			{ codegen = 1; }
813e12c5d1SDavid du Colombier 	| line			{ codegen = 1; }
823e12c5d1SDavid du Colombier 	| circle		{ codegen = 1; }
833e12c5d1SDavid du Colombier 	| draw
843e12c5d1SDavid du Colombier 	| next			{ codegen = 1; }
853e12c5d1SDavid du Colombier 	| PIC			{ codegen = 1; pic($1); }
863e12c5d1SDavid du Colombier 	| for
873e12c5d1SDavid du Colombier 	| if
883e12c5d1SDavid du Colombier 	| copy
893e12c5d1SDavid du Colombier 	| numlist		{ codegen = 1; numlist(); }
903e12c5d1SDavid du Colombier 	| assign
913e12c5d1SDavid du Colombier 	| PRINT expr		{ fprintf(stderr, "\t%g\n", $2); }
923e12c5d1SDavid du Colombier 	| PRINT string		{ fprintf(stderr, "\t%s\n", $2->sval); freeattr($2); }
933e12c5d1SDavid du Colombier 	| /* empty */
943e12c5d1SDavid du Colombier 	;
953e12c5d1SDavid du Colombier 
963e12c5d1SDavid du Colombier numlist:
973e12c5d1SDavid du Colombier 	  number		{ savenum(0, $1); $$ = 1; }
983e12c5d1SDavid du Colombier 	| numlist number	{ savenum($1, $2); $$ = $1+1; }
993e12c5d1SDavid du Colombier 	| numlist comma number	{ savenum($1, $3); $$ = $1+1; }
1003e12c5d1SDavid du Colombier 	;
1013e12c5d1SDavid du Colombier number:
1023e12c5d1SDavid du Colombier 	  NUMBER
1033e12c5d1SDavid du Colombier 	| '-' NUMBER %prec UMINUS	{ $$ = -$2; }
1043e12c5d1SDavid du Colombier 	| '+' NUMBER %prec UMINUS	{ $$ = $2; }
1053e12c5d1SDavid du Colombier 	;
1063e12c5d1SDavid du Colombier 
1073e12c5d1SDavid du Colombier label:
1083e12c5d1SDavid du Colombier 	  LABEL optside stringlist lablist	{ label($2, $3); }
1093e12c5d1SDavid du Colombier 	;
1103e12c5d1SDavid du Colombier lablist:
1113e12c5d1SDavid du Colombier 	  labattr
1123e12c5d1SDavid du Colombier 	| lablist labattr
1133e12c5d1SDavid du Colombier 	| /* empty */
1143e12c5d1SDavid du Colombier 	;
1153e12c5d1SDavid du Colombier labattr:
1163e12c5d1SDavid du Colombier 	  UP expr		{ labelmove($1, $2); }
1173e12c5d1SDavid du Colombier 	| DOWN expr		{ labelmove($1, $2); }
1183e12c5d1SDavid du Colombier 	| SIDE expr		{ labelmove($1, $2); /* LEFT or RIGHT only */ }
1193e12c5d1SDavid du Colombier 	| WIDTH expr		{ labelwid($2); }
1203e12c5d1SDavid du Colombier 	;
1213e12c5d1SDavid du Colombier 
1223e12c5d1SDavid du Colombier framelist:
1233e12c5d1SDavid du Colombier 	  framelist frameitem
1243e12c5d1SDavid du Colombier 	| /* empty */		{ $$ = 0; }
1253e12c5d1SDavid du Colombier 	;
1263e12c5d1SDavid du Colombier frameitem:
1273e12c5d1SDavid du Colombier 	  HEIGHT expr		{ frameht($2); }
1283e12c5d1SDavid du Colombier 	| WIDTH expr		{ framewid($2); }
1293e12c5d1SDavid du Colombier 	| side linedesc		{ frameside($1, $2); }
1303e12c5d1SDavid du Colombier 	| linedesc		{ frameside(0, $1); }
1313e12c5d1SDavid du Colombier 	;
1323e12c5d1SDavid du Colombier side:
1333e12c5d1SDavid du Colombier 	  SIDE
1343e12c5d1SDavid du Colombier 	;
1353e12c5d1SDavid du Colombier optside:
1363e12c5d1SDavid du Colombier 	  side
1373e12c5d1SDavid du Colombier 	| /* empty */		{ $$ = 0; }
1383e12c5d1SDavid du Colombier 	;
1393e12c5d1SDavid du Colombier 
1403e12c5d1SDavid du Colombier linedesc:
1413e12c5d1SDavid du Colombier 	  linetype optexpr	{ $$ = makeattr($1, $2, (char *) 0, 0, 0); }
1423e12c5d1SDavid du Colombier 	;
1433e12c5d1SDavid du Colombier linetype:
1443e12c5d1SDavid du Colombier 	  DOT | DASH | SOLID | INVIS
1453e12c5d1SDavid du Colombier 	;
1463e12c5d1SDavid du Colombier optdesc:
1473e12c5d1SDavid du Colombier 	  linedesc
1483e12c5d1SDavid du Colombier 	| /* empty */		{ $$ = makeattr(0, 0.0, (char *) 0, 0, 0); }
1493e12c5d1SDavid du Colombier 	;
1503e12c5d1SDavid du Colombier 
1513e12c5d1SDavid du Colombier ticks:
1523e12c5d1SDavid du Colombier 	  TICKS tickdesc	{ ticks(); }
1533e12c5d1SDavid du Colombier 	;
1543e12c5d1SDavid du Colombier tickdesc:
1553e12c5d1SDavid du Colombier 	  tickattr
1563e12c5d1SDavid du Colombier 	| tickdesc tickattr
1573e12c5d1SDavid du Colombier 	;
1583e12c5d1SDavid du Colombier tickattr:
1593e12c5d1SDavid du Colombier 	  side			{ tickside($1); }
1603e12c5d1SDavid du Colombier 	| IN expr		{ tickdir(IN, $2, 1); }
1613e12c5d1SDavid du Colombier 	| OUT expr		{ tickdir(OUT, $2, 1); }
1623e12c5d1SDavid du Colombier 	| IN			{ tickdir(IN, 0.0, 0); }
1633e12c5d1SDavid du Colombier 	| OUT			{ tickdir(OUT, 0.0, 0); }
1643e12c5d1SDavid du Colombier 	| AT optname ticklist	{ setlist(); ticklist($2, AT); }
1653e12c5d1SDavid du Colombier 	| iterator		{ setlist(); ticklist($1, AT); }
1663e12c5d1SDavid du Colombier 	| side OFF		{ tickoff($1); }
1673e12c5d1SDavid du Colombier 	| OFF			{ tickoff(LEFT|RIGHT|TOP|BOT); }
1683e12c5d1SDavid du Colombier 	| labattr
1693e12c5d1SDavid du Colombier 	;
1703e12c5d1SDavid du Colombier ticklist:
1713e12c5d1SDavid du Colombier 	  tickpoint
1723e12c5d1SDavid du Colombier 	| ticklist comma tickpoint
1733e12c5d1SDavid du Colombier 	;
1743e12c5d1SDavid du Colombier tickpoint:
1753e12c5d1SDavid du Colombier 	  expr			{ savetick($1, (char *) 0); }
176*7dd7cddfSDavid du Colombier 	| expr string		{ savetick($1, $2->sval); }
1773e12c5d1SDavid du Colombier 	;
1783e12c5d1SDavid du Colombier iterator:
1793e12c5d1SDavid du Colombier 	  FROM optname expr TO optname expr BY optop expr optstring
1803e12c5d1SDavid du Colombier 			{ iterator($3, $6, $8, $9, $10); $$ = $2; }
1813e12c5d1SDavid du Colombier 	| FROM optname expr TO optname expr optstring
1823e12c5d1SDavid du Colombier 			{ iterator($3, $6, '+', 1.0, $7); $$ = $2; }
1833e12c5d1SDavid du Colombier 	;
1843e12c5d1SDavid du Colombier optop:
1853e12c5d1SDavid du Colombier 	  '+'		{ $$ = '+'; }
1863e12c5d1SDavid du Colombier 	| '-'		{ $$ = '-'; }
1873e12c5d1SDavid du Colombier 	| '*'		{ $$ = '*'; }
1883e12c5d1SDavid du Colombier 	| '/'		{ $$ = '/'; }
1893e12c5d1SDavid du Colombier 	| /* empty */	{ $$ = ' '; }
1903e12c5d1SDavid du Colombier 	;
1913e12c5d1SDavid du Colombier optstring:
192*7dd7cddfSDavid du Colombier 	  string	{ $$ = $1->sval; }
1933e12c5d1SDavid du Colombier 	| /* empty */	{ $$ = (char *) 0; }
1943e12c5d1SDavid du Colombier 	;
1953e12c5d1SDavid du Colombier 
1963e12c5d1SDavid du Colombier grid:
1973e12c5d1SDavid du Colombier 	  GRID griddesc		{ ticks(); }
1983e12c5d1SDavid du Colombier 	;
1993e12c5d1SDavid du Colombier griddesc:
2003e12c5d1SDavid du Colombier 	  gridattr
2013e12c5d1SDavid du Colombier 	| griddesc gridattr
2023e12c5d1SDavid du Colombier 	;
2033e12c5d1SDavid du Colombier gridattr:
2043e12c5d1SDavid du Colombier 	  side			{ tickside($1); }
2053e12c5d1SDavid du Colombier 	| X			{ tickside(BOT); }
2063e12c5d1SDavid du Colombier 	| Y			{ tickside(LEFT); }
2073e12c5d1SDavid du Colombier 	| linedesc		{ griddesc($1); }
2083e12c5d1SDavid du Colombier 	| AT optname ticklist	{ setlist(); gridlist($2); }
2093e12c5d1SDavid du Colombier 	| iterator		{ setlist(); gridlist($1); }
2103e12c5d1SDavid du Colombier 	| TICKS OFF		{ gridtickoff(); }
2113e12c5d1SDavid du Colombier 	| OFF			{ gridtickoff(); }
2123e12c5d1SDavid du Colombier 	| labattr
2133e12c5d1SDavid du Colombier 	;
2143e12c5d1SDavid du Colombier 
2153e12c5d1SDavid du Colombier line:
2163e12c5d1SDavid du Colombier 	  LINE FROM point TO point optdesc	{ line($1, $3, $5, $6); }
2173e12c5d1SDavid du Colombier 	| LINE optdesc FROM point TO point	{ line($1, $4, $6, $2); }
2183e12c5d1SDavid du Colombier 	;
2193e12c5d1SDavid du Colombier circle:
2203e12c5d1SDavid du Colombier 	  CIRCLE RADIUS expr AT point		{ circle($3, $5); }
2213e12c5d1SDavid du Colombier 	| CIRCLE AT point RADIUS expr		{ circle($5, $3); }
2223e12c5d1SDavid du Colombier 	| CIRCLE AT point			{ circle(0.0, $3); }
2233e12c5d1SDavid du Colombier 	;
2243e12c5d1SDavid du Colombier 
2253e12c5d1SDavid du Colombier stringlist:
2263e12c5d1SDavid du Colombier 	  string
2273e12c5d1SDavid du Colombier 	| stringlist string	{ $$ = addattr($1, $2); }
2283e12c5d1SDavid du Colombier 	;
2293e12c5d1SDavid du Colombier string:
2303e12c5d1SDavid du Colombier 	  STRING sattrlist	{ $$ = makesattr($1); }
2313e12c5d1SDavid du Colombier 	| SPRINTF '(' STRING ')' sattrlist
2323e12c5d1SDavid du Colombier 				{ $$ = makesattr(sprntf($3, (Attr*) 0)); }
2333e12c5d1SDavid du Colombier 	| SPRINTF '(' STRING ',' exprlist ')' sattrlist
2343e12c5d1SDavid du Colombier 				{ $$ = makesattr(sprntf($3, $5)); }
2353e12c5d1SDavid du Colombier 	;
2363e12c5d1SDavid du Colombier exprlist:
2373e12c5d1SDavid du Colombier 	  expr			{ $$ = makefattr(NUMBER, $1); }
2383e12c5d1SDavid du Colombier 	| exprlist ',' expr	{ $$ = addattr($1, makefattr(NUMBER, $3)); }
2393e12c5d1SDavid du Colombier 	;
2403e12c5d1SDavid du Colombier sattrlist:
2413e12c5d1SDavid du Colombier 	  stringattr
2423e12c5d1SDavid du Colombier 	| sattrlist stringattr
2433e12c5d1SDavid du Colombier 	| /* empty */		{ $$ = (Attr *) 0; }
2443e12c5d1SDavid du Colombier 	;
2453e12c5d1SDavid du Colombier stringattr:
2463e12c5d1SDavid du Colombier 	  JUST			{ setjust($1); }
2473e12c5d1SDavid du Colombier 	| SIZE optop expr	{ setsize($2, $3); }
2483e12c5d1SDavid du Colombier 	;
2493e12c5d1SDavid du Colombier 
2503e12c5d1SDavid du Colombier coord:
2513e12c5d1SDavid du Colombier 	  COORD optname coordlist	{ coord($2); }
2523e12c5d1SDavid du Colombier 	| COORD optname			{ resetcoord($2); }
2533e12c5d1SDavid du Colombier 	;
2543e12c5d1SDavid du Colombier coordlist:
2553e12c5d1SDavid du Colombier 	  coorditem
2563e12c5d1SDavid du Colombier 	| coordlist coorditem
2573e12c5d1SDavid du Colombier 	;
2583e12c5d1SDavid du Colombier coorditem:
2593e12c5d1SDavid du Colombier 	  coordlog	{ coordlog($1); }
2603e12c5d1SDavid du Colombier 	| X point	{ coord_x($2); }
2613e12c5d1SDavid du Colombier 	| Y point	{ coord_y($2); }
2623e12c5d1SDavid du Colombier 	| X optname expr TO expr		{ coord_x(makepoint($2, $3, $5)); }
2633e12c5d1SDavid du Colombier 	| Y optname expr TO expr		{ coord_y(makepoint($2, $3, $5)); }
2643e12c5d1SDavid du Colombier 	| X FROM optname expr TO expr		{ coord_x(makepoint($3, $4, $6)); }
2653e12c5d1SDavid du Colombier 	| Y FROM optname expr TO expr		{ coord_y(makepoint($3, $4, $6)); }
2663e12c5d1SDavid du Colombier 	;
2673e12c5d1SDavid du Colombier coordlog:
2683e12c5d1SDavid du Colombier 	  LOG X		{ $$ = XFLAG; }
2693e12c5d1SDavid du Colombier 	| LOG Y		{ $$ = YFLAG; }
2703e12c5d1SDavid du Colombier 	| LOG X LOG Y	{ $$ = XFLAG|YFLAG; }
2713e12c5d1SDavid du Colombier 	| LOG Y LOG X	{ $$ = XFLAG|YFLAG; }
2723e12c5d1SDavid du Colombier 	| LOG LOG	{ $$ = XFLAG|YFLAG; }
2733e12c5d1SDavid du Colombier 	;
2743e12c5d1SDavid du Colombier 
2753e12c5d1SDavid du Colombier plot:
2763e12c5d1SDavid du Colombier 	  stringlist AT point		{ plot($1, $3); }
2773e12c5d1SDavid du Colombier 	| PLOT stringlist AT point	{ plot($2, $4); }
2783e12c5d1SDavid du Colombier 	| PLOT expr optstring AT point	{ plotnum($2, $3, $5); }
2793e12c5d1SDavid du Colombier 	;
2803e12c5d1SDavid du Colombier 
2813e12c5d1SDavid du Colombier draw:
2823e12c5d1SDavid du Colombier 	  drawtype optname linedesc		{ drawdesc($1, $2, $3, (char *) 0); }
283*7dd7cddfSDavid du Colombier 	| drawtype optname optdesc string	{ drawdesc($1, $2, $3, $4->sval); }
284*7dd7cddfSDavid du Colombier 	| drawtype optname string optdesc	{ drawdesc($1, $2, $4, $3->sval); }
2853e12c5d1SDavid du Colombier 	;
2863e12c5d1SDavid du Colombier drawtype:
2873e12c5d1SDavid du Colombier 	  DRAW
2883e12c5d1SDavid du Colombier 	| NEW
2893e12c5d1SDavid du Colombier 	;
2903e12c5d1SDavid du Colombier 
2913e12c5d1SDavid du Colombier next:
2923e12c5d1SDavid du Colombier 	  NEXT optname AT point optdesc		{ next($2, $4, $5); }
2933e12c5d1SDavid du Colombier 
2943e12c5d1SDavid du Colombier copy:
2953e12c5d1SDavid du Colombier 	  COPY copylist		{ copy(); }
2963e12c5d1SDavid du Colombier 	;
2973e12c5d1SDavid du Colombier copylist:
2983e12c5d1SDavid du Colombier 	  copyattr
2993e12c5d1SDavid du Colombier 	| copylist copyattr
3003e12c5d1SDavid du Colombier 	;
3013e12c5d1SDavid du Colombier copyattr:
302*7dd7cddfSDavid du Colombier 	  string		{ copyfile($1->sval); }
3033e12c5d1SDavid du Colombier 	| THRU DEFNAME		{ copydef($2); }
304*7dd7cddfSDavid du Colombier 	| UNTIL string		{ copyuntil($2->sval); }
3053e12c5d1SDavid du Colombier 	;
3063e12c5d1SDavid du Colombier 
3073e12c5d1SDavid du Colombier for:
3083e12c5d1SDavid du Colombier 	  FOR name FROM expr TO expr BY optop expr DOSTR
3093e12c5d1SDavid du Colombier 		{ forloop($2, $4, $6, $8, $9, $10); }
3103e12c5d1SDavid du Colombier 	| FOR name FROM expr TO expr DOSTR
3113e12c5d1SDavid du Colombier 		{ forloop($2, $4, $6, '+', 1.0, $7); }
3123e12c5d1SDavid du Colombier 	| FOR name '=' expr TO expr BY optop expr DOSTR
3133e12c5d1SDavid du Colombier 		{ forloop($2, $4, $6, $8, $9, $10); }
3143e12c5d1SDavid du Colombier 	| FOR name '=' expr TO expr DOSTR
3153e12c5d1SDavid du Colombier 		{ forloop($2, $4, $6, '+', 1.0, $7); }
3163e12c5d1SDavid du Colombier 	;
3173e12c5d1SDavid du Colombier 
3183e12c5d1SDavid du Colombier if:
3193e12c5d1SDavid du Colombier 	  IF if_expr THEN ELSE		{ $$ = ifstat($2, $3, $4); }
3203e12c5d1SDavid du Colombier 	| IF if_expr THEN		{ $$ = ifstat($2, $3, (char *) 0); }
3213e12c5d1SDavid du Colombier 	;
3223e12c5d1SDavid du Colombier if_expr:
3233e12c5d1SDavid du Colombier 	  expr
324*7dd7cddfSDavid du Colombier 	| string_expr
325*7dd7cddfSDavid du Colombier 	| if_expr AND string_expr	{ $$ = $1 && $3; }
326*7dd7cddfSDavid du Colombier 	| if_expr OR string_expr	{ $$ = $1 || $3; }
327*7dd7cddfSDavid du Colombier 	;
328*7dd7cddfSDavid du Colombier string_expr:
329*7dd7cddfSDavid du Colombier 	  STRING EQ STRING	{ $$ = strcmp($1,$3) == 0; free($1); free($3); }
3303e12c5d1SDavid du Colombier 	| STRING NE STRING	{ $$ = strcmp($1,$3) != 0; free($1); free($3); }
3313e12c5d1SDavid du Colombier 	;
3323e12c5d1SDavid du Colombier 
3333e12c5d1SDavid du Colombier point:
3343e12c5d1SDavid du Colombier 	  optname expr comma expr		{ $$ = makepoint($1, $2, $4); }
3353e12c5d1SDavid du Colombier 	| optname '(' expr comma expr ')'	{ $$ = makepoint($1, $3, $5); }
3363e12c5d1SDavid du Colombier 	;
3373e12c5d1SDavid du Colombier comma:
3383e12c5d1SDavid du Colombier 	  ','		{ $$ = ','; }
3393e12c5d1SDavid du Colombier 	;
3403e12c5d1SDavid du Colombier 
3413e12c5d1SDavid du Colombier optname:
3423e12c5d1SDavid du Colombier 	  NAME		{ $$ = $1; }
3433e12c5d1SDavid du Colombier 	| /* empty */	{ $$ = lookup(curr_coord, 1); }
3443e12c5d1SDavid du Colombier 	;
3453e12c5d1SDavid du Colombier 
3463e12c5d1SDavid du Colombier expr:
3473e12c5d1SDavid du Colombier 	  NUMBER
3483e12c5d1SDavid du Colombier 	| assign
349*7dd7cddfSDavid du Colombier 	| '(' string_expr ')'	{ $$ = $2; }
3503e12c5d1SDavid du Colombier 	| VARNAME		{ $$ = getvar($1); }
3513e12c5d1SDavid du Colombier 	| expr '+' expr		{ $$ = $1 + $3; }
3523e12c5d1SDavid du Colombier 	| expr '-' expr		{ $$ = $1 - $3; }
3533e12c5d1SDavid du Colombier 	| expr '*' expr		{ $$ = $1 * $3; }
3543e12c5d1SDavid du Colombier 	| expr '/' expr		{ if ($3 == 0.0) {
3553e12c5d1SDavid du Colombier 					ERROR "division by 0" WARNING; $3 = 1; }
3563e12c5d1SDavid du Colombier 				  $$ = $1 / $3; }
3573e12c5d1SDavid du Colombier 	| expr '%' expr		{ if ((long)$3 == 0) {
3583e12c5d1SDavid du Colombier 					ERROR "mod division by 0" WARNING; $3 = 1; }
3593e12c5d1SDavid du Colombier 				  $$ = (long)$1 % (long)$3; }
3603e12c5d1SDavid du Colombier 	| '-' expr %prec UMINUS	{ $$ = -$2; }
3613e12c5d1SDavid du Colombier 	| '+' expr %prec UMINUS	{ $$ = $2; }
3623e12c5d1SDavid du Colombier 	| '(' expr ')'		{ $$ = $2; }
3633e12c5d1SDavid du Colombier 	| LOG '(' expr ')'		{ $$ = Log10($3); }
3643e12c5d1SDavid du Colombier 	| EXP '(' expr ')'		{ $$ = Exp($3 * log(10.0)); }
3653e12c5d1SDavid du Colombier 	| expr '^' expr			{ $$ = pow($1, $3); }
3663e12c5d1SDavid du Colombier 	| SIN '(' expr ')'		{ $$ = sin($3); }
3673e12c5d1SDavid du Colombier 	| COS '(' expr ')'		{ $$ = cos($3); }
3683e12c5d1SDavid du Colombier 	| ATAN2 '(' expr ',' expr ')'	{ $$ = atan2($3, $5); }
3693e12c5d1SDavid du Colombier 	| SQRT '(' expr ')'		{ $$ = Sqrt($3); }
3703e12c5d1SDavid du Colombier 	| RAND '(' ')'			{ $$ = (double)rand() / (double)RAND_MAX; }
3713e12c5d1SDavid du Colombier 	| MAX '(' expr ',' expr ')'	{ $$ = $3 >= $5 ? $3 : $5; }
3723e12c5d1SDavid du Colombier 	| MIN '(' expr ',' expr ')'	{ $$ = $3 <= $5 ? $3 : $5; }
3733e12c5d1SDavid du Colombier 	| INT '(' expr ')'	{ $$ = (long) $3; }
3743e12c5d1SDavid du Colombier 	| expr GT expr		{ $$ = $1 > $3; }
3753e12c5d1SDavid du Colombier 	| expr LT expr		{ $$ = $1 < $3; }
3763e12c5d1SDavid du Colombier 	| expr LE expr		{ $$ = $1 <= $3; }
3773e12c5d1SDavid du Colombier 	| expr GE expr		{ $$ = $1 >= $3; }
3783e12c5d1SDavid du Colombier 	| expr EQ expr		{ $$ = $1 == $3; }
3793e12c5d1SDavid du Colombier 	| expr NE expr		{ $$ = $1 != $3; }
3803e12c5d1SDavid du Colombier 	| expr AND expr		{ $$ = $1 && $3; }
3813e12c5d1SDavid du Colombier 	| expr OR expr		{ $$ = $1 || $3; }
3823e12c5d1SDavid du Colombier 	| NOT expr		{ $$ = !($2); }
3833e12c5d1SDavid du Colombier 	;
3843e12c5d1SDavid du Colombier assign:
3853e12c5d1SDavid du Colombier 	  name '=' expr		{ $$ = setvar($1, $3); }
3863e12c5d1SDavid du Colombier 	;
3873e12c5d1SDavid du Colombier 
3883e12c5d1SDavid du Colombier name:
3893e12c5d1SDavid du Colombier 	  NAME
3903e12c5d1SDavid du Colombier 	| VARNAME
3913e12c5d1SDavid du Colombier 	;
3923e12c5d1SDavid du Colombier 
3933e12c5d1SDavid du Colombier optexpr:
3943e12c5d1SDavid du Colombier 	  expr
3953e12c5d1SDavid du Colombier 	| /* empty */		{ $$ = 0.0; }
3963e12c5d1SDavid du Colombier 	;
397