|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T y
Length: 15119 (0x3b0f)
Types: TextFile
Names: »yacc.y«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/graph/yacc.y«
/*
* Copyright (C) 1986 Alan Kent
*
* Permission is granted to freely distribute part or
* all of this code as long as it is not for profit
* and this message is retained in the code.
*
* No resposibility is taken for any damage or incorect
* results this program generates.
*
*/
/* Declaration section */
%{
#include <stdio.h>
#include <math.h>
#include "graph.h"
#define LARGE_INT 16000
extern char *new ();
extern double floor ();
extern table_st *read_table ();
extern table_st *load_table ();
extern attr_st *attr_node ();
extern double eval ();
extern table_st *eval_tab ();
extern tnode_st *tab_node ();
extern parm_st *parm_node ();
extern char *ctime ();
extern int gargc;
extern char **gargv;
extern axis_st xaxis;
extern axis_st yaxis;
extern graph_st graph[];
extern int num_graphs;
extern char *graph_label;
extern int horiz_legend;
extern int vert_legend;
static axis_st *paxis;
%}
%union {
attr_st *attr_expr;
table_st *table;
tnode_st *tnode;
double number;
char *string;
expr_list_st *expr_list;
range_st *range;
int_st *interval;
int integer;
parm_st *parm;
tcol_st *tcol;
trow_st *trow;
}
%left JOIN SORT GROUP CUMULATE
%left BY
%left APPEND
%left ADJACENT
%left '[' WHERE
%left <string> STRING IDENT TAB_IDENT VAR_IDENT FTAB_IDENT FVAR_IDENT
%left <number> NUMBER
%type <string> string_expr string_sub_expr
%type <trow> table_line_list
%type <tcol> table_line
%type <number> constant
%type <attr_expr> expr or_op and_op rel_op add_op mul_op primary attr
%type <expr_list> expr_list
%type <range> range
%type <interval> interval
%type <string> group_function
%type <tnode> table
%type <parm> dec_parm_list dec_parm call_parm_list call_parm
%start program
%token READ SHELL PRINT TABLE XAXIS YAXIS PLOT GRAPH VALUE INCLUDE
%token APPEND SORT JOIN GROUP BY WHERE INTO INTERVAL SIZE FROM TO WITH
%token PERFORMING ADJACENT DATE PARAMETER SAVE LOAD AS
%token LBRACKET RBRACKET LPAREN RPAREN
%token EQ NE GE GT LE LT PLUS MINUS DIVIDE MULTIPLY AND OR NOT NEG
%token IDENT TAB_IDENT VAR_IDENT STRING ATTR NUMBER FTAB_IDENT FVAR_IDENT
%token TICK LABEL FORMAT AUTO NO SCALE FRAME GRID OUTLINE AXIS
%token LOGRITHMIC LINEAR DOTTED SOLID LONGDASHED SHORTDASHED DOTDASHED LINE
%token QUEST COLON MODULUS TAB_CONST PROJECT CUMULATE GENERATE
%token TRIANGLE CIRCLE SQUARE CROSS POINTS POWER
%token PUT LEGEND AT TOP MIDDLE BOTTOM LEFT CENTER RIGHT
%token STR VAL PARMS ASSUME
%%
/* Rules section */
program: statement_list
{
if ( num_graphs > 0 ) {
dump_graphs ();
reset_graphs ();
}
}
;
statement_list:
| statement statement_list
;
statement: ';'
| IDENT EQ table
{ tab_declare ( $1 , eval_tab ( $3 ) ); }
| TAB_IDENT EQ table
{ tab_declare ( $1 , eval_tab ( $3 ) ); }
| IDENT EQ expr
{ var_declare ( $1 , eval ( NULL , 0 , $3 ) ); }
| VAR_IDENT EQ expr
{ var_declare ( $1 , eval ( NULL , 0 , $3 ) ); }
| IDENT '(' dec_parm_list ')' EQ expr
{ fun_declare ( $1 , $3 , $6 , NULL ); }
| IDENT '(' dec_parm_list ')' EQ table
{ fun_declare ( $1 , $3 , NULL , $6 ); }
| INCLUDE string_expr
{ include ( $2 ); release ( $2 ); }
| SHELL string_expr
{ system ( $2 ); /* use >file */ release ( $2 ); }
| SAVE table AS string_expr
{ save_table ( $4 , eval_tab ( $2 ) ); release ( $4 ); }
| PRINT GT GT string_expr table
{ print_table ( eval_tab ( $5 ) , $4 , "a" ); release ( $4 ); }
| PRINT GT string_expr table
{ print_table ( eval_tab ( $4 ) , $3 , "w" ); release ( $3 ); }
| PRINT table
{ print_table ( eval_tab ( $2 ) , NULL , NULL ); }
| PRINT GT GT string_expr expr
{ print_expr ( eval ( NULL , 0 , $5 ) , $4 , "a" ); release ( $4 ); }
| PRINT GT string_expr expr
{ print_expr ( eval ( NULL , 0 , $4 ) , $3 , "w" ); release ( $3 ); }
| PRINT expr
{ print_expr ( eval ( NULL , 0 , $2 ) , NULL , NULL ); }
| PRINT GT GT string_expr string_expr
{ print_string ( $5 , $4 , "a" ); release ( $4 ); release ( $5 ); }
| PRINT GT string_expr string_expr
{ print_string ( $4 , $3 , "w" ); release ( $3 ); release ( $4 ); }
| PRINT string_expr
{ print_string ( $2 , NULL , NULL ); release ( $2 ); }
| graph
| XAXIS
{ paxis = &xaxis; }
axis
| YAXIS
{ paxis = &yaxis; }
axis
| PUT LEGEND AT pos_list
| PLOT
{ dump_graphs (); reset_graphs (); }
| ASSUME expr string_expr
{
if ( eval ( NULL , 0 , $2 ) == 0.0 ) {
fprintf ( stderr , "%s\n" , $3 );
exit ( 1 );
}
release ( $3 );
}
;
pos_list: /* empty */
| pos pos_list
;
pos: LEFT
{ horiz_legend = LEFT; }
| CENTER
{ horiz_legend = CENTER; }
| RIGHT
{ horiz_legend = RIGHT; }
| TOP
{ vert_legend = TOP; }
| MIDDLE
{ vert_legend = MIDDLE; }
| BOTTOM
{ vert_legend = BOTTOM; }
;
table : READ string_expr
{
$$ = tab_node ( TAB_CONST );
$$->table = read_table ( $2 , -1 , -1 );
release ( $2 );
}
| READ expr BY expr string_expr
{
$$ = tab_node ( TAB_CONST );
$$->table = read_table ( $5 ,
(int)eval ( NULL , 0 , $2 ) ,
(int)eval ( NULL , 0 , $4 ) );
release ( $5 );
}
| LOAD string_expr
{
$$ = tab_node ( TAB_CONST );
$$->table = load_table ( $2 );
release ( $2 );
}
| '{' table_line_list '}'
{
$$ = tab_node ( TABLE );
$$->const_table = $2;
}
| GENERATE range interval
{
$$ = tab_node ( GENERATE );
$$->range = $2;
$$->interval = $3;
}
| table APPEND table
{
$$ = tab_node ( APPEND );
$$->left = $1;
$$->right = $3;
}
| table ADJACENT table
{
$$ = tab_node ( ADJACENT );
$$->left = $1;
$$->right = $3;
}
| table '[' expr_list ']'
{
$$ = tab_node ( PROJECT );
$$->left = $1;
$$->expr_list = $3;
}
| table WHERE expr
{
$$ = tab_node ( WHERE );
$$->left = $1;
$$->expr = $3;
}
| SORT table BY attr
{
$$ = tab_node ( SORT );
$$->left = $2;
$$->expr = $4;
}
| JOIN table ',' table BY attr ',' attr
{
$$ = tab_node ( JOIN );
$$->left = $2;
$$->right = $4;
$$->expr = attr_node ( JOIN , (double)0.0 , $6 , $8 );
}
| CUMULATE table BY attr
{
$$ = tab_node ( CUMULATE );
$$->left = $2;
$$->expr = $4;
}
| GROUP table range interval PERFORMING group_function
{
$$ = tab_node ( GROUP );
$$->left = $2;
$$->range = $3;
$$->interval = $4;
$$->ident = $6;
}
| '(' table ')'
{ $$ = $2; }
| IDENT
{ abort ( "Undefined identifier" ); }
| FTAB_IDENT '(' call_parm_list ')'
{
$$ = tab_node ( FTAB_IDENT );
$$->ident = $1;
$$->parm_list = $3;
}
| TAB_IDENT
{ $$ = tab_node ( TAB_IDENT ); $$->ident = $1; }
;
group_function:
FVAR_IDENT
{ $$ = $1; check_group_fun ( $1 ); }
;
table_line_list:
{ $$ = NULL; }
| '{' table_line '}' table_line_list
{
$$ = (trow_st *) new ( sizeof ( trow_st ) );
$$->cols = $2;
$$->next = $4;
}
;
table_line: expr
{
$$ = (tcol_st *) new ( sizeof ( tcol_st ) );
$$->expr = $1;
$$->next = NULL;
}
|
expr ',' table_line
{
$$ = (tcol_st *) new ( sizeof ( tcol_st ) );
$$->expr = $1;
$$->next = $3;
}
;
attr : '$' primary
{ $$ = $2; }
;
expr : or_op '?' or_op ':' or_op
{ $$ = attr_node ( QUEST , (double)0.0 , $1 ,
attr_node ( COLON , (double)0.0 , $3 , $5 ) ); }
| or_op
{ $$ = $1; }
;
or_op : and_op '|' or_op
{ $$ = attr_node ( OR , (double)0.0 , $1 , $3 ); }
| and_op
{ $$ = $1; }
;
and_op : rel_op '&' and_op
{ $$ = attr_node ( AND , (double)0.0 , $1 , $3 ); }
| rel_op
{ $$ = $1; }
;
rel_op : add_op EQ add_op
{ $$ = attr_node ( EQ , (double)0.0 , $1 , $3 ); }
| add_op NE add_op
{ $$ = attr_node ( NE , (double)0.0 , $1 , $3 ); }
| add_op LE add_op
{ $$ = attr_node ( LE , (double)0.0 , $1 , $3 ); }
| add_op LT add_op
{ $$ = attr_node ( LT , (double)0.0 , $1 , $3 ); }
| add_op GE add_op
{ $$ = attr_node ( GE , (double)0.0 , $1 , $3 ); }
| add_op GT add_op
{ $$ = attr_node ( GT , (double)0.0 , $1 , $3 ); }
| add_op
{ $$ = $1; }
;
add_op : mul_op '+' add_op
{ $$ = attr_node ( PLUS , (double)0.0 , $1 , $3 ); }
| mul_op '-' add_op
{ $$ = attr_node ( MINUS , (double)0.0 , $1 , $3 ); }
| mul_op
{ $$ = $1; }
;
mul_op : primary '/' mul_op
{ $$ = attr_node ( DIVIDE , (double)0.0 , $1 , $3 ); }
| primary '*' mul_op
{ $$ = attr_node ( MULTIPLY , (double)0.0 , $1 , $3 ); }
| primary '%' mul_op
{ $$ = attr_node ( MODULUS , (double)0.0 , $1 , $3 ); }
| primary
{ $$ = $1; }
;
primary : '-' primary
{ $$ = attr_node ( NEG , (double)0.0 , $2 , NULL ); }
| '!' primary
{ $$ = attr_node ( NOT , (double)0.0 , $2 , NULL ); }
| '(' expr ')'
{ $$ = $2; }
| attr
{ $$ = attr_node ( ATTR , (double)0.0 , $1 , NULL ); }
| constant
{ $$ = attr_node ( NUMBER , $1 , NULL , NULL ); }
| FVAR_IDENT '(' call_parm_list ')'
{
$$ = attr_node ( FVAR_IDENT , (double)0.0 , NULL , NULL );
$$->ident = $1;
$$->parm_list = $3;
}
| VAR_IDENT
{
$$ = attr_node ( VAR_IDENT , (double)0.0 , NULL , NULL );
$$->ident = $1;
}
;
expr_list:
{ $$ = NULL; }
| expr
{
$$ = (expr_list_st *) new ( sizeof ( expr_list_st ) );
$$->expr = $1;
$$->next = NULL;
}
| expr ',' expr_list
{
$$ = (expr_list_st *) new ( sizeof ( expr_list_st ) );
$$->expr = $1;
$$->next = $3;
}
;
interval: WITH expr INTERVAL
{
$$ = (int_st *) new ( sizeof ( int_st ) );
$$->int_type = INUMINT;
$$->value = eval ( NULL , 0 , $2 );
}
| INTERVAL SIZE expr
{
$$ = (int_st *) new ( sizeof ( int_st ) );
$$->int_type = ISIZE;
$$->value = eval ( NULL , 0 , $3 );
}
;
range : /* default min to max */
{ $$ = NULL; }
| FROM expr TO expr
{
$$ = (range_st *) new ( sizeof ( range_st ) );
$$->min = eval ( NULL , 0 , $2 );
$$->max = eval ( NULL , 0 , $4 );
}
;
constant: NUMBER
{ $$ = $1; }
| PARMS
{ $$ = gargc - 2; }
| VAL '(' string_expr ')'
{
double num;
if ( scan_value ( $3 , &num ) == NULL ) {
warn ( "Illegal number in VAL()" );
num = 0.0;
}
release ( $3 );
$$ = num;
}
;
axis : axis_option_list
;
axis_option_list:
| axis_option axis_option_list
;
axis_option:
/*
| TICK range
| AUTO TICK
*/
LABEL string_expr
{ paxis->label = $2; }
| FORMAT string_expr
{ paxis->user_format = $2; }
| AUTO SCALE
{ paxis->scale = AUTO; }
| NO SCALE
{ paxis->scale = NO; }
| TICK SIZE expr POWER expr
{
paxis->auto_tick_size = 0;
paxis->tick_size = eval ( NULL , 0 , $3 );
paxis->power_10 = eval ( NULL , 0 , $5 );
}
| TICK SIZE expr
{
paxis->auto_tick_size = 0;
paxis->tick_size = eval ( NULL , 0 , $3 );
paxis->power_10 = 0.0; /* not good */
}
| FRAME AXIS
{ paxis->frame = FRAME; }
| GRID AXIS
{ paxis->frame = GRID; }
| OUTLINE AXIS
{ paxis->frame = OUTLINE; }
| NO AXIS
{ paxis->frame = NO; }
| LOGRITHMIC
{ paxis->linear = LOGRITHMIC; }
| LINEAR
{ paxis->linear = LINEAR; }
| FROM expr TO expr
{
paxis->range.min = eval ( NULL , 0 , $2 );
paxis->range.max = eval ( NULL , 0 , $4 );
}
;
graph : GRAPH table
{
if ( num_graphs >= MAX_GRAPHS )
abort ( "too many graphs" );
graph[ num_graphs ].line_type = SOLID;
graph[ num_graphs ].point_type = 0;
graph[ num_graphs ].cumulative = 0;
graph[ num_graphs ].label = NULL;
graph[ num_graphs ].legend = NULL;
}
graph_option_list
{
table_st *p;
p = eval_tab ( $2 );
if ( p == NULL || p->next == NULL )
abort ( "GRAPH requires two column tables to plot" );
if ( p->size < 1 )
warn ( "No data in graph to plot" );
else
graph[ num_graphs++ ].table = p;
}
| GRAPH LABEL string_expr
{
graph_label = $3;
}
;
graph_option_list:
| graph_option_list graph_option
;
graph_option: DOTTED LINE
{ graph[ num_graphs ].line_type = DOTTED; }
| SOLID LINE
{ graph[ num_graphs ].line_type = SOLID; }
| SHORTDASHED LINE
{ graph[ num_graphs ].line_type = SHORTDASHED; }
| LONGDASHED LINE
{ graph[ num_graphs ].line_type = LONGDASHED; }
| DOTDASHED LINE
{ graph[ num_graphs ].line_type = DOTDASHED; }
| NO LINE
{ graph[ num_graphs ].line_type = NO; }
| NO POINTS
{ graph[ num_graphs ].point_type = 0; }
| TRIANGLE POINTS
{ graph[ num_graphs ].point_type |= MSK_TRIANGLE; }
| CIRCLE POINTS
{ graph[ num_graphs ].point_type |= MSK_CIRCLE; }
| SQUARE POINTS
{ graph[ num_graphs ].point_type |= MSK_SQUARE; }
| CROSS POINTS
{ graph[ num_graphs ].point_type |= MSK_CROSS; }
| PLUS POINTS
{ graph[ num_graphs ].point_type |= MSK_PLUS; }
| LABEL string_expr
{ graph[ num_graphs ].label = $2; }
| LEGEND string_expr
{ graph[ num_graphs ].legend = $2; }
;
dec_parm_list:
{ $$ = NULL; }
|
dec_parm
{ $$ = $1; $$->next = NULL; }
| dec_parm ',' dec_parm_list
{ $$ = $1; $$->next = $3; }
;
dec_parm: VAR_IDENT
{ $$ = parm_node ( $1 , VALUE ); }
| TAB_IDENT
{ $$ = parm_node ( $1 , TABLE ); }
;
call_parm_list:
{ $$ = NULL; }
|
call_parm
{ $$ = $1; $$->next = NULL; }
| call_parm ',' call_parm_list
{ $$ = $1; $$->next = $3; }
;
call_parm: expr
{ $$ = parm_node ( NULL , VALUE ); $$->expr = $1; }
| table
{ $$ = parm_node ( NULL , TABLE ); $$->tab_expr = $1; }
;
string_expr: string_sub_expr
{
$$ = $1;
}
| string_sub_expr '+' string_expr
{
char *p;
p = new ( strlen ( $1 ) + strlen ( $3 ) + 1 );
strcpy ( p , $1 );
strcat ( p , $3 );
release ( $1 );
release ( $3 );
$$ = p;
}
;
string_sub_expr: STRING
{
char *p;
p = new ( strlen ( $1 ) + 1 );
strcpy ( p , $1 );
$$ = p;
}
| PARAMETER constant
{
char *p;
int i;
i = $2;
if ( i > gargc - 2 || i < 1 )
abort ( "undefined parameter" );
p = new ( strlen ( gargv[ i + 1 ] ) + 1 );
strcpy ( p , gargv[ i + 1 ] );
$$ = p;
}
| STR '(' string_expr ',' expr ')'
{
char *p;
char buf[ 100 ];
sprintf ( buf , $3 , eval ( NULL , 0 , $5 ) );
p = new ( strlen ( buf ) + 1 );
strcpy ( p , buf );
release ( $3 );
$$ = p;
}
| STR '(' expr ')'
{
char *p;
char buf[ 30 ];
sprintf ( buf , "%g" , eval ( NULL , 0 , $3 ) );
p = new ( strlen ( buf ) + 1 );
strcpy ( p , buf );
$$ = p;
}
| DATE
{
long clock;
char *p , *str;
int i;
p = new ( 32 );
time ( &clock );
str = ctime ( &clock );
for ( i = 0; str[i] != '\n' && str[i] != '\0'; i++ )
p[i] = str[i];
p[i] = '\0';
$$ = p;
}
;
%%
/* Subroutine section */