nodes: add source location to AST nodes
This commit is contained in:
parent
585910a60b
commit
caffa92c1e
2 changed files with 43 additions and 8 deletions
|
|
@ -16,10 +16,20 @@ class Node:
|
|||
def _values(self) -> Any | list[Node]:
|
||||
raise NotImplementedError(f"Please override {__name__}")
|
||||
|
||||
@functools.cache
|
||||
def location(self) -> SourceLocation:
|
||||
locations = [v.location() for v in self._values()]
|
||||
begin = min([loc.begin for loc in locations])
|
||||
end = max([loc.end for loc in locations])
|
||||
loc = SourceLocation(begin=begin, end=end)
|
||||
return loc
|
||||
|
||||
def __repr__(self):
|
||||
vals = self._values()
|
||||
if type(vals) == list:
|
||||
vals = ", ".join(repr(val) for val in vals)
|
||||
else:
|
||||
vals = repr(vals)
|
||||
return f"{self.__class__.__name__}({vals})"
|
||||
|
||||
def pprint(self, depth: int | None = None, indent: str = "\t"):
|
||||
|
|
@ -48,9 +58,13 @@ class Node:
|
|||
return result
|
||||
|
||||
|
||||
class Literal(Node):
|
||||
def __init__(self, value: Any):
|
||||
class Literal(Node, ABC):
|
||||
def __init__(self, location: SourceLocation, value: Any):
|
||||
self.value = value
|
||||
self.loc = location
|
||||
|
||||
def location(self) -> SourceLocation:
|
||||
return self.loc
|
||||
|
||||
def _values(self) -> Any | list[Node]:
|
||||
return self.value
|
||||
|
|
@ -96,14 +110,15 @@ BinaryOperation = Sum | Sub | Product | Division
|
|||
|
||||
@beartype
|
||||
class Float(Literal):
|
||||
def __init__(self, value: float):
|
||||
super().__init__(value)
|
||||
def __init__(self, location: SourceLocation, value: float):
|
||||
super().__init__(location, value)
|
||||
|
||||
|
||||
@beartype
|
||||
class Integer(Literal):
|
||||
def __init__(self, value: int):
|
||||
super().__init__(value)
|
||||
|
||||
def __init__(self, location: SourceLocation, value: int):
|
||||
super().__init__(location, value)
|
||||
|
||||
|
||||
class Expression(Node):
|
||||
|
|
@ -113,6 +128,26 @@ class Expression(Node):
|
|||
def _values(self) -> Any | list[Node]:
|
||||
return self.node
|
||||
|
||||
def location(self) -> SourceLocation:
|
||||
return self.node.location()
|
||||
|
||||
|
||||
class Identifier(Literal):
|
||||
def __init__(self, name: str):
|
||||
super().__init__(name)
|
||||
|
||||
|
||||
class Assignment(Node):
|
||||
def intermediate_representation(self, context: semantic.Context) -> list[ir.IRItem]:
|
||||
return self.value.intermediate_representation(context)
|
||||
|
||||
def __init__(self, identifier: Identifier, value: Value):
|
||||
self.identifier = identifier
|
||||
self.value = value
|
||||
|
||||
def _values(self) -> Any | list[Node]:
|
||||
return [self.identifier, self.value]
|
||||
|
||||
|
||||
Number = Float | Integer
|
||||
Value = BinaryOperation | Number
|
||||
|
|
|
|||
|
|
@ -68,10 +68,10 @@ class Parser:
|
|||
def number(self, mandatory: bool = False):
|
||||
if tok := self.accept(Tokens.Float):
|
||||
logger.debug(f"Found float {tok}")
|
||||
return Float(value=float(tok.value))
|
||||
return Float(location=tok.loc, value=float(tok.value))
|
||||
elif tok := self.accept(Tokens.Integer):
|
||||
logger.debug(f"Found integer {tok}")
|
||||
return Integer(value=int(tok.value))
|
||||
return Integer(location=tok.loc, value=int(tok.value))
|
||||
elif mandatory:
|
||||
raise UnexpectedTokenError(self.token, "integer or float")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue