📄 tclgetdate.y
字号:
/* * tclGetDate.y -- * * Contains yacc grammar for parsing date and time strings. * The output of this file should be the file tclDate.c which * is used directly in the Tcl sources. * * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans. * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclGetDate.y,v 1.18 2001/10/18 20:20:28 hobbs Exp $ */%{/* * tclDate.c -- * * This file is generated from a yacc grammar defined in * the file tclGetDate.y. It should not be edited directly. * * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans. * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCSID */#include "tclInt.h"#include "tclPort.h"#if defined(MAC_TCL) && !defined(TCL_MAC_USE_MSL_EPOCH)# define EPOCH 1904# define START_OF_TIME 1904# define END_OF_TIME 2039#else# define EPOCH 1970# define START_OF_TIME 1902# define END_OF_TIME 2037#endif/* * The offset of tm_year of struct tm returned by localtime, gmtime, etc. * I don't know how universal this is; K&R II, the NetBSD manpages, and * ../compat/strftime.c all agree that tm_year is the year-1900. However, * some systems may have a different value. This #define should be the * same as in ../compat/strftime.c. */#define TM_YEAR_BASE 1900#define HOUR(x) ((int) (60 * x))#define SECSPERDAY (24L * 60L * 60L)#define IsLeapYear(x) ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))/* * An entry in the lexical lookup table. */typedef struct _TABLE { char *name; int type; time_t value;} TABLE;/* * Daylight-savings mode: on, off, or not yet known. */typedef enum _DSTMODE { DSTon, DSToff, DSTmaybe} DSTMODE;/* * Meridian: am, pm, or 24-hour style. */typedef enum _MERIDIAN { MERam, MERpm, MER24} MERIDIAN;/* * Global variables. We could get rid of most of these by using a good * union as the yacc stack. (This routine was originally written before * yacc had the %union construct.) Maybe someday; right now we only use * the %union very rarely. */static char *yyInput;static DSTMODE yyDSTmode;static time_t yyDayOrdinal;static time_t yyDayNumber;static time_t yyMonthOrdinal;static int yyHaveDate;static int yyHaveDay;static int yyHaveOrdinalMonth;static int yyHaveRel;static int yyHaveTime;static int yyHaveZone;static time_t yyTimezone;static time_t yyDay;static time_t yyHour;static time_t yyMinutes;static time_t yyMonth;static time_t yySeconds;static time_t yyYear;static MERIDIAN yyMeridian;static time_t yyRelMonth;static time_t yyRelDay;static time_t yyRelSeconds;static time_t *yyRelPointer;/* * Prototypes of internal functions. */static void yyerror _ANSI_ARGS_((char *s));static time_t ToSeconds _ANSI_ARGS_((time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian));static int Convert _ANSI_ARGS_((time_t Month, time_t Day, time_t Year, time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridia, DSTMODE DSTmode, time_t *TimePtr));static time_t DSTcorrect _ANSI_ARGS_((time_t Start, time_t Future));static time_t NamedDay _ANSI_ARGS_((time_t Start, time_t DayOrdinal, time_t DayNumber));static time_t NamedMonth _ANSI_ARGS_((time_t Start, time_t MonthOrdinal, time_t MonthNumber));static int RelativeMonth _ANSI_ARGS_((time_t Start, time_t RelMonth, time_t *TimePtr));static int RelativeDay _ANSI_ARGS_((time_t Start, time_t RelDay, time_t *TimePtr));static int LookupWord _ANSI_ARGS_((char *buff));static int yylex _ANSI_ARGS_((void));intyyparse _ANSI_ARGS_((void));%}%union { time_t Number; enum _MERIDIAN Meridian;}%token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT%token tSTARDATE tSEC_UNIT tSNUMBER tUNUMBER tZONE tEPOCH tDST tISOBASE%token tDAY_UNIT tNEXT%type <Number> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT tDST%type <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE tISOBASE tDAY_UNIT%type <Number> unit sign tNEXT tSTARDATE%type <Meridian> tMERIDIAN o_merid%%spec : /* NULL */ | spec item ;item : time { yyHaveTime++; } | zone { yyHaveZone++; } | date { yyHaveDate++; } | ordMonth { yyHaveOrdinalMonth++; } | day { yyHaveDay++; } | relspec { yyHaveRel++; } | iso { yyHaveTime++; yyHaveDate++; } | trek { yyHaveTime++; yyHaveDate++; yyHaveRel++; } | number ;time : tUNUMBER tMERIDIAN { yyHour = $1; yyMinutes = 0; yySeconds = 0; yyMeridian = $2; } | tUNUMBER ':' tUNUMBER o_merid { yyHour = $1; yyMinutes = $3; yySeconds = 0; yyMeridian = $4; } | tUNUMBER ':' tUNUMBER '-' tUNUMBER { yyHour = $1; yyMinutes = $3; yyMeridian = MER24; yyDSTmode = DSToff; yyTimezone = ($5 % 100 + ($5 / 100) * 60); } | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid { yyHour = $1; yyMinutes = $3; yySeconds = $5; yyMeridian = $6; } | tUNUMBER ':' tUNUMBER ':' tUNUMBER '-' tUNUMBER { yyHour = $1; yyMinutes = $3; yySeconds = $5; yyMeridian = MER24; yyDSTmode = DSToff; yyTimezone = ($7 % 100 + ($7 / 100) * 60); } ;zone : tZONE tDST { yyTimezone = $1; yyDSTmode = DSTon; } | tZONE { yyTimezone = $1; yyDSTmode = DSToff; } | tDAYZONE { yyTimezone = $1; yyDSTmode = DSTon; } ;day : tDAY { yyDayOrdinal = 1; yyDayNumber = $1; } | tDAY ',' { yyDayOrdinal = 1; yyDayNumber = $1; } | tUNUMBER tDAY { yyDayOrdinal = $1; yyDayNumber = $2; } | sign tUNUMBER tDAY { yyDayOrdinal = $1 * $2; yyDayNumber = $3; } | tNEXT tDAY { yyDayOrdinal = 2; yyDayNumber = $2; } ;date : tUNUMBER '/' tUNUMBER { yyMonth = $1; yyDay = $3; } | tUNUMBER '/' tUNUMBER '/' tUNUMBER { yyMonth = $1; yyDay = $3; yyYear = $5; } | tISOBASE { yyYear = $1 / 10000; yyMonth = ($1 % 10000)/100; yyDay = $1 % 100; } | tUNUMBER '-' tMONTH '-' tUNUMBER { yyDay = $1; yyMonth = $3; yyYear = $5; } | tUNUMBER '-' tUNUMBER '-' tUNUMBER { yyMonth = $3; yyDay = $5; yyYear = $1; } | tMONTH tUNUMBER { yyMonth = $1; yyDay = $2; } | tMONTH tUNUMBER ',' tUNUMBER { yyMonth = $1; yyDay = $2; yyYear = $4; } | tUNUMBER tMONTH { yyMonth = $2; yyDay = $1; } | tEPOCH { yyMonth = 1; yyDay = 1; yyYear = EPOCH; } | tUNUMBER tMONTH tUNUMBER { yyMonth = $2; yyDay = $1; yyYear = $3; } ;ordMonth: tNEXT tMONTH { yyMonthOrdinal = 1; yyMonth = $2; } | tNEXT tUNUMBER tMONTH { yyMonthOrdinal = $2; yyMonth = $3; } ;iso : tISOBASE tZONE tISOBASE { if ($2 != HOUR(- 7)) YYABORT; yyYear = $1 / 10000; yyMonth = ($1 % 10000)/100; yyDay = $1 % 100; yyHour = $3 / 10000; yyMinutes = ($3 % 10000)/100; yySeconds = $3 % 100; } | tISOBASE tZONE tUNUMBER ':' tUNUMBER ':' tUNUMBER { if ($2 != HOUR(- 7)) YYABORT; yyYear = $1 / 10000; yyMonth = ($1 % 10000)/100; yyDay = $1 % 100; yyHour = $3; yyMinutes = $5; yySeconds = $7; } | tISOBASE tISOBASE { yyYear = $1 / 10000; yyMonth = ($1 % 10000)/100; yyDay = $1 % 100; yyHour = $2 / 10000; yyMinutes = ($2 % 10000)/100; yySeconds = $2 % 100; } ;trek : tSTARDATE tUNUMBER '.' tUNUMBER { /* * Offset computed year by -377 so that the returned years will * be in a range accessible with a 32 bit clock seconds value */ yyYear = $2/1000 + 2323 - 377; yyDay = 1; yyMonth = 1; yyRelDay += (($2%1000)*(365 + IsLeapYear(yyYear)))/1000; yyRelSeconds += $4 * 144 * 60; } ;relspec : relunits tAGO { yyRelSeconds *= -1; yyRelMonth *= -1; yyRelDay *= -1; } | relunits ;relunits : sign tUNUMBER unit { *yyRelPointer += $1 * $2 * $3; } | tUNUMBER unit { *yyRelPointer += $1 * $2; } | tNEXT unit { *yyRelPointer += $2; } | tNEXT tUNUMBER unit { *yyRelPointer += $2 * $3; } | unit { *yyRelPointer += $1; } ;sign : '-' { $$ = -1; } | '+' { $$ = 1; } ;unit : tSEC_UNIT { $$ = $1; yyRelPointer = &yyRelSeconds; } | tDAY_UNIT { $$ = $1; yyRelPointer = &yyRelDay; } | tMONTH_UNIT { $$ = $1; yyRelPointer = &yyRelMonth; } ;number : tUNUMBER { if (yyHaveTime && yyHaveDate && !yyHaveRel) { yyYear = $1; } else { yyHaveTime++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -