63 lines
2.0 KiB
Python
63 lines
2.0 KiB
Python
"""
|
|
Main time expression parser class that integrates all components.
|
|
"""
|
|
|
|
import datetime
|
|
from typing import Optional
|
|
|
|
from .lexer import Lexer
|
|
from .parser import Parser
|
|
from .semantic import SemanticAnalyzer
|
|
from .ptime_ast import TimeExpressionNode
|
|
from .err import TokenUnhandledException
|
|
|
|
|
|
class TimeExpression:
|
|
"""Main class for parsing time expressions."""
|
|
|
|
def __init__(self, text: str, now: Optional[datetime.datetime] = None):
|
|
self.text = text.strip()
|
|
self.now = now or datetime.datetime.now()
|
|
|
|
if not self.text:
|
|
raise TokenUnhandledException("Empty input")
|
|
|
|
# Initialize components
|
|
self.lexer = Lexer(self.text, self.now)
|
|
self.parser = Parser(self.text, self.now)
|
|
self.semantic_analyzer = SemanticAnalyzer(self.now)
|
|
|
|
# Parse the expression
|
|
self.ast = self._parse()
|
|
|
|
def _parse(self) -> TimeExpressionNode:
|
|
"""Parse the time expression and return the AST."""
|
|
try:
|
|
return self.parser.parse()
|
|
except Exception as e:
|
|
raise TokenUnhandledException(f"Failed to parse '{self.text}': {str(e)}")
|
|
|
|
def evaluate(self) -> datetime.datetime:
|
|
"""Evaluate the time expression and return the datetime."""
|
|
try:
|
|
return self.semantic_analyzer.evaluate(self.ast)
|
|
except Exception as e:
|
|
raise TokenUnhandledException(f"Failed to evaluate '{self.text}': {str(e)}")
|
|
|
|
@classmethod
|
|
def parse(cls, text: str, now: Optional[datetime.datetime] = None) -> datetime.datetime:
|
|
"""
|
|
Parse a time expression and return a datetime object.
|
|
|
|
Args:
|
|
text: The time expression to parse
|
|
now: The reference time (defaults to current time)
|
|
|
|
Returns:
|
|
A datetime object representing the parsed time
|
|
|
|
Raises:
|
|
TokenUnhandledException: If the input cannot be parsed
|
|
"""
|
|
expression = cls(text, now)
|
|
return expression.evaluate() |