package ch.pollet.jzic.parser;
import ch.pollet.jzic.datetime.DateTime;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import ch.pollet.jzic.timezone.Database;
import ch.pollet.jzic.tokenizer.Tokenizer;
/**
*
* @author Christophe Pollet
*/
public class Parser {
private Database db;
public Parser(Database db) {
this.db = db;
}
public void parse(String[] fileNames) throws ParserException, IOException {
for (String fileName : fileNames) {
parse(fileName);
}
}
public void parse(String fileName) throws ParserException, IOException {
LineNumberReader in = new LineNumberReader(new FileReader(fileName));
RuleParser rp = new RuleParser(db);
ZoneParser zp = new ZoneParser(db);
LinkParser lp = new LinkParser(db);
String line;
System.out.println("Parsing " + fileName);
while ((line = in.readLine()) != null) {
if ((line = stripComment(line)) != null) {
Tokenizer st = new Tokenizer(line, "\t ", fileName, in.getLineNumber());
if (Character.isWhitespace(line.charAt(0)) && st.hasMoreTokens()) {
zp.continueParsing(st);
}
else if (st.hasMoreTokens()) {
String token = st.nextToken();
if (token.equalsIgnoreCase("rule")) {
rp.parse(st);
} else if (token.equalsIgnoreCase("zone")) {
zp.parse(st);
} else if (token.equalsIgnoreCase("link")) {
lp.parse(st);
} else {
throw new ParserException("Unknown definition [" +
token + "] in " + fileName + ":" +
in.getLineNumber());
}
}
}
}
in.close();
}
private String stripComment(String line) {
int commentIndex;
String trimmed = line.trim();
if (trimmed.length() == 0 || trimmed.charAt(0) == '#') {
return null;
}
commentIndex = line.indexOf("#");
if (commentIndex > 0) {
return line.substring(0, commentIndex);
}
return line;
}
public static int parseOffset(String str) {
String tmp[];
int c = 3600;
int offset = 0;
if (str.charAt(0) == '-') {
c *= -1;
str = str.substring(1);
}
tmp = str.split(":");
for (int i = 0; i < tmp.length; i++) {
offset += c * Integer.parseInt(tmp[i]);
c = c / 60;
}
return offset;
}
public static int parseMonth(String str) throws ParserException {
str = str.toLowerCase();
if (str.equals("jan") || str.equals("january")) {
return 1;
}
if (str.equals("feb") || str.equals("february")) {
return 2;
}
if (str.equals("mar") || str.equals("march")) {
return 3;
}
if (str.equals("apr") || str.equals("april")) {
return 4;
}
if (str.equals("may") || str.equals("may")) {
return 5;
}
if (str.equals("jun") || str.equals("june")) {
return 6;
}
if (str.equals("jul") || str.equals("july")) {
return 7;
}
if (str.equals("aug") || str.equals("august")) {
return 8;
}
if (str.equals("sep") || str.equals("september")) {
return 9;
}
if (str.equals("oct") || str.equals("october")) {
return 10;
}
if (str.equals("nov") || str.equals("november")) {
return 11;
}
if (str.equals("dec") || str.equals("january")) {
return 12;
}
throw new ParserException("Invalid month [" + str + "]");
}
public static int parseDayOfWeek(String str) throws ParserException {
str = str.toLowerCase();
if (str.equals("mon") || str.equals("monday")) {
return 1;
}
if (str.equals("tue") || str.equals("tuesday")) {
return 2;
}
if (str.equals("wed") || str.equals("wednesday")) {
return 3;
}
if (str.equals("thu") || str.equals("thursday")) {
return 4;
}
if (str.equals("fri") || str.equals("friday")) {
return 5;
}
if (str.equals("sat") || str.equals("saturday")) {
return 6;
}
if (str.equals("sun") || str.equals("sunday")) {
return 7;
}
throw new ParserException("Invalid day of week [" + str + "]");
}
public static DateTime parseDateTime(Tokenizer st, DateTime dt) throws ParserException {
String str;
// parse month
if (st.hasMoreTokens()) {
try {
dt.setMonth(Parser.parseMonth(st.nextToken()));
} catch (ParserException ex) {
throw new ParserException(ex.getMessage() + ": "
+ st.getFileName() + ":" + st.getLineNumber());
}
}
// parse day
if (st.hasMoreTokens()) {
str = st.nextToken().toLowerCase();
if (str.startsWith("last")) {
try {
dt.setDayOfWeek(parseDayOfWeek(str.substring(4)));
} catch (ParserException ex) {
throw new ParserException(ex.getMessage() + ": "
+ st.getFileName() + ":" + st.getLineNumber());
}
dt.setDayBase(31);
dt.setDayPosition(DateTime.DayPosition.LE);
} else {
try {
dt.setDay(Integer.parseInt(str));
} catch (NumberFormatException ex1) {
// we have something like xxx>=y
try {
dt.setDayOfWeek(parseDayOfWeek(str.substring(0, 3)));
} catch (ParserException ex2) {
throw new ParserException(ex2.getMessage() + ": "
+ st.getFileName() + ":" + st.getLineNumber());
}
str = str.substring(3);
if (str.substring(0, 2).equals("<=")) {
dt.setDayPosition(DateTime.DayPosition.LE);
} else {
dt.setDayPosition(DateTime.DayPosition.GE);
}
dt.setDayBase(Integer.parseInt(str.substring(2)));
}
}
}
// parse time
if (st.hasMoreTokens()) {
str = st.nextToken().toLowerCase();
String tmp[];
switch (str.charAt(str.length() - 1)) {
case 'u':
case 'g':
case 'z':
dt.setType(DateTime.Type.UTC);
break;
case 's':
dt.setType(DateTime.Type.STD);
break;
default:
dt.setType(DateTime.Type.WALL);
break;
}
// remove last char if it is not a digit
if (!Character.isDigit(str.charAt(str.length() - 1))) {
str = str.substring(0, str.length() - 1);
}
tmp = str.split(":");
dt.setHour(Integer.parseInt(tmp[0]));
if (tmp.length >= 2) {
dt.setMinute(Integer.parseInt(tmp[1]));
} else {
dt.setMinute(0);
}
if (tmp.length >= 3) {
dt.setSecond(Integer.parseInt(tmp[2]));
} else {
dt.setSecond(0);
}
}
return dt;
}
public static DateTime parseDateTime(Tokenizer st) throws ParserException {
DateTime dt = new DateTime(st.getFileName(), st.getLineNumber());
return parseDateTime(st, dt);
}
}