|
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 */