Improved time parsing
This commit is contained in:
parent
12f9ddbb95
commit
176b3044e3
4 changed files with 87 additions and 83 deletions
|
|
@ -34,3 +34,9 @@ February 02
|
||||||
February-02
|
February-02
|
||||||
Feb 02, 2002
|
Feb 02, 2002
|
||||||
February 02, 2002
|
February 02, 2002
|
||||||
|
2002-02-02 12:00:00
|
||||||
|
2002-02-02 12:00:00 AM
|
||||||
|
2002-02-02 12:00 AM
|
||||||
|
2002-02-02 12:00AM
|
||||||
|
2002-02-02 12p
|
||||||
|
2002-02-02 12a
|
||||||
|
|
|
||||||
71
parsetime.h
71
parsetime.h
|
|
@ -1,67 +1,6 @@
|
||||||
/* A Bison parser, made by GNU Bison 2.3. */
|
#define TOK_FOURNUM 257
|
||||||
|
#define TOK_TWONUM 258
|
||||||
/* Skeleton interface for Bison's Yacc-like parsers in C
|
#define TOK_ONENUM 259
|
||||||
|
#define TOK_MONTH 260
|
||||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
#define TOK_AMPM 261
|
||||||
Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2, or (at your option)
|
|
||||||
any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
||||||
Boston, MA 02110-1301, USA. */
|
|
||||||
|
|
||||||
/* As a special exception, you may create a larger work that contains
|
|
||||||
part or all of the Bison parser skeleton and distribute that work
|
|
||||||
under terms of your choice, so long as that work isn't itself a
|
|
||||||
parser generator using the skeleton or a modified version thereof
|
|
||||||
as a parser skeleton. Alternatively, if you modify or redistribute
|
|
||||||
the parser skeleton itself, you may (at your option) remove this
|
|
||||||
special exception, which will cause the skeleton and the resulting
|
|
||||||
Bison output files to be licensed under the GNU General Public
|
|
||||||
License without this special exception.
|
|
||||||
|
|
||||||
This special exception was added by the Free Software Foundation in
|
|
||||||
version 2.2 of Bison. */
|
|
||||||
|
|
||||||
/* Tokens. */
|
|
||||||
#ifndef YYTOKENTYPE
|
|
||||||
# define YYTOKENTYPE
|
|
||||||
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
|
||||||
know about them. */
|
|
||||||
enum yytokentype {
|
|
||||||
TOK_FOURNUM = 258,
|
|
||||||
TOK_TWONUM = 259,
|
|
||||||
TOK_ONENUM = 260,
|
|
||||||
TOK_MONTH = 261,
|
|
||||||
TOK_SPACE = 262
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
/* Tokens. */
|
|
||||||
#define TOK_FOURNUM 258
|
|
||||||
#define TOK_TWONUM 259
|
|
||||||
#define TOK_ONENUM 260
|
|
||||||
#define TOK_MONTH 261
|
|
||||||
#define TOK_SPACE 262
|
#define TOK_SPACE 262
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
|
||||||
typedef int YYSTYPE;
|
|
||||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
|
||||||
# define YYSTYPE_IS_DECLARED 1
|
|
||||||
# define YYSTYPE_IS_TRIVIAL 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern YYSTYPE yylval;
|
|
||||||
|
|
||||||
|
|
|
||||||
88
parsetime.yy
88
parsetime.yy
|
|
@ -9,6 +9,8 @@ static struct std::tm * timeval;
|
||||||
namespace {
|
namespace {
|
||||||
boost::posix_time::ptime moment;
|
boost::posix_time::ptime moment;
|
||||||
|
|
||||||
|
struct time_to_leave : std::exception {};
|
||||||
|
|
||||||
yyFlexLexer * lexer;
|
yyFlexLexer * lexer;
|
||||||
|
|
||||||
inline void yyerror(const char *str) {
|
inline void yyerror(const char *str) {
|
||||||
|
|
@ -23,21 +25,21 @@ namespace {
|
||||||
{
|
{
|
||||||
switch (std::toupper(name[0])) {
|
switch (std::toupper(name[0])) {
|
||||||
case 'J':
|
case 'J':
|
||||||
if (name[1] == std::tolower('a'))
|
if (std::tolower(name[1]) == 'a')
|
||||||
return 1;
|
return 1;
|
||||||
else if (name[2] == std::tolower('n'))
|
else if (std::tolower(name[2]) == 'n')
|
||||||
return 6;
|
return 6;
|
||||||
else
|
else
|
||||||
return 7;
|
return 7;
|
||||||
case 'F':
|
case 'F':
|
||||||
return 2;
|
return 2;
|
||||||
case 'M':
|
case 'M':
|
||||||
if (name[2] == std::tolower('r'))
|
if (std::tolower(name[2]) == 'r')
|
||||||
return 3;
|
return 3;
|
||||||
else
|
else
|
||||||
return 5;
|
return 5;
|
||||||
case 'A':
|
case 'A':
|
||||||
if (name[1] == std::tolower('p'))
|
if (std::tolower(name[1]) == 'p')
|
||||||
return 4;
|
return 4;
|
||||||
else
|
else
|
||||||
return 8;
|
return 8;
|
||||||
|
|
@ -76,6 +78,30 @@ namespace {
|
||||||
(year.ival < 70 ? year.ival + 100 : year.ival) :
|
(year.ival < 70 ? year.ival + 100 : year.ival) :
|
||||||
year.ival - 1900);
|
year.ival - 1900);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_hms(const ledger::intorchar& ampm,
|
||||||
|
const ledger::intorchar& hour,
|
||||||
|
const ledger::intorchar& min = ledger::intorchar(),
|
||||||
|
const ledger::intorchar& sec = ledger::intorchar())
|
||||||
|
{
|
||||||
|
if (ampm.sval && std::tolower(ampm.sval[0]) == 'a' && hour.ival == 12)
|
||||||
|
timeval->tm_hour = 0;
|
||||||
|
else if (ampm.sval && std::tolower(ampm.sval[0]) == 'p' && hour.ival == 12)
|
||||||
|
timeval->tm_hour = 12;
|
||||||
|
else if (hour.ival < 0 || (! ampm.sval && hour.ival > 23) ||
|
||||||
|
(ampm.sval && hour.ival > 12))
|
||||||
|
throw ledger::datetime_error("Hour out of range");
|
||||||
|
else
|
||||||
|
timeval->tm_hour += hour.ival;
|
||||||
|
|
||||||
|
if (min.ival < -1 || min.ival > 59)
|
||||||
|
throw ledger::datetime_error("Minute out of range");
|
||||||
|
if (sec.ival < -1 || sec.ival > 59)
|
||||||
|
throw ledger::datetime_error("Seconds out of range");
|
||||||
|
|
||||||
|
timeval->tm_min = min.ival == -1 ? 0 : min.ival;
|
||||||
|
timeval->tm_sec = sec.ival == -1 ? 0 : sec.ival;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
@ -84,6 +110,7 @@ namespace {
|
||||||
%token TOK_TWONUM
|
%token TOK_TWONUM
|
||||||
%token TOK_ONENUM
|
%token TOK_ONENUM
|
||||||
%token TOK_MONTH
|
%token TOK_MONTH
|
||||||
|
%token TOK_AMPM
|
||||||
|
|
||||||
%token TOK_SPACE
|
%token TOK_SPACE
|
||||||
|
|
||||||
|
|
@ -91,12 +118,12 @@ namespace {
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
input: date optspace ;
|
input: date
|
||||||
|
{
|
||||||
|
throw time_to_leave();
|
||||||
|
};
|
||||||
|
|
||||||
optspace: /* epsilon */ | TOK_SPACE ;
|
date: absdate opttime
|
||||||
|
|
||||||
date:
|
|
||||||
absdate opttime
|
|
||||||
{
|
{
|
||||||
if (timeval->tm_gmtoff != -1) {
|
if (timeval->tm_gmtoff != -1) {
|
||||||
boost::posix_time::ptime::time_duration_type offset;
|
boost::posix_time::ptime::time_duration_type offset;
|
||||||
|
|
@ -195,12 +222,38 @@ absdate:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
opttime: /* epsilon */ |
|
opttime: /* epsilon */ | TOK_SPACE time ;
|
||||||
TOK_SPACE TOK_TWONUM ':' TOK_TWONUM ':' TOK_TWONUM
|
|
||||||
{
|
time:
|
||||||
timeval->tm_hour = $2.ival;
|
onetwo optspace TOK_AMPM {
|
||||||
timeval->tm_min = $4.ival;
|
if (std::tolower($3.sval[0]) == 'p')
|
||||||
timeval->tm_sec = $6.ival;
|
timeval->tm_hour = 12;
|
||||||
|
else
|
||||||
|
timeval->tm_hour = 0;
|
||||||
|
|
||||||
|
set_hms($3, $1);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
onetwo ':' TOK_TWONUM optampm {
|
||||||
|
set_hms($4, $1, $3);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
onetwo ':' TOK_TWONUM ':' TOK_TWONUM optampm {
|
||||||
|
set_hms($6, $1, $3, $5);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
onetwo: TOK_ONENUM { $$ = $1; } | TOK_TWONUM { $$ = $1; } ;
|
||||||
|
|
||||||
|
optspace: /* epsilon */ | TOK_SPACE ;
|
||||||
|
|
||||||
|
optampm: /* epsilon */ |
|
||||||
|
optspace TOK_AMPM {
|
||||||
|
if (std::tolower($2.sval[0]) == 'p')
|
||||||
|
timeval->tm_hour = 12;
|
||||||
|
else
|
||||||
|
timeval->tm_hour = 0;
|
||||||
|
$$ = $2;
|
||||||
};
|
};
|
||||||
|
|
||||||
isodate:
|
isodate:
|
||||||
|
|
@ -250,7 +303,6 @@ boost::posix_time::ptime parse_abs_datetime(std::istream& input)
|
||||||
temp.tm_gmtoff = -1;
|
temp.tm_gmtoff = -1;
|
||||||
|
|
||||||
timeval = &temp;
|
timeval = &temp;
|
||||||
//yydebug = 1;
|
|
||||||
|
|
||||||
// jww (2007-04-19): Catch any boost errors thrown from here and
|
// jww (2007-04-19): Catch any boost errors thrown from here and
|
||||||
// push them onto the new error stack scheme.
|
// push them onto the new error stack scheme.
|
||||||
|
|
@ -258,6 +310,9 @@ boost::posix_time::ptime parse_abs_datetime(std::istream& input)
|
||||||
if (yyparse() == 0)
|
if (yyparse() == 0)
|
||||||
return moment;
|
return moment;
|
||||||
}
|
}
|
||||||
|
catch (const time_to_leave&) {
|
||||||
|
return moment;
|
||||||
|
}
|
||||||
catch (ledger::datetime_error *) {
|
catch (ledger::datetime_error *) {
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
@ -275,6 +330,7 @@ namespace ledger {
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
yydebug = 1;
|
||||||
std::cout << parse_abs_datetime(std::cin) << std::endl;
|
std::cout << parse_abs_datetime(std::cin) << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ extern YYSTYPE yylval;
|
||||||
|
|
||||||
shortmon (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)
|
shortmon (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)
|
||||||
longmon (January|February|March|April|May|June|July|August|September|October|November|December)
|
longmon (January|February|March|April|May|June|July|August|September|October|November|December)
|
||||||
|
ampm (AM|PM|am|pm|A.M.|P.M.|a.m.|p.m.|[AP]|[ap])
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
|
|
@ -26,4 +27,6 @@ longmon (January|February|March|April|May|June|July|August|September|October|No
|
||||||
{shortmon} yylval = ledger::intorchar(yytext); return TOK_MONTH;
|
{shortmon} yylval = ledger::intorchar(yytext); return TOK_MONTH;
|
||||||
{longmon} yylval = ledger::intorchar(yytext); return TOK_MONTH;
|
{longmon} yylval = ledger::intorchar(yytext); return TOK_MONTH;
|
||||||
|
|
||||||
|
{ampm} yylval = ledger::intorchar(yytext); return TOK_AMPM;
|
||||||
|
|
||||||
. return (int) yytext[0];
|
. return (int) yytext[0];
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue