⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gram.y

📁 这是一个银行业务上用来计算日期时间的工具包
💻 Y
字号:
%{/* * $Id: //pentools/main/datemath/gram.y#3 $ * * written by:  Stephen J. Friedl *              Software Consultant *              Tustin, California USA *              steve@unixwiz.net / www.unixwiz.net * *	This is the grammar for the datemath program.  It uses a long *	yylval to contain the actual dates (either yymm or Julian),  *	and the return values from the scanner are the tokens shown *	below. */#include	<stdio.h>#include	<stdlib.h>#include	"defs.h"#define		pr		(void)printfstatic int	formatted_output = FALSE;static void bogus 	 ( char const * );static void print_jdate  ( long );static void print_num    ( long );static void print_yymm   ( int  );static long yymm_diff    ( long, long );static long day_jdate 	 ( long );static long fday_jdate 	 ( long );static long fday_yymm 	 ( int  );static long lday_jdate 	 ( long );static long lday_yymm 	 ( int  );static long month_jdate  ( long );static long month_yymm 	 ( int  );static long ndays_jdate  ( long );static long ndays_yymm 	 ( int  );static long year_jdate 	 ( long );static long year_yymm 	 ( int  );static short	mdy[3];		/* for use by any function that needs it */static void cannot_add(void);%}%token	PLUS	MINUS	TIMES	DIV	MOD%token	MMDDYY	YYMM	INTEGER%token	LPAREN	RPAREN	%token	FDAY	LDAY	KYYMM	DOY%token	NDAYS	YEAR	MONTH	DAY	WEEKS%left	TIMES DIV MOD%left	PLUS MINUS%%expr :		mmddyy				{ print_jdate($1);	}	|	yymm				{ print_yymm($1);	}	|	num				{ print_num($1);	}	|	bogus				/* error checking */	;/*---------------------------------------------------------------------- * this is an attempt to catch errors where the user does things that * don't make any sense (i.e., semantic errors).  This is not intended * to be an exhaustive list, but since they might be common we try to * have reasonable error reporting. */bogus	:	FDAY LPAREN num RPAREN		{ bogus("fday");	}	| 	LDAY LPAREN num RPAREN		{ bogus("lday");	}	|	NDAYS LPAREN num RPAREN		{ bogus("ndays");	}	|	MONTH LPAREN num RPAREN		{ bogus("month");	}	|	DAY LPAREN num RPAREN		{ bogus("day");		}	|	YEAR LPAREN num RPAREN		{ bogus("year");	}	|	mmddyy PLUS mmddyy		{ cannot_add();		}	|	mmddyy PLUS yymm  		{ cannot_add();		}	|	yymm   PLUS mmddyy		{ cannot_add();		}	|	yymm   PLUS yymm		{ cannot_add();		}	|	yymm MINUS mmddyy		  { die("can't subtract mmddyy dates from yymm dates"); }	|	mmddyy MINUS yymm		  { die("can't subtract yymm dates from mmddyy dates"); }	;/*---------------------------------------------------------------------- * This is the symbol for anything that can evaluate to a Julian date * (internally, a long). */mmddyy	:	MMDDYY				{ $$ = $1 ; 		}	|	num PLUS  mmddyy		{ $$ = $1 + $3 ; 	}	|	mmddyy PLUS  num		{ $$ = $1 + $3 ; 	}	|	mmddyy MINUS num		{ $$ = $1 - $3 ; 	}	|	FDAY LPAREN mmddyy RPAREN	{ $$ = fday_jdate($3);	}	|	LDAY LPAREN mmddyy RPAREN	{ $$ = lday_jdate($3);	}	|	FDAY LPAREN yymm   RPAREN	{ $$ = fday_yymm($3);	}	|	LDAY LPAREN yymm   RPAREN	{ $$ = lday_yymm($3);	}	|	LPAREN mmddyy RPAREN		{ $$ = $2; }	;/*---------------------------------------------------------------------- * These are all expressions that can yield a yymm date. */yymm 	:	YYMM				{ $$ = $1 ;		  }	|	yymm PLUS  num			{ $$ = yymm_add($1,  $3); }	|	num PLUS  yymm			{ $$ = yymm_add($3,  $1); }	|	yymm MINUS num			{ $$ = yymm_add($1, -$3); }	|	KYYMM LPAREN mmddyy RPAREN 	{ $$ = jultoyymm($3); 	  }	|	KYYMM LPAREN yymm   RPAREN 	{ $$ = $3;		  }	|	LPAREN yymm RPAREN		{ $$ = $2 ; 		  }	;/*---------------------------------------------------------------------- * These are all the expressions that can yield a numeric value. * We allow some limited normal math (+-* /) here because it was * easy, but expr(1) is probably best used for these tasks. */num	:	INTEGER				{ $$ = $1 ; 		  }	|	mmddyy MINUS mmddyy		{ $$ = $1 - $3;		  }	|	yymm   MINUS yymm		{ $$ = yymm_diff($1, $3); }	|	INTEGER WEEKS			{ $$ = $2 * 7; }	|	NDAYS LPAREN yymm   RPAREN	{ $$ = ndays_yymm($3);    }	|	NDAYS LPAREN mmddyy RPAREN	{ $$ = ndays_jdate($3);	  }	|	MONTH LPAREN mmddyy RPAREN	{ $$ = month_jdate($3); }	|	YEAR  LPAREN mmddyy RPAREN	{ $$ = year_jdate ($3);	}	|	DAY   LPAREN mmddyy RPAREN	{ $$ = day_jdate  ($3);	}	|	MONTH LPAREN yymm   RPAREN	{ $$ = month_yymm ($3);	}	|	YEAR  LPAREN yymm   RPAREN	{ $$ = year_yymm  ($3);	}	|	DAY   LPAREN yymm   RPAREN				{ die("can't take \"day\" of yymm date"); }	|	num MINUS num			{ $$ = $1 - $3 ; 	}	|	num PLUS  num			{ $$ = $1 + $3 ; 	}	|	num TIMES num			{ $$ = $1 * $3 ; 	}	|	num DIV   num		{ $$ = ($3 == 0) ? 0 : ($1 / $3); }	|	num MOD   num		{ $$ = ($3 == 0) ? 0 : ($1 % $3); }	|	LPAREN num RPAREN		{ $$ = $2 ; 		}	;%%/* * yymm_diff() * *	Given two yymm dates, return their difference in months. *	Do this by converting both to the number of months since *	1/1/1900 and subtracting. */static longyymm_diff(long yymm1, long yymm2){long	y1, y2;	y1 = ((yymm1 / 100) * 12) + (yymm1 % 100);	y2 = ((yymm2 / 100) * 12) + (yymm2 % 100);	return(y1 - y2);}/* * print_jdate() * *	Given a Julian date, print it in the format requested by the *	user. We can print either two-digit or four-digit dates, and *	we handle this by simply lopping off the century part for two- *	digit dates. Printing the year with %02d works correctly for *	years 0..9, but it correctly expands to four digits when needed. */static void print_jdate(long jdate){	if (rjulmdy(jdate, mdy) < 0)		die("cannot convert date to ASCII (this should not happen)");	if ( year_digits == 2 )		mdy[YY] %= 100;	if ( collate_order )	{		printf("%02d/%02d/%02d\n", mdy[YY], mdy[MM], mdy[DD]);	}	else	{		printf("%02d/%02d/%02d\n", mdy[MM], mdy[DD], mdy[YY]);	}}/* * print_num() * *	Given an number, print it in the normal method (just digits). */static void print_num(long num){	pr("%ld\n", num);}/* * print_yymm() * *	Given a yymm date, print it.  This routine has support for *	output as either mm/yy or yymm formats, but there is currently *	no way to set the formatted_output flag. */static void print_yymm(int yymm){	if (formatted_output)		pr("%02d/%02d\n", yymm % 100, yymm / 100);	else		pr("%04d\n", yymm);}/* * fday_jdate() * *	Given a Julian date, return the Julian date of the *	first day of the month. */static long fday_jdate(long jdate){	return(yymmtojul(jultoyymm(jdate), 0));}/* * fday_yymm() * *	Given a yymm date, return the Julian date of the *	first day of the month. */static long fday_yymm(int yymm){	return(yymmtojul(yymm, 0));}/* * lday_jdate() * *	Given a Julian date, return the Julian date of the *	last day of the month. */static long lday_jdate(long jdate){	return(yymmtojul(jultoyymm(jdate), 1));}/* * lday_yymm() * *	Given a yymm date, return the Julian date of the *	last day of the month. */static long lday_yymm(int yymm){	return(yymmtojul(yymm, 1));}/* * ndays_yymm() * *	Given a YYMM date, return the number of days in this month. */static long ndays_yymm(int yymm){	return daysinyymm(yymm);}/* * ndays_jdate() * *	Given a Julian date, return the number of days in this month. */static long ndays_jdate(long jdate){	return(daysinyymm(jultoyymm(jdate)));}static long month_yymm(int yymm){	return(yymm % 100);}static long year_yymm(int yymm){	return((yymm / 100) + 1900);}static long year_jdate(long jdate){	rjulmdy(jdate, mdy);	return mdy[YY];}static long month_jdate(long jdate){	rjulmdy(jdate, mdy);	return(mdy[MM]);}static long day_jdate(long jdate){	rjulmdy(jdate, mdy);	return(mdy[DD]);}/* * bogus() * *	Given a string that is the name of a date function, print *	an error message saying that we can't apply this function *	to an integer.  Then die. */static void bogus(const char *str){	die("can't take \"%s\" of a numeric expression!", str);}static void cannot_add(void){	die("Adding dates doesn't make any sense!");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -