diff options
author | rsc <devnull@localhost> | 2006-04-14 00:04:03 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2006-04-14 00:04:03 +0000 |
commit | b6d98463b416e9d95bc88f948b4abdff6b24aede (patch) | |
tree | 6ae4dabb948c5b3c42a48b34964bdde7b0afa5c2 /src/cmd/tpic/picy.y | |
parent | 434d1b41b61a9771f4cec2ca6c0a00b067a50fa0 (diff) | |
download | plan9port-b6d98463b416e9d95bc88f948b4abdff6b24aede.tar.gz plan9port-b6d98463b416e9d95bc88f948b4abdff6b24aede.tar.bz2 plan9port-b6d98463b416e9d95bc88f948b4abdff6b24aede.zip |
tpic
Diffstat (limited to 'src/cmd/tpic/picy.y')
-rw-r--r-- | src/cmd/tpic/picy.y | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/src/cmd/tpic/picy.y b/src/cmd/tpic/picy.y new file mode 100644 index 00000000..46b2b4da --- /dev/null +++ b/src/cmd/tpic/picy.y @@ -0,0 +1,320 @@ +%{ +#include <stdio.h> +#include "pic.h" +#include <math.h> +YYSTYPE y; +int yylex(void); +%} + +%token <i> BOX 1 /* DON'T CHANGE THESE! */ +%token <i> LINE 2 +%token <i> ARROW 3 +%token <i> CIRCLE 4 +%token <i> ELLIPSE 5 +%token <i> ARC 6 +%token <i> SPLINE 7 +%token <i> BLOCK 8 +%token <p> TEXT 9 +%token <p> TROFF 10 +%token <i> MOVE 11 +%token <i> BLOCKEND 12 +%token <i> PLACE 13 +%token <i> PRINT RESET THRU UNTIL +%token <o> FOR IF COPY +%token <p> THENSTR ELSESTR DOSTR PLACENAME VARNAME SPRINTF +%token <st> DEFNAME +%token <i> ATTR TEXTATTR +%token <i> LEFT RIGHT UP DOWN FROM TO AT BY WITH HEAD CW CCW THEN +%token <i> HEIGHT WIDTH RADIUS DIAMETER LENGTH SIZE +%token <i> CORNER HERE LAST NTH SAME BETWEEN AND +%token <i> EAST WEST NORTH SOUTH NE NW SE SW START END +%token <i> DOTX DOTY DOTHT DOTWID DOTRAD +%token <f> NUMBER +%token <f> LOG EXP SIN COS ATAN2 SQRT RAND MIN MAX INT +%token <i> DIR +%token <i> DOT DASH CHOP FILL +%token <o> ST /* statement terminator */ + +%right <f> '=' +%left <f> OROR +%left <f> ANDAND +%nonassoc <f> GT LT LE GE EQ NEQ +%left <f> '+' '-' +%left <f> '*' '/' '%' +%right <f> UMINUS NOT +%right <f> '^' + +%type <f> expr if_expr asgn +%type <p> name text +%type <i> optop exprlist +%type <o> if for copy + +/* this is a lie: picture and position are really the whole union */ +%type <o> leftbrace picture piclist position lbracket +%type <o> prim place blockname +%type <i> textlist textattr /* not a sensible value */ +%type <i> last type + +%% + +top: + piclist + | /* empty */ + | error { ERROR "syntax error" WARNING; } + ; + +piclist: + picture + | piclist picture + ; + +picture: + prim ST { codegen = 1; makeiattr(0, 0); } + | leftbrace piclist '}' { rightthing($1, '}'); $$ = $2; } + | PLACENAME ':' picture { y.o=$3; makevar($1,PLACENAME,y); $$ = $3; } + | PLACENAME ':' ST picture { y.o=$4; makevar($1,PLACENAME,y); $$ = $4; } + | PLACENAME ':' position ST { y.o=$3; makevar($1,PLACENAME,y); $$ = $3; } + | asgn ST { y.f = $1; $$ = y.o; $$ = makenode(PLACE, 0); } + | DIR { setdir($1); $$ = makenode(PLACE, 0); } + | PRINT expr ST { printexpr($2); $$ = makenode(PLACE, 0); } + | PRINT position ST { printpos($2); $$ = makenode(PLACE, 0); } + | PRINT text ST { printf("%s\n", $2); free($2); $$ = makenode(PLACE, 0); } + | RESET varlist ST { resetvar(); makeiattr(0, 0); $$ = makenode(PLACE, 0); } + | copy + | for + | if + | ST + ; + +varlist: + /* empty */ + | VARNAME { makevattr($1); } + | varlist VARNAME { makevattr($2); } + | varlist ',' VARNAME { makevattr($3); } + ; + +asgn: + VARNAME '=' expr { $$=y.f=$3; makevar($1,VARNAME,y); checkscale($1); } + ; + +copy: + COPY copylist { copy(); } + ; +copylist: + copyattr + | copylist copyattr + ; +copyattr: + text { copyfile($1); } + | THRU DEFNAME { copydef($2); } + | UNTIL text { copyuntil($2); } + ; + +for: + FOR name FROM expr TO expr BY optop expr DOSTR + { forloop($2, $4, $6, $8, $9, $10); } + | FOR name FROM expr TO expr DOSTR + { forloop($2, $4, $6, '+', 1.0, $7); } + | FOR name '=' expr TO expr BY optop expr DOSTR + { forloop($2, $4, $6, $8, $9, $10); } + | FOR name '=' expr TO expr DOSTR + { forloop($2, $4, $6, '+', 1.0, $7); } + ; + +if: + IF if_expr THENSTR ELSESTR { ifstat($2, $3, $4); } + | IF if_expr THENSTR { ifstat($2, $3, (char *) 0); } + ; +if_expr: + expr + | text EQ text { $$ = strcmp($1,$3) == 0; free($1); free($3); } + | text NEQ text { $$ = strcmp($1,$3) != 0; free($1); free($3); } + ; + +name: + VARNAME { y.f = 0; makevar($1, VARNAME, y); } + ; +optop: + '+' { $$ = '+'; } + | '-' { $$ = '-'; } + | '*' { $$ = '*'; } + | '/' { $$ = '/'; } + | /* empty */ { $$ = ' '; } + ; + + +leftbrace: + '{' { $$ = leftthing('{'); } + ; + +prim: + BOX attrlist { $$ = boxgen(); } + | CIRCLE attrlist { $$ = circgen($1); } + | ELLIPSE attrlist { $$ = circgen($1); } + | ARC attrlist { $$ = arcgen($1); } + | LINE attrlist { $$ = linegen($1); } + | ARROW attrlist { $$ = linegen($1); } + | SPLINE attrlist { $$ = linegen($1); } + | MOVE attrlist { $$ = movegen(); } + | textlist attrlist { $$ = textgen(); } + | TROFF { $$ = troffgen($1); } + | lbracket piclist ']' { $<o>$=rightthing($1,']'); } attrlist + { $$ = blockgen($1, $<o>4); } + ; + +lbracket: + '[' { $$ = leftthing('['); } + ; + +attrlist: + attrlist attr + | /* empty */ + ; + +attr: + ATTR expr { makefattr($1, !DEFAULT, $2); } + | ATTR { makefattr($1, DEFAULT, 0.0); } + | expr { makefattr(curdir(), !DEFAULT, $1); } + | DIR expr { makefattr($1, !DEFAULT, $2); } + | DIR { makefattr($1, DEFAULT, 0.0); } + | FROM position { makeoattr($1, $2); } + | TO position { makeoattr($1, $2); } + | AT position { makeoattr($1, $2); } + | BY position { makeoattr($1, $2); } + | WITH CORNER { makeiattr(WITH, $2); } + | WITH '.' PLACENAME { makeoattr(PLACE, getblock(getlast(1,BLOCK), $3)); } + | WITH '.' PLACENAME CORNER + { makeoattr(PLACE, getpos(getblock(getlast(1,BLOCK), $3), $4)); } + | WITH position { makeoattr(PLACE, $2); } + | SAME { makeiattr(SAME, $1); } + | TEXTATTR { maketattr($1, (char *) 0); } + | HEAD { makeiattr(HEAD, $1); } + | DOT expr { makefattr(DOT, !DEFAULT, $2); } + | DOT { makefattr(DOT, DEFAULT, 0.0); } + | DASH expr { makefattr(DASH, !DEFAULT, $2); } + | DASH { makefattr(DASH, DEFAULT, 0.0); } + | CHOP expr { makefattr(CHOP, !DEFAULT, $2); } + | CHOP { makefattr(CHOP, DEFAULT, 0.0); } + | FILL expr { makefattr(FILL, !DEFAULT, $2); } + | FILL { makefattr(FILL, DEFAULT, 0.0); } + | textlist + ; + +textlist: + textattr + | textlist textattr + ; +textattr: + text { maketattr(CENTER, $1); } + | text TEXTATTR { maketattr($2, $1); } + | textattr TEXTATTR { addtattr($2); } + ; +text: + TEXT + | SPRINTF '(' text ')' { $$ = sprintgen($3); } + | SPRINTF '(' text ',' exprlist ')' { $$ = sprintgen($3); } + ; + +exprlist: + expr { exprsave($1); $$ = 0; } + | exprlist ',' expr { exprsave($3); } + ; + +position: /* absolute, not relative */ + place + | '(' position ')' { $$ = $2; } + | expr ',' expr { $$ = makepos($1, $3); } + | position '+' expr ',' expr { $$ = fixpos($1, $3, $5); } + | position '-' expr ',' expr { $$ = fixpos($1, -$3, -$5); } + | position '+' '(' expr ',' expr ')' { $$ = fixpos($1, $4, $6); } + | position '-' '(' expr ',' expr ')' { $$ = fixpos($1, -$4, -$6); } + | position '+' place { $$ = addpos($1, $3); } + | position '-' place { $$ = subpos($1, $3); } + | '(' place ',' place ')' { $$ = makepos(getcomp($2,DOTX), getcomp($4,DOTY)); } + | expr LT position ',' position GT { $$ = makebetween($1, $3, $5); } + | expr BETWEEN position AND position { $$ = makebetween($1, $3, $5); } + ; + +place: + PLACENAME { y = getvar($1); $$ = y.o; } + | PLACENAME CORNER { y = getvar($1); $$ = getpos(y.o, $2); } + | CORNER PLACENAME { y = getvar($2); $$ = getpos(y.o, $1); } + | HERE { $$ = gethere(); } + | 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 { y = getvar($1); $$ = getblock(y.o, $3); } + ; + +last: + last LAST { $$ = $1 + 1; } + | NTH LAST { $$ = $1; } + | LAST { $$ = 1; } + ; + +type: + BOX + | CIRCLE + | ELLIPSE + | ARC + | LINE + | ARROW + | SPLINE + | BLOCK + ; + +expr: + NUMBER + | VARNAME { $$ = getfval($1); } + | asgn + | expr '+' expr { $$ = $1 + $3; } + | expr '-' expr { $$ = $1 - $3; } + | expr '*' expr { $$ = $1 * $3; } + | expr '/' expr { if ($3 == 0.0) { + ERROR "division by 0" WARNING; $3 = 1; } + $$ = $1 / $3; } + | expr '%' expr { if ((long)$3 == 0) { + ERROR "mod division by 0" WARNING; $3 = 1; } + $$ = (long)$1 % (long)$3; } + | '-' expr %prec UMINUS { $$ = -$2; } + | '(' expr ')' { $$ = $2; } + | 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); } + | PLACENAME '.' VARNAME { y = getvar($1); $$ = getblkvar(y.o, $3); } + | last BLOCK '.' VARNAME { $$ = getblkvar(getlast($1,$2), $4); } + | NTH BLOCK '.' VARNAME { $$ = getblkvar(getfirst($1,$2), $4); } + | expr GT expr { $$ = $1 > $3; } + | expr LT expr { $$ = $1 < $3; } + | expr LE expr { $$ = $1 <= $3; } + | expr GE expr { $$ = $1 >= $3; } + | expr EQ expr { $$ = $1 == $3; } + | expr NEQ expr { $$ = $1 != $3; } + | expr ANDAND expr { $$ = $1 && $3; } + | expr OROR expr { $$ = $1 || $3; } + | NOT expr { $$ = !($2); } + | LOG '(' expr ')' { $$ = Log10($3); } + | EXP '(' expr ')' { $$ = Exp($3 * log(10.0)); } + | expr '^' expr { $$ = pow($1, $3); } + | SIN '(' expr ')' { $$ = sin($3); } + | COS '(' expr ')' { $$ = cos($3); } + | ATAN2 '(' expr ',' expr ')' { $$ = atan2($3, $5); } + | SQRT '(' expr ')' { $$ = Sqrt($3); } + | RAND '(' ')' { $$ = (float)rand() / 32767.0; /* might be 2^31-1 */ } + | MAX '(' expr ',' expr ')' { $$ = $3 >= $5 ? $3 : $5; } + | MIN '(' expr ',' expr ')' { $$ = $3 <= $5 ? $3 : $5; } + | INT '(' expr ')' { $$ = (long) $3; } + ; |