/// <summary> /// Parses the given date. /// </summary> /// <param name="date">The date in string format including "hash tags" (e.g. #01-01-1900#)</param> /// <returns>The root of the parse tree.</returns> public VBADateParser.DateLiteralContext Parse(string date) { var stream = new AntlrInputStream(date); var lexer = new VBADateLexer(stream); var tokens = new CommonTokenStream(lexer); var parser = new VBADateParser(tokens); parser.AddErrorListener(new ExceptionErrorListener(CodeKind.SnippetCode)); // notify? VBADateParser.CompilationUnitContext tree; try { parser.Interpreter.PredictionMode = PredictionMode.Sll; tree = parser.compilationUnit(); } catch (Exception ex) { Logger.Warn(ex, "SLL mode failed for {0}. Retrying using LL.", date); tokens.Reset(); parser.Reset(); parser.Interpreter.PredictionMode = PredictionMode.Ll; tree = parser.compilationUnit(); } return(tree.dateLiteral()); }
public override IValue Evaluate() { string literal = _tokenText.Evaluate().AsString; var stream = new AntlrInputStream(literal); var lexer = new VBADateLexer(stream); var tokens = new CommonTokenStream(lexer); var parser = new VBADateParser(tokens); var dateLiteral = parser.dateLiteral(); var dateOrTime = dateLiteral.dateOrTime(); int year; int month; int day; int hours; int mins; int seconds; Predicate<int> legalMonth = (x) => x >= 0 && x <= 12; Func<int, int, int, bool> legalDay = (m, d, y) => { bool legalYear = y >= 0 && y <= 32767; bool legalM = legalMonth(m); bool legalD = false; if (legalYear && legalM) { int daysInMonth = DateTime.DaysInMonth(y, m); legalD = d >= 1 && d <= daysInMonth; } return legalYear && legalM && legalD; }; Func<int, int> yearFunc = (x) => { if (x >= 0 && x <= 29) { return x + 2000; } else if (x >= 30 && x <= 99) { return x + 1900; } else { return x; } }; int CY = DateTime.Now.Year; if (dateOrTime.dateValue() == null) { year = 1899; month = 12; day = 30; } else { var dateValue = dateOrTime.dateValue(); var txt = dateOrTime.GetText(); var L = dateValue.dateValuePart()[0]; var M = dateValue.dateValuePart()[1]; VBADateParser.DateValuePartContext R = null; if (dateValue.dateValuePart().Count == 3) { R = dateValue.dateValuePart()[2]; } // "If L and M are numbers and R is not present:" if (L.dateValueNumber() != null && M.dateValueNumber() != null && R == null) { var LNumber = int.Parse(L.GetText(), CultureInfo.InvariantCulture); var MNumber = int.Parse(M.GetText(), CultureInfo.InvariantCulture); if (legalMonth(LNumber) && legalDay(LNumber, MNumber, CY)) { month = LNumber; day = MNumber; year = CY; } else if ((legalMonth(MNumber) && legalDay(MNumber, LNumber, CY))) { month = MNumber; day = LNumber; year = CY; } else if (legalMonth(LNumber)) { month = LNumber; day = 1; year = MNumber; } else if (legalMonth(MNumber)) { month = MNumber; day = 1; year = LNumber; } else { throw new Exception("Invalid date: " + dateLiteral.GetText()); } } // "If L, M, and R are numbers:" else if (L.dateValueNumber() != null && M.dateValueNumber() != null && R != null && R.dateValueNumber() != null) { var LNumber = int.Parse(L.GetText(), CultureInfo.InvariantCulture); var MNumber = int.Parse(M.GetText(), CultureInfo.InvariantCulture); var RNumber = int.Parse(R.GetText(), CultureInfo.InvariantCulture); if (legalMonth(LNumber) && legalDay(LNumber, MNumber, yearFunc(RNumber))) { month = LNumber; day = MNumber; year = yearFunc(RNumber); } else if (legalMonth(MNumber) && legalDay(MNumber, RNumber, yearFunc(LNumber))) { month = MNumber; day = RNumber; year = yearFunc(LNumber); } else if (legalMonth(MNumber) && legalDay(MNumber, LNumber, yearFunc(RNumber))) { month = MNumber; day = LNumber; year = yearFunc(RNumber); } else { throw new Exception("Invalid date: " + dateLiteral.GetText()); } } // "If either L or M is not a number and R is not present:" else if ((L.dateValueNumber() == null || M.dateValueNumber() == null) && R == null) { int N; string monthName; if (L.dateValueNumber() != null) { N = int.Parse(L.GetText(), CultureInfo.InvariantCulture); monthName = M.GetText(); } else { N = int.Parse(M.GetText(), CultureInfo.InvariantCulture); monthName = L.GetText(); } int monthNameNumber; if (monthName.Length == 3) { monthNameNumber = DateTime.ParseExact(monthName, "MMM", CultureInfo.InvariantCulture).Month; } else { monthNameNumber = DateTime.ParseExact(monthName, "MMMM", CultureInfo.InvariantCulture).Month; } if (legalDay(monthNameNumber, N, CY)) { month = monthNameNumber; day = N; year = CY; } else { month = monthNameNumber; day = 1; year = N; } } // "Otherwise, R is present and one of L, M, and R is not a number:" else { int N1; int N2; string monthName; if (L.dateValueNumber() == null) { monthName = L.GetText(); N1 = int.Parse(M.GetText(), CultureInfo.InvariantCulture); N2 = int.Parse(R.GetText(), CultureInfo.InvariantCulture); } else if (M.dateValueNumber() == null) { monthName = M.GetText(); N1 = int.Parse(L.GetText(), CultureInfo.InvariantCulture); N2 = int.Parse(R.GetText(), CultureInfo.InvariantCulture); } else { monthName = R.GetText(); N1 = int.Parse(L.GetText(), CultureInfo.InvariantCulture); N2 = int.Parse(M.GetText(), CultureInfo.InvariantCulture); } int monthNameNumber; if (monthName.Length == 3) { monthNameNumber = DateTime.ParseExact(monthName, "MMM", CultureInfo.InvariantCulture).Month; } else { monthNameNumber = DateTime.ParseExact(monthName, "MMMM", CultureInfo.InvariantCulture).Month; } if (legalDay(monthNameNumber, N1, yearFunc(N2))) { month = monthNameNumber; day = N1; year = yearFunc(N2); } else if (legalDay(monthNameNumber, N2, yearFunc(N1))) { month = monthNameNumber; day = N2; year = yearFunc(N1); } else { throw new Exception("Invalid date: " + dateLiteral.GetText()); } } } if (dateOrTime.timeValue() == null) { hours = 0; mins = 0; seconds = 0; } else { var timeValue = dateOrTime.timeValue(); hours = int.Parse(timeValue.timeValuePart()[0].GetText(), CultureInfo.InvariantCulture); if (timeValue.timeValuePart().Count == 1) { mins = 0; } else { mins = int.Parse(timeValue.timeValuePart()[1].GetText(), CultureInfo.InvariantCulture); } if (timeValue.timeValuePart().Count < 3) { seconds = 0; } else { seconds = int.Parse(timeValue.timeValuePart()[2].GetText(), CultureInfo.InvariantCulture); } var amPm = timeValue.AMPM(); if (amPm != null && (amPm.GetText().ToUpper() == "P" || amPm.GetText().ToUpper() == "PM") && hours >= 0 && hours <= 11) { hours += 12; } else if (amPm != null && (amPm.GetText().ToUpper() == "A" || amPm.GetText().ToUpper() == "AM") && hours == 12) { hours = 0; } } return new DateValue(new DateTime(year, month, day, hours, mins, seconds)); }
public override IValue Evaluate() { string literal = _tokenText.Evaluate().AsString; var stream = new AntlrInputStream(literal); var lexer = new VBADateLexer(stream); var tokens = new CommonTokenStream(lexer); var parser = new VBADateParser(tokens); var dateLiteral = parser.dateLiteral(); var dateOrTime = dateLiteral.dateOrTime(); int year; int month; int day; int hours; int mins; int seconds; Predicate <int> legalMonth = (x) => x >= 0 && x <= 12; Func <int, int, int, bool> legalDay = (m, d, y) => { bool legalYear = y >= 0 && y <= 32767; bool legalM = legalMonth(m); bool legalD = false; if (legalYear && legalM) { int daysInMonth = DateTime.DaysInMonth(y, m); legalD = d >= 1 && d <= daysInMonth; } return(legalYear && legalM && legalD); }; Func <int, int> yearFunc = (x) => { if (x >= 0 && x <= 29) { return(x + 2000); } else if (x >= 30 && x <= 99) { return(x + 1900); } else { return(x); } }; int CY = DateTime.Now.Year; if (dateOrTime.dateValue() == null) { year = 1899; month = 12; day = 30; } else { var dateValue = dateOrTime.dateValue(); var txt = dateOrTime.GetText(); var L = dateValue.dateValuePart()[0]; var M = dateValue.dateValuePart()[1]; VBADateParser.DateValuePartContext R = null; if (dateValue.dateValuePart().Count == 3) { R = dateValue.dateValuePart()[2]; } // "If L and M are numbers and R is not present:" if (L.dateValueNumber() != null && M.dateValueNumber() != null && R == null) { var LNumber = int.Parse(L.GetText(), CultureInfo.InvariantCulture); var MNumber = int.Parse(M.GetText(), CultureInfo.InvariantCulture); if (legalMonth(LNumber) && legalDay(LNumber, MNumber, CY)) { month = LNumber; day = MNumber; year = CY; } else if ((legalMonth(MNumber) && legalDay(MNumber, LNumber, CY))) { month = MNumber; day = LNumber; year = CY; } else if (legalMonth(LNumber)) { month = LNumber; day = 1; year = MNumber; } else if (legalMonth(MNumber)) { month = MNumber; day = 1; year = LNumber; } else { throw new Exception("Invalid date: " + dateLiteral.GetText()); } } // "If L, M, and R are numbers:" else if (L.dateValueNumber() != null && M.dateValueNumber() != null && R != null && R.dateValueNumber() != null) { var LNumber = int.Parse(L.GetText(), CultureInfo.InvariantCulture); var MNumber = int.Parse(M.GetText(), CultureInfo.InvariantCulture); var RNumber = int.Parse(R.GetText(), CultureInfo.InvariantCulture); if (legalMonth(LNumber) && legalDay(LNumber, MNumber, yearFunc(RNumber))) { month = LNumber; day = MNumber; year = yearFunc(RNumber); } else if (legalMonth(MNumber) && legalDay(MNumber, RNumber, yearFunc(LNumber))) { month = MNumber; day = RNumber; year = yearFunc(LNumber); } else if (legalMonth(MNumber) && legalDay(MNumber, LNumber, yearFunc(RNumber))) { month = MNumber; day = LNumber; year = yearFunc(RNumber); } else { throw new Exception("Invalid date: " + dateLiteral.GetText()); } } // "If either L or M is not a number and R is not present:" else if ((L.dateValueNumber() == null || M.dateValueNumber() == null) && R == null) { int N; string monthName; if (L.dateValueNumber() != null) { N = int.Parse(L.GetText(), CultureInfo.InvariantCulture); monthName = M.GetText(); } else { N = int.Parse(M.GetText(), CultureInfo.InvariantCulture); monthName = L.GetText(); } int monthNameNumber; if (monthName.Length == 3) { monthNameNumber = DateTime.ParseExact(monthName, "MMM", CultureInfo.InvariantCulture).Month; } else { monthNameNumber = DateTime.ParseExact(monthName, "MMMM", CultureInfo.InvariantCulture).Month; } if (legalDay(monthNameNumber, N, CY)) { month = monthNameNumber; day = N; year = CY; } else { month = monthNameNumber; day = 1; year = N; } } // "Otherwise, R is present and one of L, M, and R is not a number:" else { int N1; int N2; string monthName; if (L.dateValueNumber() == null) { monthName = L.GetText(); N1 = int.Parse(M.GetText(), CultureInfo.InvariantCulture); N2 = int.Parse(R.GetText(), CultureInfo.InvariantCulture); } else if (M.dateValueNumber() == null) { monthName = M.GetText(); N1 = int.Parse(L.GetText(), CultureInfo.InvariantCulture); N2 = int.Parse(R.GetText(), CultureInfo.InvariantCulture); } else { monthName = R.GetText(); N1 = int.Parse(L.GetText(), CultureInfo.InvariantCulture); N2 = int.Parse(M.GetText(), CultureInfo.InvariantCulture); } int monthNameNumber; if (monthName.Length == 3) { monthNameNumber = DateTime.ParseExact(monthName, "MMM", CultureInfo.InvariantCulture).Month; } else { monthNameNumber = DateTime.ParseExact(monthName, "MMMM", CultureInfo.InvariantCulture).Month; } if (legalDay(monthNameNumber, N1, yearFunc(N2))) { month = monthNameNumber; day = N1; year = yearFunc(N2); } else if (legalDay(monthNameNumber, N2, yearFunc(N1))) { month = monthNameNumber; day = N2; year = yearFunc(N1); } else { throw new Exception("Invalid date: " + dateLiteral.GetText()); } } } if (dateOrTime.timeValue() == null) { hours = 0; mins = 0; seconds = 0; } else { var timeValue = dateOrTime.timeValue(); hours = int.Parse(timeValue.timeValuePart()[0].GetText(), CultureInfo.InvariantCulture); if (timeValue.timeValuePart().Count == 1) { mins = 0; } else { mins = int.Parse(timeValue.timeValuePart()[1].GetText(), CultureInfo.InvariantCulture); } if (timeValue.timeValuePart().Count < 3) { seconds = 0; } else { seconds = int.Parse(timeValue.timeValuePart()[2].GetText(), CultureInfo.InvariantCulture); } var amPm = timeValue.AMPM(); if (amPm != null && (amPm.GetText().ToUpper() == "P" || amPm.GetText().ToUpper() == "PM") && hours >= 0 && hours <= 11) { hours += 12; } else if (amPm != null && (amPm.GetText().ToUpper() == "A" || amPm.GetText().ToUpper() == "AM") && hours == 12) { hours = 0; } } return(new DateValue(new DateTime(year, month, day, hours, mins, seconds))); }