%{ /* * parse.y 1.7 * * Parser Description File for Spreadsheet Program `vis' * * A. F. Gettier * Bell Laboratories * Update made 11/15/82 10:51:06 * Retrieved 11/15/82 13:22:37 */ #include <stdio.h> #include <math.h> #include "curses.h" #include "vis.h" extern struct qheader Fixup; int Inrow, Incol; %} %start lines %union { char *sval; double dval; int ival; struct vdef vval; struct node nval; struct range rval; struct colstat cval; } %type <ival> amount direc %type <nval> expr %type <rval> range %type <cval> colstat %left '+' '-' %left '*' '/' '%' %left EXPON %left UMINUS %token PI ABS ACOS ASIN ATAN ATAN2 COS EXP GAMMA HYPOT %token INT LOG POW SIN SQRT COL DUP DUPLICATE %token EDIT POSITION REDRAW REFRESH REP REPLICATE ROW %token SCALE SHIFT SLIDE SHELL SH WIDTH QUIT TERM LIST %token ERROR ZERO THRU AT DEBUG VER UP DOWN LEFT RIGHT %token HELP %token <sval> STR LETTERS READ WRITE COPY %token <dval> NUMBER %token <ival> FUNC %token <vval> AVARIABLE %token <nval> VARIABLE %% lines : /* empty */ | lines line ; line : AVARIABLE '=' expr TERM { struct node *nt; /* * Get the Target Node */ nt = getnode( $1.row, $1.col ); /* * Assign the String */ if ( nt->def != 0 ) free( nt->def ); nt->def = $1.tval; /* * Was the Old Value a String? */ if ( nt->type == STRING ) { free( nt->svalue ); nt->svalue = 0; } /* * Do the assignment */ switch ( $3.type ) { case NUM: if ( nt->type != NUM || nt->value != $3.value ) { struct qheader *y; struct node *x; y = qcopy( &(nt->depend) ); while ( (x=qread( y ) ) != 0 ) qadd( &Fixup, x ); nt->value = $3.value; free( (char *)y ); } nt->type = $3.type; break; case STRING: nt->svalue = $3.svalue; nt->type = $3.type; break; default: nt->type = UNRES; } prnode( nt ); } | COPY TERM { FILE *fp; char *fn; if ( $1 == 0 ) fn = getfn(); else fn = $1; if ( (fp=fopen( fn, "w" )) == 0 ) { char errbuf[64]; (void)sprintf( errbuf, "Cannot open '%s'", fn ); yyerror( errbuf ); lexinit(); } else { move( LINES-2, 0 ); printw( "Copying Screen Image to File '%s'", fn ); clrtoeol(); refresh(); copyfile( fp ); (void)fclose( fp ); } } | DEBUG TERM { /* yydebug = 1 - yydebug; */ } | DUPLICATE range AT VARIABLE TERM { duplicate( $2.fromrow, $2.fromcol, $2.torow, $2.tocol, $4.row, $4.col ); } | DUP range AT VARIABLE TERM { duplicate( $2.fromrow, $2.fromcol, $2.torow, $2.tocol, $4.row, $4.col ); } | EDIT TERM { editfile(); } | HELP TERM { listhelp(); } | LIST TERM { listfile(); } | QUIT TERM { quit(); } | READ TERM { FILE *fp; char *fn; if ( $1 == 0 ) fn = getfn(); else fn = $1; if ( (fp=fopen( fn, "r" )) == 0 ) { char errbuf[64]; (void)sprintf( errbuf, "Cannot open '%s'", fn ); yyerror( errbuf ); lexinit(); } else { move( LINES-2, 0 ); printw( "Reading from File '%s'", fn ); clrtoeol(); refresh(); readfile( fp ); } } | REDRAW TERM { wrefresh( curscr ); } | REFRESH TERM { wrefresh( curscr ); } | REPLICATE VARIABLE AT range TERM { replicate( $2.row, $2.col, $4.fromrow, $4.fromcol, $4.torow, $4.tocol ); } | REP VARIABLE AT range TERM { replicate( $2.row, $2.col, $4.fromrow, $4.fromcol, $4.torow, $4.tocol ); } | SCALE colstat { if ( $2.colnum < 0 ) setscale( $2.number ); else isetscale( $2.colnum, $2.number ); } | SHIFT direc amount { switch( $2 ) { case 1: scrup( $3 ); break; case 2: scrdown( $3 ); break; case 3: scrleft( $3 ); break; case 4: scrright( $3 ); } } | SH TERM { move( LINES-1, 0 ); clrtoeol(); refresh(); resetty(); (void)system( "/bin/sh" ); noecho(); crmode(); wrefresh( curscr ); } | SHELL TERM { move( LINES-1, 0 ); clrtoeol(); refresh(); resetty(); (void)system( "/bin/sh" ); noecho(); crmode(); wrefresh( curscr ); } | VER TERM { yyerror("VIS 1.7 11/15/82"); } | WIDTH colstat { if ( $2.colnum < 0 ) setwidth( $2.number ); else isetwidth( $2.colnum, $2.number ); } | WRITE TERM { FILE *fp; char *fn; if ( $1 == 0 ) fn = getfn(); else fn = $1; if ( (fp=fopen( fn, "w" )) == 0 ) { char errbuf[64]; (void)sprintf( errbuf, "Cannot open '%s'", fn ); yyerror( errbuf ); lexinit(); } else { move( LINES-2, 0 ); printw( "Writing to File '%s'", fn ); clrtoeol(); refresh(); dumpfile( fp ); (void)fclose( fp ); } } | ZERO TERM { /* * zero out the current definitions */ zerodef(); zeroscreen(); } | error TERM ; expr : '(' expr ')' { $$ = $2; } | expr '+' expr { $$ = mathop( &($1), &($3) ); if ( $$.type == NUM ) $$.value = $1.value + $3.value; } | expr '-' expr { $$ = mathop( &($1), &($3) ); if ( $$.type == NUM ) $$.value = $1.value - $3.value; } | expr '*' expr { $$ = mathop( &($1), &($3) ); if ( $$.type == NUM ) $$.value = $1.value * $3.value; } | expr '/' expr { $$ = mathop( &($1), &($3) ); if ( $$.type == NUM ) { if ( $3.value == 0 ) $$.value = BIG; else $$.value = $1.value / $3.value; } } | expr EXPON expr { $$ = mathop( &($1), &($3) ); if ( $$.type == NUM ) $$.value = pow( $1.value, $3.value ); } | '-' expr %prec UMINUS { $$ = $2; $$.value = - $2.value; } | '+' expr %prec UMINUS { $$ = $2; } | FUNC '(' expr ')' { double xval; $$ = mathop( &($3), &($3) ); if ( $$.type == NUM ) { xval = $3.value; switch( $1 ) { case ABS: if ( xval < 0 ) $$.value = -xval; else $$.value = xval; break; case ACOS: $$.value = acos( xval ); break; case ASIN: $$.value = asin( xval ); break; case ATAN: $$.value = atan( xval ); break; case COS: $$.value = cos( xval ); break; case EXP: $$.value = exp( xval ); break; case GAMMA: $$.value = gamma( xval ); break; case INT: $$.value = (double)((int)xval); break; case LOG: $$.value = log( xval ); break; case SIN: $$.value = sin( xval ); break; case SQRT: $$.value = sqrt( xval ); break; default: lexinit(); unput( '\n' ); yyerror( "Incorrect Function Call" ); } } } | FUNC '(' expr ',' expr ')' { double xval, yval; $$ = mathop( &($3), &($5) ); if ( $$.type == NUM ) { xval = $3.value; yval = $5.value; switch( $1 ) { case ATAN2: $$.value = atan2( xval, yval ); break; case HYPOT: $$.value = hypot( xval, yval ); break; case POW: $$.value = pow( xval, yval ); break; default: lexinit(); unput( '\n' ); yyerror( "Incorrect Function Call" ); } } } | POSITION '[' expr ',' expr ']' { struct node *n; $$ = mathop( &($3), &($5) ); if ( $$.type == NUM ) { int i, j; i = (int)$3.value-1; j = (int)$5.value-1; if ( i < 0 || j < 0 ) { char bfr[128]; lexinit(); (void)sprintf( bfr, "Illegal Request for Position[ %d, %d ]", i+1, j+1 ); yyerror( bfr ); $$.type = UNDEF; unput( '\n' ); } else { n = getnode( i, j ); prnode( n ); qadd( &(n->depend), getnode( Inrow, Incol ) ); $$ = *n; if ( $$.type == STRING ) $$.svalue = copystr( $$.svalue ); $$.row = -1; $$.col = -1; } } else $$.type = UNRES; } | COL { $$.svalue = 0; $$.def = 0; $$.type = NUM; $$.value = (float)(Incol + 1); $$.row = -1; $$.col = -1; } | ROW { $$.svalue = 0; $$.def = 0; $$.type = NUM; $$.value = (float)(Inrow+1); $$.row = -1; $$.col = -1; } | VARIABLE { struct node *x; x = getnode( $1.row, $1.col ); $$ = *x; /* If it is a string, patch it up */ if ( x->type == STRING ) { $$.svalue = copystr( x->svalue ); $$.row = $$.col = (-1); } /* Mark The Screen That it is Undef */ if ( x->type == UNDEF ) prnode( x ); /* Set up the Dependency List */ (void)qadd( &(x->depend), getnode( Inrow, Incol ) ); } | STR { $$.row = -1; $$.col = -1; $$.type = STRING; $$.svalue = $1; } | NUMBER { $$.row = -1; $$.col = -1; $$.type = NUM; $$.value = $1; $$.svalue = 0; $$.def = 0; } ; range : VARIABLE THRU VARIABLE { $$.fromrow = $1.row; $$.fromcol = $1.col; $$.torow = $3.row; $$.tocol = $3.col; } | VARIABLE { $$.fromrow = $$.torow = $1.row; $$.fromcol = $$.tocol = $1.col; } ; direc : UP { $$ = 1; } | DOWN { $$ = 2; } | LEFT { $$ = 3; } | RIGHT { $$ = 4; } ; amount : TERM { $$ = 1; } | NUMBER TERM { $$ = (int)$1; } ; colstat : NUMBER TERM { $$.colnum = -1; $$.number = (int)$1; } | LETTERS NUMBER TERM { $$.colnum = colval( foldup( $1 ) ); $$.number = (int)$2; free( $1 ); } ; %% char * getfn() { static char chrbuf[64]; char *tbuf; move( 22, 0 ); printw("Enter File Name: " ); refresh(); tbuf = chrbuf; loop { *tbuf = getch(); addch( *tbuf ); refresh(); if ( *(tbuf++) == '\n' ) break; } *(--tbuf) = '\0'; return( chrbuf ); } colval( string ) char *string; { int i; i = -1; while ( *string != '\0' ) { i = (i + 1) * 26 + *string - 'A'; string++; } return( i ); }