/* ** --- GRAMMAR.Y ------- REPORT RULE SYSTEM --------------------------------- ** ** ** REPORT specification ** ** adapted from Herrmann, Knut ** Technische Universitaet Dresden ** Sektion Informationsverarbeitung ** Diplomarbeit vom 25.Jan. 1986 ** ** and DABA/REP for DABA1600 ** ** ** Version: @(#)grammar.y 4.0 02/05/89 ** */ /* COMMANDS */ %term ALL AS BIG CALL %term CASE CLEAR COL COLUMN %term COMPLEMENT DEFINE DO DOMAIN %term ELSE END ENDA ENDC %term ENDI ENDO ENDR ENDW %term EXCEPTION FOR GROUPBEGIN GROUPEND %term IF IN IS LENGTH %term LINE NEW NEWLINE NEWPAGE %term ON ONE OUT PAGE %term PROC REPEAT REPORT RETURN %term SEMICOL SET SPACE SWITCH %term TERMINAL THEN TUPLE NVAR %term WHILE /* CONVERSION WORDS */ %term BYTE F_CHAR FORMAT GRAPHIC %term INTEGER REAL WORD /* FORMAT WORDS */ %term BATCH BEFORE DATE EXP %term FROM_TO IGNORE NORM PIC %term POINT SCALE WITH /* CONSTANTS */ %term BCONST /* boolean const */ %term ICONST /* integer const */ %term LCONST /* long integer const */ %term NAME /* name const */ %term RCONST /* real const */ %term SCONST /* string const */ %term SYS_CONST /* PUNCTUATION */ %term LPAREN RPAREN BGNCMNT ENDCMNT /* OPERATORS */ %term AUOP /* ARITHMETIC UNARY OPERATORS */ %term ABOP /* ARITHMETIC BINARY OPERATORS */ %term ABIS /* BINARY ASSIGNMENT OPERATORS */ %term BDOP /* BOUNDS OPERATORS */ %term EOP /* EQUALITY OPERATORS */ %term LUOP /* LOGICAL BINARY OPERATORS */ %term LBOP /* LOGICAL BINARY OPERATORS */ /* DEFINE ASCENDING PRECEDENCE FOR OPERATORS */ %left LBOP %left LUOP %left AUOP %left ABOP %binary unaryop %{ # include "rc.h" /* FORMAT STRUCTURE (formatted output) */ static struct format Format; extern char *RC_INIT_JUMP(); %} %% program : rep_kwd NAME desc fmt_def AS stmt_s report stmt_s SEMICOL = { RC_BYTE(rcRC_END); rc_report($2); } | error ; rep_kwd : DEFINE REPORT | REPORT ; desc : DOMAIN NAME = { S_desc = $2; } | /* empty */ = { S_desc = "desc"; } ; fmt_def : WITH fmt_s | /* empty */ ; fmt_s : fmt | fmt_s fmt ; fmt : LINE ICONST = { R_lines = (int) $2; } | ALL LINE ICONST = { R_all_lines = (int) $3; } | COLUMN ICONST = { R_cols = (int) $2; } | FROM_TO PAGE ICONST = { if (!((int) $1)) R_first_page = (int) $3; else R_last_page = (int) $3; } | FROM_TO TUPLE ICONST = { if (!((int) $1)) R_from_tuple = (int) $3; else R_to_tuple = (int) $3; } | BIG = { R_big = TRUE; } | DEFINE NAME IS ICONST = { RC_MACRO($2, (int) $4); } | DEFINE DOMAIN ICONST IS dom_fmt ICONST = { RC_IDOM((int) $3, (int) $5, (int) $6); } | DEFINE DOMAIN NAME IS dom_fmt ICONST = { RC_NDOM($3, (int) $5, (int) $6); } | error ; dom_fmt : INTEGER | REAL | F_CHAR ; report : for_all print enda_kwd = { RC_BYTE(rcJUMP); RC_JUMP($1); R_for_all = R_rc - R_code; } ; for_all : fora_kwd stmt_s ; print : tuple_s | print tuple_s ; tuple_s : tuple stmt_s ; tuple : for1_kwd stmt_s end1_kwd = { RC_BYTE(rcEOTUP); } ; /* statements */ stmt_s : s_stmt | /* empty */ ; s_stmt : s_stmt stmt | stmt ; /* ASSIGNMENT */ stmt : assign /* PROCEDURE declaration */ | proc_hd stmt_s RETURN = { RC_BYTE(rcRETURN); RC_UPDATE($1); } /* procedure CALL statement */ | call = { if (!Proc[((int) $1) - 1]) rc_error(3, $1); else { RC_BYTE(rcCALL); RC_JUMP(Proc[((int) $1) - 1]); } } /* IF statement */ | if_cond if_then if_else endi_kwd = { RC_UPDATE($2); } /* WHILE statement */ | wh_cond wh_do endw_kwd = { /* jump to condition */ RC_BYTE(rcJUMP); RC_JUMP($1 - 1); /* update jump over WHILE */ RC_UPDATE($2); } /* REPEAT statement */ | repeat value stmt_s endr_kwd = { RC_BYTE(rcREPEAT); RC_WORD((int) $2); RC_JUMP($1); } /* CASE statement */ | case_hd case_s out endc_kwd = { rc_case($1); } /* ON statement */ | on_hd stmt_s endo_kwd = { RC_BYTE(rcRTTS); RC_UPDATE($1); /* jump over exception */ } /* TERMINAL statement */ | console = { Format.str_len = AAlength($1); RC_BYTE(prINPUT); RC_WORD(Format.str_len); RC_WORD(Format.batch_len); RC_STR($1, Format.str_len); } /* print DATE or TIME */ | DATE = { RC_BYTE((int) $1); } /* print NEWLINE */ | NEWLINE value = { RC_BYTE(prNEWLINE); RC_WORD((int) $2); } | NEW LINE value = { RC_BYTE(prNEWLINE); RC_WORD((int) $3); } | NEWLINE = { goto new_line; } | NEW LINE = { new_line: RC_BYTE(prNEWLINE); RC_WORD(A_NEWLINE); } /* print NEWPAGE */ | NEWPAGE = { goto new_page; } | NEW PAGE = { new_page: RC_BYTE(prNEWPAGE); } /* set COLUMN pointer */ | COL value = { RC_BYTE(prNEWCOL); RC_WORD((int) $2); } /* print SPACES */ | SPACE value = { RC_BYTE(prSPACE); RC_WORD((int) $2); } /* print constant STRING */ | string = { RC_BYTE(prSTRING); RC_WORD(Format.str_len); RC_WORD(Format.batch_len); RC_STR(Format.str_adr, Format.str_len); if (Format.fr_to[1]) { RC_BYTE(rcREPEAT); RC_WORD((int) Format.fr_to[1]); RC_JUMP(Format.fr_to[0]); } } /* formatted OUTPUT statement */ | format /* ERROR */ | error ; /* ASSIGMENT */ assign : CLEAR b_var = { $1 = RC_INIT_JUMP(setSWITCH); RC_BYTE(pushSWITCH); RC_WORD((int) $2); RC_BYTE(pushFALSE); goto expr_end; } | COMPLEMENT b_var = { $1 = RC_INIT_JUMP(setSWITCH); RC_BYTE(pushSWITCH); RC_WORD((int) $2); RC_BYTE(pushSWITCH); RC_WORD((int) $2); RC_BYTE(rcNOT); goto expr_end; } | b_assign IS b_expr = { goto expr_end; } | b_assign = { RC_BYTE(pushTRUE); goto expr_end; } | c_assign expr = { RC_BYTE(Format.data); goto expr_end; } | n_assign expr = { expr_end: RC_BYTE(rcEND_SET); RC_UPDATE($1); } ; b_assign: SET b_var = { $$ = RC_INIT_JUMP(setSWITCH); RC_BYTE(pushSWITCH); RC_WORD((int) $2); } ; c_assign: SET sys_var ABIS = { $$ = RC_INIT_JUMP(setVAR); RC_SYS_VAR((int) $2, FALSE); RC_SYS_VAR((int) $2, FALSE); Format.data = (int) $3; } ; n_assign: SET sys_var IS = { $$ = RC_INIT_JUMP(setVAR); RC_SYS_VAR((int) $2, FALSE); } ; /* PROCEDURE declaration */ proc_hd : PROC proc_nam = { if (Proc[((int) $2) - 1]) rc_error(2, $2); else { /* initialze jump over proc */ $$ = RC_INIT_JUMP(rcJUMP); /* now get the address of procedure */ Proc[((int) $2) - 1] = R_rc; } } ; /* procedure CALL statement */ call : CALL PROC proc_nam = { $$ = $3; } | CALL proc_nam = { $$ = $2; } ; proc_nam: ICONST = { if (((int) $1) <= 0 || ((int) $1) > MAX_PROCS) rc_error(1, $1); } ; /* IF statement */ if_cond : if_kwd b_expr = { RC_UPDATE($1); } ; if_kwd : IF = { if_code: /* initialize jump to THEN */ $$ = RC_INIT_JUMP(rcIF); } ; if_then : th_kwd stmt_s = { /* initialize jump to END IF */ $$ = RC_INIT_JUMP(rcJUMP); /* update jump to THEN */ RC_UPDATE($1); } ; th_kwd : THEN = { then_code: /* initialize jump to ELSE */ $$ = RC_INIT_JUMP(rcTHEN); } ; if_else : ELSE stmt_s | /* empty */ ; /* WHILE statement */ wh_cond : wh_kwd b_expr = { RC_UPDATE($1); } ; wh_kwd : WHILE = { goto if_code; } ; wh_do : do stmt_s ; do : DO = { goto then_code; } ; /* REPEAT statement */ repeat : REPEAT = { $$ = R_rc; } ; /* CASE statement */ case_hd : CASE var in_kwd = { if (Case[0]) rc_error(19); else { RC_BYTE(prVAR); RC_WORD((int) $2); /* initialize case# and addr(jump_table) */ $$ = RC_INIT_JUMP(rcCASE); RC_WORD(0); /* case# */ Case_no = 0; Case[0] = R_rc; } } ; in_kwd : IN | /* empty */ ; case_s : one_case | case_s one_case ; one_case: DO stmt_s = { RC_BYTE(rcRETURN); if (++Case_no == MAX_CASES) rc_error(23); else Case[Case_no] = R_rc; } ; out : OUT stmt_s = { out_code: RC_BYTE(rcRETURN); } | /* empty */ = { goto out_code; } ; /* ON statement */ on_hd : ON EXCEPTION do_kwd = { /* initialize jump over exception */ $$ = RC_INIT_JUMP((int) $2); } ; /* TERMINAL statement */ console : TERMINAL SCONST BATCH value = { Format.batch_len = (int) $4; $$ = $2; } | TERMINAL SCONST = { Format.batch_len = A_BATCH; $$ = $2; } ; /* print constant STRING */ string : str_kwd batch | str_kwd value = { Format.fr_to[1] = $2; } | str_kwd ; str_kwd : sconst = { /* initialize string output */ Format.batch_len = A_BATCH; Format.fr_to[0] = R_rc; Format.fr_to[1] = (char *) 0; /* used as repeat info */ } ; sconst : SCONST = { Format.str_len = AAlength($1); Format.str_adr = $1; } ; batch : BATCH value = { Format.batch_len = (int) $2; } ; /* formatted OUTPUT statement */ format : int_stm int_fmt = { if (!Format.data) rc_error(21); RC_BYTE(fmtINT); RC_WORD(Format.length); RC_STR(&Format.scale, sizeof (double)); /* picture string */ RC_WORD(Format.str_len); RC_STR(Format.str_adr, Format.str_len); } | dbl_stm dbl_fmt = { if (!Format.data) rc_error(21); RC_BYTE(fmtREAL); RC_WORD(Format.length); RC_STR(&Format.scale, sizeof (double)); RC_WORD(Format.before); RC_WORD(Format.point); RC_WORD(Format.ignore); RC_WORD(Format.norm); /* exponent string */ RC_WORD(Format.str_len); RC_STR(Format.str_adr, Format.str_len); } | chr_stm chr_fmt = { if (!Format.data) rc_error(21); RC_BYTE(fmtCHAR); RC_WORD(Format.length); RC_WORD((int) Format.fr_to[0]); RC_WORD((int) Format.fr_to[1]); RC_WORD(Format.batch_len); } | gra_stm gra_fmt = { if (!Format.data) rc_error(21); RC_BYTE(fmtGRAPH); RC_WORD(Format.length); /* from */ RC_WORD((int) Format.fr_to_v[0]); if (!Format.fr_to_v[0]) RC_STR(&Format.fr_to_8[0], sizeof (double)); /* to */ RC_WORD(Format.fr_to_v[1]); if (!Format.fr_to_v[1]) RC_STR(&Format.fr_to_8[1], sizeof (double)); /* with char */ RC_STR(Format.str_adr, sizeof (char)); } /* BIT/OCT/DEC/HEX */ | byte_kwd length data = { RC_BYTE((int) $1); RC_WORD((int) $2); } | byte_kwd data = { RC_BYTE((int) $1); RC_WORD(0); } ; /* INTEGER format */ int_stm : INTEGER = { /* initialize Format structure */ Format.data = FALSE; Format.length = 0; Format.scale = A_SCALE; Format.str_len = 0; Format.str_adr = 0; } ; int_fmt : i_fmt | int_fmt i_fmt ; i_fmt : length | scale | pic | object ; length : LENGTH value = { Format.length = (int) ($$ = $2); } ; scale : SCALE RCONST = { Format.scale = *((double *) $2); } | SCALE LCONST = { Format.scale = *((long *) $2); } | SCALE ICONST = { Format.scale = ((int) $2); } ; pic : PIC sconst ; /* REAL format */ dbl_stm : REAL = { /* initialize Format structure */ Format.data = FALSE; Format.length = 0; Format.scale = A_SCALE; Format.before = A_BEFORE; Format.point = A_POINT; Format.str_len = 0; Format.str_adr = 0; Format.ignore = FALSE; Format.norm = A_NORM; } ; dbl_fmt : d_fmt | dbl_fmt d_fmt ; d_fmt : length | scale | BEFORE value = { if (((int) $2) > MAX_I1) rc_error(22, 0, MAX_I1); else Format.before = ((int) $2); } | POINT value = { if (((int) $2) > MAX_I1) rc_error(22, 0, MAX_I1); else Format.point = ((int) $2); } | EXP sconst | IGNORE = { Format.ignore |= B_IGNORE; } | NORM norm = { Format.norm = ((int) $2); } | object ; norm : ICONST = { if (((int) $1) < L_NORM || ((int) $1) > H_NORM) rc_error(22, L_NORM, H_NORM); else if (((int) $1) < 0) { Format.ignore |= B_NORM; $$ = (char *) (- ((int) $1)); } } | var ; /* CHAR format */ chr_stm : F_CHAR = { /* initialze Format structure */ Format.data = FALSE; Format.length = 0; Format.fr_to[0] = (char *) A_FROM; Format.fr_to[1] = (char *) 0; Format.batch_len = A_BATCH; } ; chr_fmt : c_fmt | chr_fmt c_fmt ; c_fmt : length | fr_to | batch | object ; fr_to : FROM_TO value = { Format.fr_to[(int) $1] = $2; } ; /* GRAPHIC format */ gra_stm : GRAPHIC = { /* initialize Format structure */ Format.data = FALSE; Format.length = 0; Format.fr_to_v[0] = 0; Format.fr_to_v[1] = 0; Format.fr_to_8[0] = 0; Format.fr_to_8[1] = 0; Format.str_len = sizeof (char); Format.str_adr = "*"; } ; gra_fmt : g_fmt | gra_fmt g_fmt ; g_fmt : length | FROM_TO var = { Format.fr_to_v[(int) $1] = (int) $2; } | FROM_TO ICONST = { Format.fr_to_8[(int) $1] = (int) $2; } | FROM_TO LCONST = { Format.fr_to_8[(int) $1] = *((long *) $2); } | FROM_TO RCONST = { Format.fr_to_8[(int) $1] = *((double *) $2); } | WITH sconst = { if (!Format.str_len) Format.str_adr = " "; } | object ; object : data = { if (Format.data++) rc_error(20); } ; data : SYS_CONST = { RC_BYTE(prCONST); RC_WORD((int) $1); } | sys_var = { RC_SYS_VAR((int) $1, TRUE); } | tup_kwd ; tup_kwd : DOMAIN value = { switch ((int) $1) { case pushLAST: RC_BYTE(prLAST); break; case pushVALUE: RC_BYTE(prVALUE); break; case pushNEXT: RC_BYTE(prNEXT); } RC_WORD((int) $2); } ; /* expressions */ b_expr : LPAREN b_expr RPAREN | LUOP b_expr = { RC_BYTE((int) $1); } | b_expr LBOP b_expr = { RC_BYTE((int) $2); } | expr relop expr = { RC_BYTE((int) $2); } | BCONST = { RC_BYTE((int) $1); } | b_var = { RC_BYTE(pushSWITCH); RC_WORD((int) $1); } | GROUPBEGIN value = { RC_BYTE(pushLAST); RC_WORD((int) $2); RC_WORD(0); /* from */ RC_WORD(0); /* to */ RC_BYTE(pushVALUE); RC_WORD((int) $2); RC_WORD(0); /* from */ RC_WORD(0); /* to */ RC_BYTE(bdNE); } | GROUPEND value = { RC_BYTE(pushVALUE); RC_WORD((int) $2); RC_WORD(0); /* from */ RC_WORD(0); /* to */ RC_BYTE(pushNEXT); RC_WORD((int) $2); RC_WORD(0); /* from */ RC_WORD(0); /* to */ RC_BYTE(bdNE); } ; expr : LPAREN expr RPAREN | auop expr %prec unaryop = { /* skip positive sign */ if (((int) $1) == ((int) rcMIN)) RC_BYTE(rcMIN); } | expr ABOP expr = { RC_BYTE((int) $2); } | expr AUOP expr /* binary '+' and '-' */ = { if (((int) $2) == ((int) rcMIN)) RC_BYTE(rcSUB); else RC_BYTE((int) $2); } | ICONST = { if (!((int) $1)) RC_BYTE(pushNULL); else if (((int) $1) <= MAX_I1 && ((int) $1) >= MIN_I1) { RC_BYTE(push1INT); RC_BYTE((int) $1); } else { RC_BYTE(push2INT); RC_WORD((int) $1); } } | LCONST = { RC_BYTE(push4INT); RC_STR($1, sizeof (long)); } | RCONST = { RC_BYTE(pushREAL); RC_STR($1, sizeof (double)); } | sconst = { RC_BYTE(pushSTRING); RC_WORD(Format.str_len); RC_STR($1, Format.str_len); } | SYS_CONST = { RC_BYTE(pushCONST); RC_BYTE((int) $1); } | sys_var = { RC_SYS_VAR((int) $1, FALSE); } | domain = { RC_WORD((int) Format.fr_to[0]); RC_WORD((int) Format.fr_to[1]); } ; relop : EOP | IS | BDOP ; auop : AUOP %prec unaryop ; domain : dom_kwd fr_to fr_to | dom_kwd fr_to | dom_kwd ; dom_kwd : DOMAIN value = { RC_BYTE((int) $1); RC_WORD((int) $2); /* initialize Format structure */ Format.fr_to[0] = (char *) 0; Format.fr_to[1] = (char *) 0; } ; /* (SYSTEM) values and variables */ sys_var : var | PAGE = { $$ = (char *) SYS_PAGE; } | LINE = { $$ = (char *) SYS_LINE; } | ALL LINE = { $$ = (char *) SYS_ALL_LINE; } | COLUMN = { $$ = (char *) SYS_COL; } | TUPLE = { $$ = (char *) SYS_TUPL; } ; var : NVAR NVAR ICONST = { if (((int) $3) < 0 || ((int) $3) >= MAX_VAR) rc_error(6, $3); else $$ = (char *) (((int) $3) | VAR_VAR_MASK); } | NVAR ICONST = { if (((int) $2) < 0 || ((int) $2) >= MAX_VAR) rc_error(6, $2); else $$ = (char *) (((int) $2)| VAR_MASK); } ; b_var : SWITCH value = { if (((int) $2) >= MAX_BVAR) rc_error(7, $2); else $$ = $2; } ; value : ICONST = { if (((int) $1) < 0) { rc_error(8, $1); $$ = 0; } } | var ; /* KEY WORDS */ byte_kwd: FORMAT BYTE | FORMAT WORD = { $$ = $1 + 1; } | FORMAT ; do_kwd : DO | /* empty */ ; end1_kwd: ENDO | END one_kwd ; enda_kwd: ENDA | END ALL ; endc_kwd: ENDC | END CASE ; endi_kwd: ENDI | END IF ; endo_kwd: ENDO | END ; endr_kwd: ENDR | END REPEAT ; endw_kwd: ENDW | END WHILE ; for1_kwd: FOR one_kwd do_kwd = { RC_BYTE(rcONE); } ; fora_kwd: FOR ALL do_kwd = { RC_BYTE(rcALL); $$ = R_rc; } ; one_kwd : ONE | /* empty */ ; %% # include "rc_tab.y"