| %{ |
| #include <stdio.h> |
| #include <math.h> |
| #include "pic.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; } |
| ; |