summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/date-examples.txt6
-rw-r--r--parsetime.h71
-rw-r--r--parsetime.yy90
-rw-r--r--scantime.ll3
4 files changed, 87 insertions, 83 deletions
diff --git a/docs/date-examples.txt b/docs/date-examples.txt
index 948d6980..2c2afe94 100644
--- a/docs/date-examples.txt
+++ b/docs/date-examples.txt
@@ -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
diff --git a/parsetime.h b/parsetime.h
index 5a9281de..16b969f5 100644
--- a/parsetime.h
+++ b/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;
-
diff --git a/parsetime.yy b/parsetime.yy
index f34730c4..f2b204c9 100644
--- a/parsetime.yy
+++ b/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 ;
-
-optspace: /* epsilon */ | TOK_SPACE ;
+input: date
+{
+ throw time_to_leave();
+};
-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;
}
diff --git a/scantime.ll b/scantime.ll
index 02d00d78..75819bcc 100644
--- a/scantime.ll
+++ b/scantime.ll
@@ -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];