private static ITimeEvalNode BuildParseTree(ITimeEvalNode[] nodes) { if (nodes.Length == 1) { return(nodes[0]); } Dictionary <int, int> operatorTable = new Dictionary <int, int>(); List <ITimeEvalNode> results = new List <ITimeEvalNode>(); for (int i = 0; i < nodes.Length; i++) { if (nodes[i] is OperatorNode) { if (nodes[i] is BinaryOperatorNode) { BinaryOperatorNode binNode = nodes[i] as BinaryOperatorNode; if (binNode.LeftChild == null && binNode.RightChild == null) { operatorTable.Add(i, binNode.Info.Priority); } } else if (nodes[i] is UnaryOperatorNode) { UnaryOperatorNode uNode = nodes[i] as UnaryOperatorNode; if (uNode.Child == null) { operatorTable.Add(i, uNode.Info.Priority); } } } } if (operatorTable.Count == 0) { results.Add(new BinaryOperatorNode(nodes[0], nodes[1], DateTimeOperation.Additive)); for (int i = 2; i < nodes.Length; i++) { ITimeEvalNode node1 = results[0]; results.Clear(); results.Add(new BinaryOperatorNode(node1, nodes[i], DateTimeOperation.Additive)); } return(BuildParseTree(results.ToArray())); } else { // Just evaluate the node with maximum priority int maxOpIndex = operatorTable.OrderByDescending(x => x.Value).First().Key; ITimeEvalNode _opNode = nodes[maxOpIndex]; if (_opNode is BinaryOperatorNode) { BinaryOperatorNode binNode = _opNode as BinaryOperatorNode; ITimeEvalNode node1 = null, node2 = null; ITimeEvalNode[] result = null; if (maxOpIndex == 0) { node1 = new DayLeafNode(null, 0); node2 = nodes[maxOpIndex + 1]; result = new ITimeEvalNode[nodes.Length - 1]; if (binNode.Info.Direction == OperatorReadDirection.Left) { result[0] = new BinaryOperatorNode(node1, node2, binNode.Info); } else { result[0] = new BinaryOperatorNode(node2, node1, binNode.Info); } } else { node1 = nodes[maxOpIndex - 1]; } if (maxOpIndex == nodes.Length - 1) { node1 = nodes[maxOpIndex - 1]; node2 = new DayLeafNode(null, 0); result = new ITimeEvalNode[nodes.Length - 1]; if (binNode.Info.Direction == OperatorReadDirection.Left) { result[result.Length - 1] = new BinaryOperatorNode(node1, node2, binNode.Info); } else { result[result.Length - 1] = new BinaryOperatorNode(node2, node1, binNode.Info); } } else { node2 = nodes[maxOpIndex + 1]; } if (result == null) { result = new ITimeEvalNode[nodes.Length - 2]; if (binNode.Info.Direction == OperatorReadDirection.Left) { result[maxOpIndex - 1] = new BinaryOperatorNode(node1, node2, binNode.Info); } else { result[maxOpIndex - 1] = new BinaryOperatorNode(node2, node1, binNode.Info); } } if (maxOpIndex > 1) { Array.Copy(nodes, 0, result, 0, maxOpIndex - 1); } if (nodes.Length > maxOpIndex + 2) { Array.Copy(nodes, maxOpIndex + 2, result, maxOpIndex, nodes.Length - maxOpIndex - 2); } return(BuildParseTree(result)); } else { UnaryOperatorNode uNode = _opNode as UnaryOperatorNode; ITimeEvalNode[] result = new ITimeEvalNode[nodes.Length - 1]; if (uNode.Info.Direction == OperatorReadDirection.Left) { if (maxOpIndex == nodes.Length - 1) { throw new Exception("Unary operator out of boundary"); } if (maxOpIndex > 0) { Array.Copy(nodes, result, maxOpIndex); } if (nodes.Length - maxOpIndex > 2) { Array.Copy(nodes, maxOpIndex + 2, result, maxOpIndex + 1, nodes.Length - maxOpIndex - 2); } result[maxOpIndex] = new UnaryOperatorNode(nodes[maxOpIndex + 1], uNode.Info); } else { if (maxOpIndex == 0) { throw new Exception("Unary operator out of boundary"); } if (maxOpIndex > 1) { Array.Copy(nodes, result, maxOpIndex - 1); } if (nodes.Length - maxOpIndex > 1) { Array.Copy(nodes, maxOpIndex + 1, result, maxOpIndex, nodes.Length - maxOpIndex - 1); } result[maxOpIndex - 1] = new UnaryOperatorNode(nodes[maxOpIndex - 1], uNode.Info); } return(BuildParseTree(result)); } } return(null); }
private static bool TryParseExact(TaggedItem[] items, out ITimeEvalNode node) { if (items.Length == 0) { node = new DayLeafNode(null, 0); return(true); } else if (items.Length == 1) { TaggedItem item = items[0]; if (item is TaggedDateTimeItem) { TaggedDateTimeItem dtItem = item as TaggedDateTimeItem; // Second if (dtItem.Type == DateTimeType.Second) { node = new SecondLeafNode(item.Term); return(true); } // Minute else if (dtItem.Type == DateTimeType.Minute) { if (dtItem.Term.StartsWith("quarter")) { node = new MinuteLeafNode(item.Term, 15); } else { node = new MinuteLeafNode(item.Term); } return(true); } // Hour else if (dtItem.Type == DateTimeType.Hour) { node = new HourLeafNode(item.Term); return(true); } // DayTime else if (dtItem.Type == DateTimeType.DayTime) { if (dtItem.Term == "am" || dtItem.Term == "morning") { node = new DayTimeLeafNode(true); return(true); } else if (dtItem.Term == "pm" || dtItem.Term == "afternoon" || dtItem.Term == "evening" || dtItem.Term == "night") { node = new DayTimeLeafNode(false); return(true); } node = null; return(false); } // Today else if (dtItem.Type == DateTimeType.Today) { if (dtItem.Term == "today") { node = new TodayLeafNode(item.Term, 0); } else if (dtItem.Term == "tomorrow") { node = new TodayLeafNode(item.Term, 1); } else if (dtItem.Term == "yesterday") { node = new TodayLeafNode(item.Term, -1); } else { node = null; return(false); } return(true); } // Day else if (dtItem.Type == DateTimeType.Day) { node = new DayLeafNode(null, 1); return(true); } // Day of Week else if (dtItem.Type == DateTimeType.DayOfWeek) { if (dtItem.Term == "monday") { node = new DayOfWeekLeafNode(DayOfWeek.Monday, item.Term); return(true); } else if (dtItem.Term == "tuesday") { node = new DayOfWeekLeafNode(DayOfWeek.Tuesday, item.Term); return(true); } else if (dtItem.Term == "wednesday") { node = new DayOfWeekLeafNode(DayOfWeek.Wednesday, item.Term); return(true); } else if (dtItem.Term == "thursday") { node = new DayOfWeekLeafNode(DayOfWeek.Thursday, item.Term); return(true); } else if (dtItem.Term == "friday") { node = new DayOfWeekLeafNode(DayOfWeek.Friday, item.Term); return(true); } else if (dtItem.Term == "saturday") { node = new DayOfWeekLeafNode(DayOfWeek.Saturday, item.Term); return(true); } else if (dtItem.Term == "sunday") { node = new DayOfWeekLeafNode(DayOfWeek.Sunday, item.Term); return(true); } node = null; return(false); } // Week else if (dtItem.Type == DateTimeType.Week) { if (dtItem.Term == "fortnight") { node = new WeekLeafNode(item.Term, 2); } else { node = new WeekLeafNode(item.Term); } return(true); } // Month else if (dtItem.Type == DateTimeType.Month) { node = new MonthLeafNode(item.Term, 1); return(true); } // Month of Year else if (dtItem.Type == DateTimeType.MonthOfYear) { if (dtItem.Term == "january") { node = new MonthOfYearLeafNode(MonthOfYear.January); } else if (dtItem.Term == "feburary") { node = new MonthOfYearLeafNode(MonthOfYear.Feburary); } else if (dtItem.Term == "march") { node = new MonthOfYearLeafNode(MonthOfYear.March); } else if (dtItem.Term == "april") { node = new MonthOfYearLeafNode(MonthOfYear.April); } else if (dtItem.Term == "may") { node = new MonthOfYearLeafNode(MonthOfYear.May); } else if (dtItem.Term == "june") { node = new MonthOfYearLeafNode(MonthOfYear.June); } else if (dtItem.Term == "july") { node = new MonthOfYearLeafNode(MonthOfYear.July); } else if (dtItem.Term == "august") { node = new MonthOfYearLeafNode(MonthOfYear.August); } else if (dtItem.Term == "september") { node = new MonthOfYearLeafNode(MonthOfYear.September); } else if (dtItem.Term == "october") { node = new MonthOfYearLeafNode(MonthOfYear.October); } else if (dtItem.Term == "november") { node = new MonthOfYearLeafNode(MonthOfYear.November); } else if (dtItem.Term == "december") { node = new MonthOfYearLeafNode(MonthOfYear.December); } else { node = null; return(false); } return(true); } // Year else if (dtItem.Type == DateTimeType.Year) { if (dtItem.Term.StartsWith("centur")) { node = new YearLeaflNode(item.Term, 100); } else { node = new YearLeaflNode(item.Term); } return(true); } else { node = null; return(false); } } else if (item is TaggedNumberItem) { TaggedNumberItem numItem = item as TaggedNumberItem; // Parse hour (e.g. at four) if (numItem.Number >= 1 && numItem.Number < 12 && numItem.Tag == Tag.Number && numItem.Term != "a" && numItem.Term != "an") { node = new BinaryOperatorNode( new HourOfDayLeafNode(FindWorkHour((int)numItem.Number)), new MinuteOfHourLeafNode(0), DateTimeOperation.Additive); return(true); } // Parse day of month if (numItem.Number > 0 && numItem.Number <= 31 && numItem.Tag == Tag.NumberOrdinal) { node = new DayOfMonthLeafNode((int)numItem.Number); return(true); } // Parse year (e.g. twenty twenty) else if (numItem.Number > 1100 && numItem.Number < 2100 && numItem.Tag == Tag.Number) { node = new YearOfHistoryLeafNode((int)numItem.Number); return(true); } } node = null; return(false); } else if (items.Length == 2) { if (items[0] is TaggedNumberItem && items[1] is TaggedDateTimeItem) { ITimeEvalNode dt; TaggedNumberItem numItem = items[0] as TaggedNumberItem; if ((items[1] as TaggedDateTimeItem).Type == DateTimeType.Today) { node = null; return(false); } if (items[0].Tag == Tag.Number && numItem.Number <= 12 && (items[1] as TaggedDateTimeItem).Type == DateTimeType.HourOfDay) { node = new BinaryOperatorNode( new HourOfDayLeafNode(FindWorkHour((int)numItem.Number)), new MinuteOfHourLeafNode(0), DateTimeOperation.Additive); return(true); } if (TryParseExact(new TaggedItem[] { items[1] }, out dt)) { if (dt is TimeEvalLeafNode) { TimeEvalLeafNode dtTimespan = dt as TimeEvalLeafNode; // 4 pm if (items[0].Tag == Tag.Number && numItem.Number <= 12 && (items[1] as TaggedDateTimeItem).Type == DateTimeType.DayTime) { node = new BinaryOperatorNode( new BinaryOperatorNode( new HourOfDayLeafNode((int)numItem.Number), new MinuteOfHourLeafNode(0), DateTimeOperation.Additive), dtTimespan, DateTimeOperation.Additive); } else if (numItem.Number > 1 && !items[1].Term.EndsWith("s") && (items[1] as TaggedDateTimeItem).Type != DateTimeType.HourOfDay) { node = null; return(false); } // 4 days else { dtTimespan.Quantity *= numItem.Number; node = dt; } return(true); } } node = null; return(false); } // July 4th else if (items[0] is TaggedDateTimeItem && items[1] is TaggedNumberItem) { TaggedNumberItem numItem = items[1] as TaggedNumberItem; if (numItem.Tag == Tag.NumberOrdinal && numItem.Number < 31) { ITimeEvalNode dt; if (TryParseExact(new TaggedItem[] { items[0] }, out dt)) { if (dt is MonthOfYearLeafNode) { node = new BinaryOperatorNode( dt, new DayOfMonthLeafNode((int)numItem.Number), DateTimeOperation.Additive); return(true); } } } node = null; return(false); } // Four thirty else if (items[0] is TaggedNumberItem && items[1] is TaggedNumberItem) { if (items[0].Tag == Tag.Number && items[1].Tag == Tag.Number) { TaggedNumberItem num1 = items[0] as TaggedNumberItem; TaggedNumberItem num2 = items[1] as TaggedNumberItem; if (num1.Number <= 24 && num2.Number < 60) { node = new BinaryOperatorNode( new HourOfDayLeafNode( FindWorkHour((int)num1.Number)), new MinuteOfHourLeafNode( (int)num2.Number), DateTimeOperation.Additive); return(true); } } node = null; return(false); } node = null; return(false); } node = null; return(false); }