V9/jtools/src/Jpic/picy.y

%token	BOX	1
%token	ARROW	2
%token	CIRCLE	3
%token	ARC	4
%token	ELLIPSE	5
%token	LINE	6
%token	MOVE	7
%token	TEXT	8
%token	TROFF	9
%token	SPLINE	10
%token	BLOCK	11
%token	BLOCKEND 12
%token	PRINT
%token	PLACE
%token	ATTR
%token	SPREAD FILL LJUST RJUST ABOVE BELOW
%token	LEFT RIGHT UP DOWN FROM TO AT BY WITH HEAD CW CCW THEN
%token	HEIGHT WIDTH RADIUS DIAMETER LENGTH SIZE
%token	PLACENAME VARNAME DEFNAME CORNER HERE LAST NTH SAME BETWEEN AND
%token	EAST WEST NORTH SOUTH NE NW SE SW CENTER START END
%token	DOTX DOTY DOTHT DOTWID DOTRAD
%token	NUMBER
%token	DIR
%token	DOT DASH CHOP
%token	ST	/* statement terminator */

%left	'+' '-'
%left	'*' '/' '%'
%right	UMINUS

%{
#include	<stdio.h>
extern	int	hvmode, codegen;
extern	float	between, lastfloat;
%}

%%

top:
	  piclist
	| /* empty */
	| error		{ yyerror("syntax error"); }
	;

piclist:
	  picture
	| piclist picture
	;

picture:
	  prim ST			{ codegen = 1; }
	| leftbrace piclist '}'		{ rightthing($1, '}'); $$ = $2; }
	| PLACENAME ':' picture		{ makevar($1, PLACENAME, $3); $$ = $3; }
	| PLACENAME ':' ST picture	{ makevar($1, PLACENAME, $4); $$ = $4; }
	| PLACENAME ':' position ST	{ makevar($1, PLACENAME, $3); $$ = $3; }
        | VARNAME '=' expr ST		{ makevar($1, VARNAME, $3); $$ = $1; }
	| DIR				{ setdir($1); }
	| PRINT expr ST			{ printexpr($2); }
	| PRINT position ST		{ printpos($2); }
	| ST
	;

leftbrace:
	  '{'			{ leftthing('{'); }
	;

prim:
	  BOX attrlist		{ $$ = boxgen($1); }
	| CIRCLE attrlist	{ $$ = circgen($1); }
	| ELLIPSE attrlist	{ $$ = circgen($1); }
	| ARC attrlist		{ $$ = arcgen($1); }
	| LINE attrlist		{ $$ = linegen($1); }
	| ARROW attrlist	{ $$ = linegen($1); }
	| SPLINE attrlist	{ $$ = splinegen($1); }
	| MOVE attrlist		{ $$ = movegen($1); }
	| TEXT attrlist		{ $$ = textgen($1); }
	| TROFF			{ $$ = troffgen($1); }
	| lbracket piclist ']' { $$=rightthing($1,']'); } attrlist
				{ $$ = blockgen($1, $2, $4); }
	;

lbracket:
	  '['			{ $$ = leftthing('['); }
	;

attrlist:
	  attrlist attr
	| /* empty */		{ makeattr(0, 0); }
	;

attr:
	  ATTR opt_expr		{ makeattr($1, $2); }
	| DIR opt_expr		{ makeattr($1, $2); }
	| FROM position		{ makeattr($1, $2); }
	| TO position		{ makeattr($1, $2); }
	| AT position		{ makeattr($1, $2); }
	| BY position		{ makeattr($1, $2); }
	| WITH CORNER		{ makeattr(WITH, $2); }
	| WITH '.' PLACENAME	{ makeattr(PLACE, getblock(getlast(1,BLOCK), $3)); }
	| WITH position		{ makeattr(PLACE, $2); }
	| SAME			{ makeattr(SAME, $1); }
	| textattr		{ makeattr($1, 0); }
	| HEAD			{ makeattr(HEAD, $1); }
	| DOT opt_expr		{ makeattr(DOT, $2); }
	| DASH opt_expr		{ makeattr(DASH, $2); }
	| CHOP opt_expr		{ makeattr(CHOP, $2); }
	| textlist
	;

opt_expr:
	  expr
	| /* empty */		{ $$ = 0; }
	;

textlist:
	  TEXT			{ makeattr(CENTER, $1); }
	| TEXT textattr		{ makeattr($2, $1); }
	| textlist TEXT		{ makeattr(CENTER, $2); }
	| textlist TEXT textattr { makeattr($3, $2); }
	;

textattr:
	  LJUST
	| RJUST
	| SPREAD
	| FILL
	| CENTER
	| ABOVE
	| BELOW
	;

position:		/* absolute, not relative */
	| place
	| expr ',' expr			{ $$ = makepos($1, $3); }
	| position '+' expr ',' expr	{ $$ = fixpos($1, $3, $5); }
	| position '-' expr ',' expr	{ $$ = fixpos($1, -$3, -$5); }
	| '(' expr ',' expr ')'			{ $$ = makepos($2, $4); }
	| position '+' '(' expr ',' expr ')'	{ $$ = fixpos($1, $4, $6); }
	| position '-' '(' expr ',' expr ')'	{ $$ = fixpos($1, -$4, -$6); }
	| '(' place ',' place ')'	{ $$ = makepos(getcomp($2,DOTX), getcomp($4,DOTY)); }
	| expr { between=lastfloat; } '<' position ',' position '>'
					{ $$ = makebetween($1, $4, $6); }
	| expr { between=lastfloat; } BETWEEN position AND position
					{ $$ = makebetween($1, $4, $6); }
	;

place:
	  PLACENAME		{ $$ = getpos(getvar($1), 0); }
	| PLACENAME CORNER	{ $$ = getpos(getvar($1), $2); }
	| CORNER PLACENAME	{ $$ = getpos(getvar($2), $1); }
	| HERE			{ $$ = gethere($1); }
	| last type		{ $$ = getlast($1, $2); }
	| last type CORNER	{ $$ = getpos(getlast($1, $2), $3); }
	| CORNER last type	{ $$ = getpos(getlast($2, $3), $1); }
	| NTH type		{ $$ = getfirst($1, $2); }
	| NTH type CORNER	{ $$ = getpos(getfirst($1, $2), $3); }
	| CORNER NTH type	{ $$ = getpos(getfirst($2, $3), $1); }
	| blockname
	| blockname CORNER	{ $$ = getpos($1, $2); }
	| CORNER blockname	{ $$ = getpos($2, $1); }
	;

blockname:
	  last BLOCK '.' PLACENAME	{ $$ = getblock(getlast($1,$2), $4); }
	| NTH BLOCK '.' PLACENAME	{ $$ = getblock(getfirst($1,$2), $4); }
	| PLACENAME '.' PLACENAME	{ $$ = getblock(getvar($1), $3); }
	;

last:
	  last LAST		{ $$ = $1 + 1; }
	| NTH LAST		{ $$ = $1; }
	| LAST			{ $$ = 1; }
	;

type:
	  BOX
	| CIRCLE
	| ELLIPSE
	| ARC
	| LINE
	| ARROW
	| SPLINE
	| BLOCK
	;

expr:
	  expr '+' expr		{ $$ = $1 + $3; }
	| expr '-' expr		{ $$ = $1 - $3; }
	| expr '*' expr		{ $$ = $1 * $3; }
	| expr '/' expr		{ $$ = $1 / $3; }
	| expr '%' expr		{ $$ = $1 % $3; }
	| '-' expr %prec UMINUS	{ $$ = -$2; }
	| '(' expr ')'		{ $$ = $2; }
	| VARNAME		{ $$ = getvar($1); }
	| NUMBER
	| place DOTX		{ $$ = getcomp($1, $2); }
	| place DOTY		{ $$ = getcomp($1, $2); }
	| place DOTHT		{ $$ = getcomp($1, $2); }
	| place DOTWID		{ $$ = getcomp($1, $2); }
	| place DOTRAD		{ $$ = getcomp($1, $2); }
	;