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
|
||||
Feb 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. */
|
||||
|
||||
/* Skeleton interface for Bison's Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
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_FOURNUM 257
|
||||
#define TOK_TWONUM 258
|
||||
#define TOK_ONENUM 259
|
||||
#define TOK_MONTH 260
|
||||
#define TOK_AMPM 261
|
||||
#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;
|
||||
|
||||
|
|
|
|||
90
parsetime.yy
90
parsetime.yy
|
|
@ -9,6 +9,8 @@ static struct std::tm * timeval;
|
|||
namespace {
|
||||
boost::posix_time::ptime moment;
|
||||
|
||||
struct time_to_leave : std::exception {};
|
||||
|
||||
yyFlexLexer * lexer;
|
||||
|
||||
inline void yyerror(const char *str) {
|
||||
|
|
@ -23,21 +25,21 @@ namespace {
|
|||
{
|
||||
switch (std::toupper(name[0])) {
|
||||
case 'J':
|
||||
if (name[1] == std::tolower('a'))
|
||||
if (std::tolower(name[1]) == 'a')
|
||||
return 1;
|
||||
else if (name[2] == std::tolower('n'))
|
||||
else if (std::tolower(name[2]) == 'n')
|
||||
return 6;
|
||||
else
|
||||
return 7;
|
||||
case 'F':
|
||||
return 2;
|
||||
case 'M':
|
||||
if (name[2] == std::tolower('r'))
|
||||
if (std::tolower(name[2]) == 'r')
|
||||
return 3;
|
||||
else
|
||||
return 5;
|
||||
case 'A':
|
||||
if (name[1] == std::tolower('p'))
|
||||
if (std::tolower(name[1]) == 'p')
|
||||
return 4;
|
||||
else
|
||||
return 8;
|
||||
|
|
@ -76,6 +78,30 @@ namespace {
|
|||
(year.ival < 70 ? year.ival + 100 : year.ival) :
|
||||
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_ONENUM
|
||||
%token TOK_MONTH
|
||||
%token TOK_AMPM
|
||||
|
||||
%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) {
|
||||
boost::posix_time::ptime::time_duration_type offset;
|
||||
|
|
@ -195,13 +222,39 @@ absdate:
|
|||
}
|
||||
;
|
||||
|
||||
opttime: /* epsilon */ |
|
||||
TOK_SPACE TOK_TWONUM ':' TOK_TWONUM ':' TOK_TWONUM
|
||||
{
|
||||
timeval->tm_hour = $2.ival;
|
||||
timeval->tm_min = $4.ival;
|
||||
timeval->tm_sec = $6.ival;
|
||||
};
|
||||
opttime: /* epsilon */ | TOK_SPACE time ;
|
||||
|
||||
time:
|
||||
onetwo optspace TOK_AMPM {
|
||||
if (std::tolower($3.sval[0]) == 'p')
|
||||
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:
|
||||
year TOK_FOURNUM optisotime
|
||||
|
|
@ -250,7 +303,6 @@ boost::posix_time::ptime parse_abs_datetime(std::istream& input)
|
|||
temp.tm_gmtoff = -1;
|
||||
|
||||
timeval = &temp;
|
||||
//yydebug = 1;
|
||||
|
||||
// jww (2007-04-19): Catch any boost errors thrown from here and
|
||||
// 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)
|
||||
return moment;
|
||||
}
|
||||
catch (const time_to_leave&) {
|
||||
return moment;
|
||||
}
|
||||
catch (ledger::datetime_error *) {
|
||||
throw;
|
||||
}
|
||||
|
|
@ -275,6 +330,7 @@ namespace ledger {
|
|||
|
||||
int main()
|
||||
{
|
||||
yydebug = 1;
|
||||
std::cout << parse_abs_datetime(std::cin) << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ extern YYSTYPE yylval;
|
|||
|
||||
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)
|
||||
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;
|
||||
{longmon} yylval = ledger::intorchar(yytext); return TOK_MONTH;
|
||||
|
||||
{ampm} yylval = ledger::intorchar(yytext); return TOK_AMPM;
|
||||
|
||||
. return (int) yytext[0];
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue