add more evaluator
This commit is contained in:
parent
dd527edbc4
commit
15e6fb864d
89
evaluator.py
89
evaluator.py
@ -1,10 +1,15 @@
|
|||||||
from typing import List, Optional
|
from typing import Dict, List, Optional, cast
|
||||||
from position import Node
|
from position import Node
|
||||||
|
from utils import Err, Ok, Result
|
||||||
import parsed
|
import parsed
|
||||||
|
|
||||||
class Value:
|
class Value:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class Unit(Value):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
class Int(Value):
|
class Int(Value):
|
||||||
def __init__(self, value: int) -> None:
|
def __init__(self, value: int) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
@ -48,6 +53,20 @@ class ContinueResult(EvalResult):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
|
class PanicResult(EvalResult):
|
||||||
|
def __init__(self, message: str) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.message = message
|
||||||
|
|
||||||
|
class SymbolTable:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.symbols: Dict[str, Value] = {}
|
||||||
|
|
||||||
|
def define(self, symbol_id: str, value: Value) -> Result[None, str]:
|
||||||
|
if symbol_id in self.symbols:
|
||||||
|
return Err("symbol already defined")
|
||||||
|
return Ok(None)
|
||||||
|
|
||||||
class Evaluator:
|
class Evaluator:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
pass
|
pass
|
||||||
@ -57,60 +76,60 @@ class Evaluator:
|
|||||||
self.eval_expr(node)
|
self.eval_expr(node)
|
||||||
|
|
||||||
def eval_expr(self, node: Node[parsed.Expr]) -> EvalResult:
|
def eval_expr(self, node: Node[parsed.Expr]) -> EvalResult:
|
||||||
if node.value is parsed.ExprError:
|
if isinstance(node.value, parsed.ExprError):
|
||||||
|
return PanicResult(f"error: {cast(parsed.ExprError, node.value).message}, at {node.span}")
|
||||||
|
elif isinstance(node.value, parsed.Id):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.Id:
|
elif isinstance(node.value, parsed.Int):
|
||||||
|
return ValueResult(Int(cast(parsed.Int, node.value).value))
|
||||||
|
elif isinstance(node.value, parsed.Char):
|
||||||
|
return ValueResult(Char(cast(parsed.Char, node.value).value))
|
||||||
|
elif isinstance(node.value, parsed.String):
|
||||||
|
return ValueResult(String(cast(parsed.String, node.value).value))
|
||||||
|
elif isinstance(node.value, parsed.Bool):
|
||||||
|
return ValueResult(Bool(cast(parsed.Bool, node.value).value))
|
||||||
|
elif isinstance(node.value, parsed.Unit):
|
||||||
|
return ValueResult(Unit())
|
||||||
|
elif isinstance(node.value, parsed.Tuple):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.Int:
|
elif isinstance(node.value, parsed.Block):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.Char:
|
elif isinstance(node.value, parsed.Lambda):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.String:
|
elif isinstance(node.value, parsed.If):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.Bool:
|
elif isinstance(node.value, parsed.Match):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.Unit:
|
elif isinstance(node.value, parsed.Loop):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.Tuple:
|
elif isinstance(node.value, parsed.While):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.Block:
|
elif isinstance(node.value, parsed.For):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.Lambda:
|
elif isinstance(node.value, parsed.StructMember):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.If:
|
elif isinstance(node.value, parsed.TupleMember):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.Match:
|
elif isinstance(node.value, parsed.Index):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.Loop:
|
elif isinstance(node.value, parsed.Call):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.While:
|
elif isinstance(node.value, parsed.Unary):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.For:
|
elif isinstance(node.value, parsed.Binary):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.StructMember:
|
elif isinstance(node.value, parsed.Assign):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.TupleMember:
|
elif isinstance(node.value, parsed.Let):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.Index:
|
elif isinstance(node.value, parsed.Function):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.Call:
|
elif isinstance(node.value, parsed.Return):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.Unary:
|
elif isinstance(node.value, parsed.Break):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
elif node.value is parsed.Binary:
|
elif isinstance(node.value, parsed.Continue):
|
||||||
raise NotImplementedError()
|
|
||||||
elif node.value is parsed.Assign:
|
|
||||||
raise NotImplementedError()
|
|
||||||
elif node.value is parsed.Let:
|
|
||||||
raise NotImplementedError()
|
|
||||||
elif node.value is parsed.Function:
|
|
||||||
raise NotImplementedError()
|
|
||||||
elif node.value is parsed.Return:
|
|
||||||
raise NotImplementedError()
|
|
||||||
elif node.value is parsed.Break:
|
|
||||||
raise NotImplementedError()
|
|
||||||
elif node.value is parsed.Continue:
|
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError(str(node))
|
||||||
|
|
||||||
|
8
main.py
8
main.py
@ -1,14 +1,20 @@
|
|||||||
from lexer import Lexer
|
from lexer import Lexer
|
||||||
from parser import Parser
|
from parser import Parser
|
||||||
|
from evaluator import Evaluator
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
text = "\"\\\"hello\\\\\""
|
text = "\"hello\""
|
||||||
lexer = Lexer(text)
|
lexer = Lexer(text)
|
||||||
parser = Parser(text, lexer)
|
parser = Parser(text, lexer)
|
||||||
|
print("parsing...")
|
||||||
parsed = parser.parse()
|
parsed = parser.parse()
|
||||||
|
print("ast = ")
|
||||||
for node in parsed:
|
for node in parsed:
|
||||||
print(node)
|
print(node)
|
||||||
|
evaluator = Evaluator()
|
||||||
|
print("evaluating...")
|
||||||
|
evaluator.evaluate(parsed)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
15
parsed.py
15
parsed.py
@ -1,6 +1,7 @@
|
|||||||
from enum import Enum, auto
|
from enum import Enum, auto
|
||||||
from position import Node
|
from position import Node
|
||||||
from typing import Optional, List
|
from typing import Optional, List
|
||||||
|
from utils import escape_string
|
||||||
|
|
||||||
class Type:
|
class Type:
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
@ -64,7 +65,7 @@ class Char(Expr):
|
|||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return f"Char('{self.value}')"
|
return f"Char('{escape_string(self.value)}')"
|
||||||
|
|
||||||
|
|
||||||
class String(Expr):
|
class String(Expr):
|
||||||
@ -73,7 +74,7 @@ class String(Expr):
|
|||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return f"String(\"{self.value}\")"
|
return f"String(\"{escape_string(self.value)}\")"
|
||||||
|
|
||||||
|
|
||||||
class Bool(Expr):
|
class Bool(Expr):
|
||||||
@ -99,7 +100,7 @@ class Tuple(Expr):
|
|||||||
self.values = values
|
self.values = values
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
values = ", ".join(node.__str__() for node in self.values)
|
values = ", ".join(str(node) for node in self.values)
|
||||||
return f"Tuple {{ values: [{values}] }}"
|
return f"Tuple {{ values: [{values}] }}"
|
||||||
|
|
||||||
class Block(Expr):
|
class Block(Expr):
|
||||||
@ -109,7 +110,7 @@ class Block(Expr):
|
|||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
statements = ", ".join(node.__str__() for node in self.statements)
|
statements = ", ".join(str(node) for node in self.statements)
|
||||||
return f"Block {{ statements: [{statements}], value: {self.value} }}"
|
return f"Block {{ statements: [{statements}], value: {self.value} }}"
|
||||||
|
|
||||||
class Lambda(Expr):
|
class Lambda(Expr):
|
||||||
@ -119,7 +120,7 @@ class Lambda(Expr):
|
|||||||
self.body = body
|
self.body = body
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
params = ", ".join(node.__str__() for node in self.params)
|
params = ", ".join(str(node) for node in self.params)
|
||||||
return f"Lambda {{ params: [{params}], body: {self.body} }}"
|
return f"Lambda {{ params: [{params}], body: {self.body} }}"
|
||||||
|
|
||||||
|
|
||||||
@ -205,7 +206,7 @@ class Call(Expr):
|
|||||||
self.arguments = arguments
|
self.arguments = arguments
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
arguments = ", ".join(node.__str__() for node in self.arguments)
|
arguments = ", ".join(str(node) for node in self.arguments)
|
||||||
return f"Index {{ subject: {self.subject}, arguments: {arguments} }}"
|
return f"Index {{ subject: {self.subject}, arguments: {arguments} }}"
|
||||||
|
|
||||||
class UnaryType(Enum):
|
class UnaryType(Enum):
|
||||||
@ -292,7 +293,7 @@ class Function(Expr):
|
|||||||
self.body = body
|
self.body = body
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
params = ", ".join(node.__str__() for node in self.params)
|
params = ", ".join(str(node) for node in self.params)
|
||||||
return f"Function {{ subject_id: {self.subject_id}, params: [{params}], body: {self.body} }}"
|
return f"Function {{ subject_id: {self.subject_id}, params: [{params}], body: {self.body} }}"
|
||||||
|
|
||||||
class Return(Expr):
|
class Return(Expr):
|
||||||
|
18
parser.py
18
parser.py
@ -2,7 +2,7 @@ from tokens import Token, TokenType, TokenIterator
|
|||||||
from position import Position, Span, Node
|
from position import Position, Span, Node
|
||||||
from parsed import Assign, AssignType, Binary, BinaryType, Block, Break, Call, Continue, Match, MatchArm, PatternError, Expr, For, Id, If, Index, Int, Char, Loop, Pattern, Return, String, ExprError, StructMember, Tuple, TupleMember, Unary, UnaryType, Unit, While
|
from parsed import Assign, AssignType, Binary, BinaryType, Block, Break, Call, Continue, Match, MatchArm, PatternError, Expr, For, Id, If, Index, Int, Char, Loop, Pattern, Return, String, ExprError, StructMember, Tuple, TupleMember, Unary, UnaryType, Unit, While
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
from utils import Result, Ok, Err
|
from utils import Result, Ok, Err, unescape_string
|
||||||
|
|
||||||
|
|
||||||
class Parser:
|
class Parser:
|
||||||
@ -217,24 +217,28 @@ class Parser:
|
|||||||
def parse_operand(self) -> Node[Expr]:
|
def parse_operand(self) -> Node[Expr]:
|
||||||
if self.current_is(TokenType.Id):
|
if self.current_is(TokenType.Id):
|
||||||
token = self.current()
|
token = self.current()
|
||||||
value = token.text_slice(self.text)
|
|
||||||
self.step()
|
self.step()
|
||||||
|
value = token.text_slice(self.text)
|
||||||
return Node(Id(value), token.span)
|
return Node(Id(value), token.span)
|
||||||
elif self.current_is(TokenType.Int):
|
elif self.current_is(TokenType.Int):
|
||||||
token = self.current()
|
token = self.current()
|
||||||
value = int(token.text_slice(self.text))
|
|
||||||
self.step()
|
self.step()
|
||||||
|
value = int(token.text_slice(self.text))
|
||||||
return Node(Int(value), token.span)
|
return Node(Int(value), token.span)
|
||||||
elif self.current_is(TokenType.Char):
|
elif self.current_is(TokenType.Char):
|
||||||
token = self.current()
|
token = self.current()
|
||||||
value = token.text_slice(self.text)
|
|
||||||
self.step()
|
self.step()
|
||||||
return Node(Char(value), token.span)
|
value = unescape_string(token.text_slice(self.text)[1:-1])
|
||||||
|
if not value.ok():
|
||||||
|
return Node(ExprError(value.error()), token.span)
|
||||||
|
return Node(Char(value.value()), token.span)
|
||||||
elif self.current_is(TokenType.String):
|
elif self.current_is(TokenType.String):
|
||||||
token = self.current()
|
token = self.current()
|
||||||
value = token.text_slice(self.text)
|
|
||||||
self.step()
|
self.step()
|
||||||
return Node(String(value), token.span)
|
value = unescape_string(token.text_slice(self.text)[1:-1])
|
||||||
|
if not value.ok():
|
||||||
|
return Node(ExprError(value.error()), token.span)
|
||||||
|
return Node(String(value.value()), token.span)
|
||||||
elif self.current_is(TokenType.LParen):
|
elif self.current_is(TokenType.LParen):
|
||||||
return self.parse_unit_group_tuple()
|
return self.parse_unit_group_tuple()
|
||||||
elif self.current_is(TokenType.LBrace):
|
elif self.current_is(TokenType.LBrace):
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
from typing import NamedTuple, TypeVar, Generic
|
from typing import NamedTuple, TypeVar, Generic
|
||||||
|
|
||||||
|
|
||||||
class Position(NamedTuple):
|
class Position(NamedTuple):
|
||||||
index: int
|
index: int
|
||||||
line: int
|
line: int
|
||||||
col: int
|
col: int
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f"{self.line}:{self.col}"
|
||||||
|
|
||||||
class Span(NamedTuple):
|
class Span(NamedTuple):
|
||||||
begin: Position
|
begin: Position
|
||||||
end: Position
|
end: Position
|
||||||
@ -14,6 +16,9 @@ class Span(NamedTuple):
|
|||||||
def to(self, end: Span) -> Span:
|
def to(self, end: Span) -> Span:
|
||||||
return Span(self.begin, end.end)
|
return Span(self.begin, end.end)
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f"{self.begin} to {self.end}"
|
||||||
|
|
||||||
|
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
|
|
||||||
@ -25,4 +30,4 @@ class Node(Generic[T]):
|
|||||||
self.span = span
|
self.span = span
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return self.value.__str__()
|
return str(self.value)
|
||||||
|
44
utils.py
44
utils.py
@ -48,3 +48,47 @@ class Err(Result[T, E]):
|
|||||||
def error(self) -> E:
|
def error(self) -> E:
|
||||||
return self.__error
|
return self.__error
|
||||||
|
|
||||||
|
def unescape_string(value: str) -> Result[str, str]:
|
||||||
|
result = ""
|
||||||
|
i = 0
|
||||||
|
while i < len(value):
|
||||||
|
if value[i] == "\\":
|
||||||
|
i += 1
|
||||||
|
if i >= len(value):
|
||||||
|
return Err("unescaped '\\'")
|
||||||
|
elif value[i] == "0":
|
||||||
|
result += "\0"
|
||||||
|
elif value[i] == "n":
|
||||||
|
result += "\n"
|
||||||
|
elif value[i] == "t":
|
||||||
|
result += "\t"
|
||||||
|
elif value[i] == "r":
|
||||||
|
result += "\r"
|
||||||
|
else:
|
||||||
|
result += value[i]
|
||||||
|
else:
|
||||||
|
result += value[i]
|
||||||
|
i += 1
|
||||||
|
return Ok(result)
|
||||||
|
|
||||||
|
def escape_string(value: str) -> str:
|
||||||
|
result = ""
|
||||||
|
for char in value:
|
||||||
|
if char == "\0":
|
||||||
|
result += "\\0"
|
||||||
|
elif char == "\n":
|
||||||
|
result += "\\n"
|
||||||
|
elif char == "\t":
|
||||||
|
result += "\\t"
|
||||||
|
elif char == "\r":
|
||||||
|
result += "\\r"
|
||||||
|
elif char == "\"":
|
||||||
|
result += "\\\""
|
||||||
|
elif char == "\'":
|
||||||
|
result += "\\'"
|
||||||
|
elif char == "\\":
|
||||||
|
result += "\\\\"
|
||||||
|
else:
|
||||||
|
result += char
|
||||||
|
return result
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user