/**************************************************************** | |
* Licensed to the Apache Software Foundation (ASF) under one * | |
* or more contributor license agreements. See the NOTICE file * | |
* distributed with this work for additional information * | |
* regarding copyright ownership. The ASF licenses this file * | |
* to you under the Apache License, Version 2.0 (the * | |
* "License"); you may not use this file except in compliance * | |
* with the License. You may obtain a copy of the License at * | |
* * | |
* http://www.apache.org/licenses/LICENSE-2.0 * | |
* * | |
* Unless required by applicable law or agreed to in writing, * | |
* software distributed under the License is distributed on an * | |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * | |
* KIND, either express or implied. See the License for the * | |
* specific language governing permissions and limitations * | |
* under the License. * | |
****************************************************************/ | |
/** | |
* RFC2822 date parser. | |
* | |
* Created 9/28/2004 | |
* by Joe Cheng <code@joecheng.com> | |
*/ | |
options { | |
STATIC=false; | |
LOOKAHEAD=1; | |
JDK_VERSION = "1.5"; | |
OUTPUT_DIRECTORY = "../../../../../../../../../target/generated-sources/javacc"; | |
//DEBUG_PARSER=true; | |
//DEBUG_TOKEN_MANAGER=true; | |
} | |
PARSER_BEGIN(DateTimeParser) | |
/**************************************************************** | |
* Licensed to the Apache Software Foundation (ASF) under one * | |
* or more contributor license agreements. See the NOTICE file * | |
* distributed with this work for additional information * | |
* regarding copyright ownership. The ASF licenses this file * | |
* to you under the Apache License, Version 2.0 (the * | |
* "License"); you may not use this file except in compliance * | |
* with the License. You may obtain a copy of the License at * | |
* * | |
* http://www.apache.org/licenses/LICENSE-2.0 * | |
* * | |
* Unless required by applicable law or agreed to in writing, * | |
* software distributed under the License is distributed on an * | |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * | |
* KIND, either express or implied. See the License for the * | |
* specific language governing permissions and limitations * | |
* under the License. * | |
****************************************************************/ | |
package org.apache.james.mime4j.field.datetime.parser; | |
import org.apache.james.mime4j.field.datetime.DateTime; | |
public class DateTimeParser { | |
private static final boolean ignoreMilitaryZoneOffset = true; | |
public static void main(String args[]) throws ParseException { | |
while (true) { | |
try { | |
DateTimeParser parser = new DateTimeParser(System.in); | |
parser.parseLine(); | |
} catch (Exception x) { | |
x.printStackTrace(); | |
return; | |
} | |
} | |
} | |
private static int parseDigits(Token token) { | |
return Integer.parseInt(token.image, 10); | |
} | |
private static int getMilitaryZoneOffset(char c) { | |
if (ignoreMilitaryZoneOffset) | |
return 0; | |
c = Character.toUpperCase(c); | |
switch (c) { | |
case 'A': return 1; | |
case 'B': return 2; | |
case 'C': return 3; | |
case 'D': return 4; | |
case 'E': return 5; | |
case 'F': return 6; | |
case 'G': return 7; | |
case 'H': return 8; | |
case 'I': return 9; | |
case 'K': return 10; | |
case 'L': return 11; | |
case 'M': return 12; | |
case 'N': return -1; | |
case 'O': return -2; | |
case 'P': return -3; | |
case 'Q': return -4; | |
case 'R': return -5; | |
case 'S': return -6; | |
case 'T': return -7; | |
case 'U': return -8; | |
case 'V': return -9; | |
case 'W': return -10; | |
case 'X': return -11; | |
case 'Y': return -12; | |
case 'Z': return 0; | |
default: return 0; | |
} | |
} | |
private static class Time { | |
private int hour; | |
private int minute; | |
private int second; | |
private int zone; | |
public Time(int hour, int minute, int second, int zone) { | |
this.hour = hour; | |
this.minute = minute; | |
this.second = second; | |
this.zone = zone; | |
} | |
public int getHour() { return hour; } | |
public int getMinute() { return minute; } | |
public int getSecond() { return second; } | |
public int getZone() { return zone; } | |
} | |
private static class Date { | |
private String year; | |
private int month; | |
private int day; | |
public Date(String year, int month, int day) { | |
this.year = year; | |
this.month = month; | |
this.day = day; | |
} | |
public String getYear() { return year; } | |
public int getMonth() { return month; } | |
public int getDay() { return day; } | |
} | |
} | |
PARSER_END(DateTimeParser) | |
DateTime parseLine() : | |
{DateTime dt;} | |
{ | |
dt=date_time() ["\r"] "\n" | |
{ return dt; } | |
} | |
DateTime parseAll() : | |
{DateTime dt;} | |
{ | |
dt=date_time() <EOF> | |
{ return dt; } | |
} | |
DateTime date_time() : | |
{Date d; Time t;} | |
{ | |
[ day_of_week() "," ] | |
d=date() | |
t=time() | |
{ | |
return new DateTime( | |
d.getYear(), | |
d.getMonth(), | |
d.getDay(), | |
t.getHour(), | |
t.getMinute(), | |
t.getSecond(), | |
t.getZone()); // time zone offset | |
} | |
} | |
String day_of_week() : | |
{} | |
{ | |
( "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | "Sun" | |
) | |
{ return token.image; } | |
} | |
Date date() : | |
{int d, m; String y;} | |
{ | |
d=day() m=month() y=year() | |
{ return new Date(y, m, d); } | |
} | |
int day() : | |
{Token t;} | |
{ | |
t=<DIGITS> { return parseDigits(t); } | |
} | |
int month() : | |
{} | |
{ | |
"Jan" { return 1; } | |
| "Feb" { return 2; } | |
| "Mar" { return 3; } | |
| "Apr" { return 4; } | |
| "May" { return 5; } | |
| "Jun" { return 6; } | |
| "Jul" { return 7; } | |
| "Aug" { return 8; } | |
| "Sep" { return 9; } | |
| "Oct" { return 10; } | |
| "Nov" { return 11; } | |
| "Dec" { return 12; } | |
} | |
String year() : | |
{Token t;} | |
{ | |
t=<DIGITS> { return t.image; } | |
} | |
Time time() : | |
{int h, m, s=0, z;} | |
{ | |
h=hour() ":" m=minute() [ ":" s=second() ] z=zone() | |
{ return new Time(h, m, s, z); } | |
} | |
int hour() : | |
{Token t;} | |
{ | |
t=<DIGITS> { return parseDigits(t); } | |
} | |
int minute() : | |
{Token t;} | |
{ | |
t=<DIGITS> { return parseDigits(t); } | |
} | |
int second() : | |
{Token t;} | |
{ | |
t=<DIGITS> { return parseDigits(t); } | |
} | |
int zone() : | |
{ Token t, u; int z; } | |
{ | |
( t=< OFFSETDIR: ["+", "-"] > u=<DIGITS> { z=parseDigits(u)*(t.image.equals("-") ? -1 : 1); } | |
| z=obs_zone() | |
) | |
{ return z; } | |
} | |
int obs_zone() : | |
{Token t; int z;} | |
{ | |
( "UT" { z=0; } | |
| "GMT" { z=0; } | |
| "EST" { z=-5; } | |
| "EDT" { z=-4; } | |
| "CST" { z=-6; } | |
| "CDT" { z=-5; } | |
| "MST" { z=-7; } | |
| "MDT" { z=-6; } | |
| "PST" { z=-8; } | |
| "PDT" { z=-7; } | |
| t=< MILITARY_ZONE: ["A"-"I","a"-"i","K"-"Z","k"-"z"] > { z=getMilitaryZoneOffset(t.image.charAt(0)); } | |
) | |
{ return z * 100; } | |
} | |
SPECIAL_TOKEN : | |
{ | |
< WS: ( [" ", "\t"] )+ > | |
} | |
TOKEN_MGR_DECLS : | |
{ | |
// Keeps track of how many levels of comment nesting | |
// we've encountered. This is only used when the 2nd | |
// level is reached, for example ((this)), not (this). | |
// This is because the outermost level must be treated | |
// specially anyway, because the outermost ")" has a | |
// different token type than inner ")" instances. | |
static int commentNest; | |
} | |
MORE : | |
{ | |
// starts a comment | |
"(" : INCOMMENT | |
} | |
<INCOMMENT> | |
SKIP : | |
{ | |
// ends a comment | |
< COMMENT: ")" > : DEFAULT | |
// if this is ever changed to not be a SKIP, need | |
// to make sure matchedToken.token = token.toString() | |
// is called. | |
} | |
<INCOMMENT> | |
MORE : | |
{ | |
< <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); } | |
| "(" { commentNest = 1; } : NESTED_COMMENT | |
| < <ANY>> | |
} | |
<NESTED_COMMENT> | |
MORE : | |
{ | |
< <QUOTEDPAIR>> { image.deleteCharAt(image.length() - 2); } | |
| "(" { ++commentNest; } | |
| ")" { --commentNest; if (commentNest == 0) SwitchTo(INCOMMENT); } | |
| < <ANY>> | |
} | |
TOKEN : | |
{ | |
< DIGITS: ( ["0"-"9"] )+ > | |
} | |
// GLOBALS | |
<*> | |
TOKEN : | |
{ | |
< #QUOTEDPAIR: "\\" <ANY> > | |
| < #ANY: ~[] > | |
} |