📄 getdate.y
字号:
%{
/*
** Originally written by Steven M. Bellovin <smb@research.att.com> while
** at the University of North Carolina at Chapel Hill. Later tweaked by
** a couple of people on Usenet. Completely overhauled by Rich $alz
** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
**
** Major hack to coerce it into use with the Equivalence Portable
** Windows Library.
**
** This grammar has 10 shift/reduce conflicts.
**
** This code is in the public domain and has no copyright.
*/
/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
/* SUPPRESS 288 on yyerrlab *//* Label unused */
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#ifndef EOF
#include <stdio.h>
#endif
#ifdef _WIN32
#ifdef _MSC_VER
#pragma warning(disable:4131 4701 4996)
#endif
#define STDAPICALLTYPE __stdcall
#define MSDOS
#else
#define STDAPICALLTYPE
#endif
extern int STDAPICALLTYPE PTimeGetChar(void * stream);
extern void STDAPICALLTYPE PTimeUngetChar(void * stream, int c);
int STDAPICALLTYPE PTimeGetDateOrder();
int STDAPICALLTYPE PTimeIsMonthName(const char *, int, int);
int STDAPICALLTYPE PTimeIsDayName(const char *, int, int);
#define EPOCH 1970
#define HOUR(x) ((time_t)(x) * 60)
#define SECSPERDAY (24L * 60L * 60L)
/*
** 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.
*/
struct Variables {
void *yyInput;
DSTMODE yyDSTmode;
time_t yyDayOrdinal;
time_t yyDayNumber;
int yyHaveDate;
int yyHaveDay;
int yyHaveRel;
int yyHaveTime;
int yyHaveZone;
time_t yyTimezone;
time_t yyDay;
time_t yyHour;
time_t yyMinutes;
time_t yyMonth;
time_t yySeconds;
time_t yyYear;
MERIDIAN yyMeridian;
time_t yyRelMonth;
time_t yyRelSeconds;
};
#define VARIABLE ((struct Variables*)parseParam)
#define YYPURE 1
#define YYLEX_PARAM VARIABLE->yyInput
#define YYPARSE_PARAM parseParam
#define yyparse PTime_yyparse
#define yylex PTime_yylex
#define yyerror PTime_yyerror
static int yyparse(void *);
static int yylex();
#ifdef __GNUC__
static int yyerror();
#else
static void yyerror();
#endif
static void SetPossibleDate(struct Variables*, time_t, time_t, time_t);
%}
%pure_parser
%union {
time_t Number;
enum _MERIDIAN Meridian;
}
%token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
%token tSNUMBER tUNUMBER t4DIGITNUMBER t6DIGITNUMBER
%token tSEC_UNIT tZONE tMILZONE tDST
%type <Number> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
%type <Number> tSNUMBER tUNUMBER t4DIGITNUMBER t6DIGITNUMBER unumber
%type <Number> tSEC_UNIT tZONE tMILZONE
%type <Meridian> tMERIDIAN o_merid
%%
spec : /* NULL */
| spec item
;
item : time {
VARIABLE->yyHaveTime++;
}
| zone {
VARIABLE->yyHaveZone++;
}
| date {
VARIABLE->yyHaveDate++;
}
| day {
VARIABLE->yyHaveDay++;
}
| rel {
VARIABLE->yyHaveRel++;
}
| number
;
time : tUNUMBER tMERIDIAN {
VARIABLE->yyHour = $1;
VARIABLE->yyMinutes = 0;
VARIABLE->yySeconds = 0;
VARIABLE->yyMeridian = $2;
}
| t4DIGITNUMBER tSNUMBER {
VARIABLE->yyHour = $1/100;
VARIABLE->yyMinutes = $1%100;
VARIABLE->yySeconds = 0;
VARIABLE->yyMeridian = MER24;
VARIABLE->yyDSTmode = DSToff;
VARIABLE->yyTimezone = - ($2 % 100 + ($2 / 100) * 60);
}
| t6DIGITNUMBER tSNUMBER {
VARIABLE->yyHour = $1/10000;
VARIABLE->yyMinutes = ($1/100)%100;
VARIABLE->yySeconds = $1 % 100;
VARIABLE->yyMeridian = MER24;
VARIABLE->yyDSTmode = DSToff;
VARIABLE->yyTimezone = - ($2 % 100 + ($2 / 100) * 60);
}
| unumber ':' unumber o_merid {
VARIABLE->yyHour = $1;
VARIABLE->yyMinutes = $3;
VARIABLE->yySeconds = 0;
VARIABLE->yyMeridian = $4;
}
| unumber ':' unumber tSNUMBER {
VARIABLE->yyHour = $1;
VARIABLE->yyMinutes = $3;
VARIABLE->yyMeridian = MER24;
VARIABLE->yyDSTmode = DSToff;
VARIABLE->yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
}
| unumber ':' unumber ':' unumber o_merid {
VARIABLE->yyHour = $1;
VARIABLE->yyMinutes = $3;
VARIABLE->yySeconds = $5;
VARIABLE->yyMeridian = $6;
}
| unumber ':' unumber ':' unumber tSNUMBER {
VARIABLE->yyHour = $1;
VARIABLE->yyMinutes = $3;
VARIABLE->yySeconds = $5;
VARIABLE->yyMeridian = MER24;
VARIABLE->yyDSTmode = DSToff;
VARIABLE->yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
}
;
zone : tZONE {
VARIABLE->yyTimezone = $1;
VARIABLE->yyDSTmode = DSToff;
}
| tDAYZONE {
VARIABLE->yyTimezone = $1;
VARIABLE->yyDSTmode = DSTon;
}
|
tZONE tDST {
VARIABLE->yyTimezone = $1;
VARIABLE->yyDSTmode = DSTon;
}
| tMILZONE {
if (VARIABLE->yyHaveTime > 0) {
VARIABLE->yyTimezone = $1;
VARIABLE->yyDSTmode = DSToff;
}
else
VARIABLE->yyHaveZone--;
}
;
day : tDAY {
VARIABLE->yyDayOrdinal = 1;
VARIABLE->yyDayNumber = $1;
}
| tDAY ',' {
VARIABLE->yyDayOrdinal = 1;
VARIABLE->yyDayNumber = $1;
}
| unumber tDAY {
VARIABLE->yyDayOrdinal = $1;
VARIABLE->yyDayNumber = $2;
}
;
date : unumber '/' unumber {
SetPossibleDate(VARIABLE, $1, $3, VARIABLE->yyYear);
}
| unumber '/' unumber '/' unumber {
SetPossibleDate(VARIABLE, $1, $3, $5);
}
| unumber tSNUMBER tSNUMBER {
/* ISO 8601 format. yyyy-mm-dd. */
if ($1 > 31) {
VARIABLE->yyYear = $1;
VARIABLE->yyMonth = -$2;
VARIABLE->yyDay = -$3;
}
else
SetPossibleDate(VARIABLE, $1, -$2, -$3);
}
| unumber tMONTH tSNUMBER {
/* e.g. 17-JUN-1992. */
VARIABLE->yyDay = $1;
VARIABLE->yyMonth = $2;
VARIABLE->yyYear = -$3;
}
| tMONTH unumber {
VARIABLE->yyMonth = $1;
VARIABLE->yyDay = $2;
}
| tMONTH unumber ',' unumber {
VARIABLE->yyMonth = $1;
VARIABLE->yyDay = $2;
VARIABLE->yyYear = $4;
}
| unumber tMONTH {
VARIABLE->yyMonth = $2;
VARIABLE->yyDay = $1;
}
| unumber tMONTH unumber {
VARIABLE->yyMonth = $2;
VARIABLE->yyDay = $1;
VARIABLE->yyYear = $3;
}
;
rel : relunit tAGO {
VARIABLE->yyRelSeconds = -VARIABLE->yyRelSeconds;
VARIABLE->yyRelMonth = -VARIABLE->yyRelMonth;
}
| relunit
;
relunit : unumber tMINUTE_UNIT {
VARIABLE->yyRelSeconds += $1 * $2 * 60L;
}
| tSNUMBER tMINUTE_UNIT {
VARIABLE->yyRelSeconds += $1 * $2 * 60L;
}
| tMINUTE_UNIT {
VARIABLE->yyRelSeconds += $1 * 60L;
}
| tSNUMBER tSEC_UNIT {
VARIABLE->yyRelSeconds += $1;
}
| unumber tSEC_UNIT {
VARIABLE->yyRelSeconds += $1;
}
| tSEC_UNIT {
VARIABLE->yyRelSeconds++;
}
| tSNUMBER tMONTH_UNIT {
VARIABLE->yyRelMonth += $1 * $2;
}
| unumber tMONTH_UNIT {
VARIABLE->yyRelMonth += $1 * $2;
}
| tMONTH_UNIT {
VARIABLE->yyRelMonth += $1;
}
;
unumber : tUNUMBER {
$$ = $1;
}
| t4DIGITNUMBER {
$$ = $1;
}
| t6DIGITNUMBER {
$$ = $1;
}
;
number : tUNUMBER {
if (VARIABLE->yyHaveTime && VARIABLE->yyHaveDate && !VARIABLE->yyHaveRel)
VARIABLE->yyYear = $1;
else {
if($1>240000) {
VARIABLE->yyHaveDate++;
VARIABLE->yyDay= ($1)%100;
VARIABLE->yyMonth= ($1/100)%100;
VARIABLE->yyYear = $1/10000;
}
else {
VARIABLE->yyHaveTime++;
if ($1 < 10000) {
VARIABLE->yyHour = $1 / 100;
VARIABLE->yyMinutes = $1 % 100;
VARIABLE->yySeconds = 0;
}
else {
VARIABLE->yyHour = $1/10000;
VARIABLE->yyMinutes = ($1/100)%100;
VARIABLE->yySeconds = $1 % 100;
}
VARIABLE->yyMeridian = MER24;
}
}
}
| t4DIGITNUMBER {
if (VARIABLE->yyHaveTime && VARIABLE->yyHaveDate && !VARIABLE->yyHaveRel)
VARIABLE->yyYear = $1;
else {
VARIABLE->yyHaveTime++;
VARIABLE->yyHour = $1/100;
VARIABLE->yyMinutes = $1%100;
VARIABLE->yySeconds = 0;
VARIABLE->yyMeridian = MER24;
}
}
| t6DIGITNUMBER {
if (!VARIABLE->yyHaveDate && $1>240000) {
VARIABLE->yyHaveDate++;
VARIABLE->yyDay= ($1)%100;
VARIABLE->yyMonth= ($1/100)%100;
VARIABLE->yyYear = $1/10000;
}
else if (!VARIABLE->yyHaveTime) {
VARIABLE->yyHaveTime++;
VARIABLE->yyHour = $1/10000;
VARIABLE->yyMinutes = ($1/100)%100;
VARIABLE->yySeconds = $1 % 100;
VARIABLE->yyMeridian = MER24;
}
}
;
o_merid : /* NULL */ {
$$ = MER24;
}
| tMERIDIAN {
$$ = $1;
}
;
%%
/* Month and day table. */
static TABLE const MonthDayTable[] = {
{ "january", tMONTH, 1 },
{ "february", tMONTH, 2 },
{ "march", tMONTH, 3 },
{ "april", tMONTH, 4 },
{ "may", tMONTH, 5 },
{ "june", tMONTH, 6 },
{ "july", tMONTH, 7 },
{ "august", tMONTH, 8 },
{ "september", tMONTH, 9 },
{ "sept", tMONTH, 9 },
{ "october", tMONTH, 10 },
{ "november", tMONTH, 11 },
{ "december", tMONTH, 12 },
{ "sunday", tDAY, 0 },
{ "monday", tDAY, 1 },
{ "tuesday", tDAY, 2 },
{ "tues", tDAY, 2 },
{ "wednesday", tDAY, 3 },
{ "wednes", tDAY, 3 },
{ "thursday", tDAY, 4 },
{ "thur", tDAY, 4 },
{ "thurs", tDAY, 4 },
{ "friday", tDAY, 5 },
{ "saturday", tDAY, 6 },
{ NULL }
};
/* Time units table. */
static TABLE const UnitsTable[] = {
{ "year", tMONTH_UNIT, 12 },
{ "month", tMONTH_UNIT, 1 },
{ "fortnight", tMINUTE_UNIT, 14 * 24 * 60 },
{ "week", tMINUTE_UNIT, 7 * 24 * 60 },
{ "day", tMINUTE_UNIT, 1 * 24 * 60 },
{ "hour", tMINUTE_UNIT, 60 },
{ "minute", tMINUTE_UNIT, 1 },
{ "min", tMINUTE_UNIT, 1 },
{ "second", tSEC_UNIT, 1 },
{ "sec", tSEC_UNIT, 1 },
{ NULL }
};
/* Assorted relative-time words. */
static TABLE const OtherTable[] = {
{ "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 },
{ "yesterday", tMINUTE_UNIT, -1 * 24 * 60 },
{ "today", tMINUTE_UNIT, 0 },
{ "now", tMINUTE_UNIT, 0 },
{ "last", tUNUMBER, -1 },
{ "this", tMINUTE_UNIT, 0 },
{ "next", tUNUMBER, 2 },
{ "first", tUNUMBER, 1 },
/* { "second", tUNUMBER, 2 }, */
{ "third", tUNUMBER, 3 },
{ "fourth", tUNUMBER, 4 },
{ "fifth", tUNUMBER, 5 },
{ "sixth", tUNUMBER, 6 },
{ "seventh", tUNUMBER, 7 },
{ "eighth", tUNUMBER, 8 },
{ "ninth", tUNUMBER, 9 },
{ "tenth", tUNUMBER, 10 },
{ "eleventh", tUNUMBER, 11 },
{ "twelfth", tUNUMBER, 12 },
{ "ago", tAGO, 1 },
{ NULL }
};
/* The timezone table. */
/* Some of these are commented out because a time_t can't store a float. */
static TABLE const TimezoneTable[] = {
{ "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */
{ "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */
{ "utc", tZONE, HOUR( 0) },
{ "wet", tZONE, HOUR( 0) }, /* Western European */
{ "bst", tDAYZONE, HOUR( 0) }, /* British Summer */
{ "wat", tZONE, HOUR( 1) }, /* West Africa */
{ "at", tZONE, HOUR( 2) }, /* Azores */
#if 0
/* For completeness. BST is also British Summer, and GST is
* also Guam Standard. */
{ "bst", tZONE, HOUR( 3) }, /* Brazil Standard */
{ "gst", tZONE, HOUR( 3) }, /* Greenland Standard */
#endif
#if 0
{ "nft", tZONE, HOUR(3.5) }, /* Newfoundland */
{ "nst", tZONE, HOUR(3.5) }, /* Newfoundland Standard */
{ "ndt", tDAYZONE, HOUR(3.5) }, /* Newfoundland Daylight */
#endif
{ "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */
{ "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */
{ "est", tZONE, HOUR( 5) }, /* Eastern Standard */
{ "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */
{ "cst", tZONE, HOUR( 6) }, /* Central Standard */
{ "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */
{ "mst", tZONE, HOUR( 7) }, /* Mountain Standard */
{ "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */
{ "pst", tZONE, HOUR( 8) }, /* Pacific Standard */
{ "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */
{ "yst", tZONE, HOUR( 9) }, /* Yukon Standard */
{ "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */
{ "hst", tZONE, HOUR(10) }, /* Hawaii Standard */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -