add more evaluator

This commit is contained in:
SimonFJ20 2023-04-10 04:20:05 +02:00
parent dd527edbc4
commit 15e6fb864d
6 changed files with 131 additions and 52 deletions

View File

@ -1,10 +1,15 @@
from typing import List, Optional
from typing import Dict, List, Optional, cast
from position import Node
from utils import Err, Ok, Result
import parsed
class Value:
pass
class Unit(Value):
def __init__(self) -> None:
super().__init__()
class Int(Value):
def __init__(self, value: int) -> None:
super().__init__()
@ -48,6 +53,20 @@ class ContinueResult(EvalResult):
super().__init__()
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:
def __init__(self) -> None:
pass
@ -57,60 +76,60 @@ class Evaluator:
self.eval_expr(node)
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()
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()
elif node.value is parsed.Int:
elif isinstance(node.value, parsed.Block):
raise NotImplementedError()
elif node.value is parsed.Char:
elif isinstance(node.value, parsed.Lambda):
raise NotImplementedError()
elif node.value is parsed.String:
elif isinstance(node.value, parsed.If):
raise NotImplementedError()
elif node.value is parsed.Bool:
elif isinstance(node.value, parsed.Match):
raise NotImplementedError()
elif node.value is parsed.Unit:
elif isinstance(node.value, parsed.Loop):
raise NotImplementedError()
elif node.value is parsed.Tuple:
elif isinstance(node.value, parsed.While):
raise NotImplementedError()
elif node.value is parsed.Block:
elif isinstance(node.value, parsed.For):
raise NotImplementedError()
elif node.value is parsed.Lambda:
elif isinstance(node.value, parsed.StructMember):
raise NotImplementedError()
elif node.value is parsed.If:
elif isinstance(node.value, parsed.TupleMember):
raise NotImplementedError()
elif node.value is parsed.Match:
elif isinstance(node.value, parsed.Index):
raise NotImplementedError()
elif node.value is parsed.Loop:
elif isinstance(node.value, parsed.Call):
raise NotImplementedError()
elif node.value is parsed.While:
elif isinstance(node.value, parsed.Unary):
raise NotImplementedError()
elif node.value is parsed.For:
elif isinstance(node.value, parsed.Binary):
raise NotImplementedError()
elif node.value is parsed.StructMember:
elif isinstance(node.value, parsed.Assign):
raise NotImplementedError()
elif node.value is parsed.TupleMember:
elif isinstance(node.value, parsed.Let):
raise NotImplementedError()
elif node.value is parsed.Index:
elif isinstance(node.value, parsed.Function):
raise NotImplementedError()
elif node.value is parsed.Call:
elif isinstance(node.value, parsed.Return):
raise NotImplementedError()
elif node.value is parsed.Unary:
elif isinstance(node.value, parsed.Break):
raise NotImplementedError()
elif node.value is parsed.Binary:
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:
elif isinstance(node.value, parsed.Continue):
raise NotImplementedError()
else:
raise NotImplementedError()
raise NotImplementedError(str(node))

View File

@ -1,14 +1,20 @@
from lexer import Lexer
from parser import Parser
from evaluator import Evaluator
def main() -> None:
text = "\"\\\"hello\\\\\""
text = "\"hello\""
lexer = Lexer(text)
parser = Parser(text, lexer)
print("parsing...")
parsed = parser.parse()
print("ast = ")
for node in parsed:
print(node)
evaluator = Evaluator()
print("evaluating...")
evaluator.evaluate(parsed)
if __name__ == "__main__":
main()

View File

@ -1,6 +1,7 @@
from enum import Enum, auto
from position import Node
from typing import Optional, List
from utils import escape_string
class Type:
def __str__(self) -> str:
@ -64,7 +65,7 @@ class Char(Expr):
self.value = value
def __str__(self) -> str:
return f"Char('{self.value}')"
return f"Char('{escape_string(self.value)}')"
class String(Expr):
@ -73,7 +74,7 @@ class String(Expr):
self.value = value
def __str__(self) -> str:
return f"String(\"{self.value}\")"
return f"String(\"{escape_string(self.value)}\")"
class Bool(Expr):
@ -99,7 +100,7 @@ class Tuple(Expr):
self.values = values
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}] }}"
class Block(Expr):
@ -109,7 +110,7 @@ class Block(Expr):
self.value = value
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} }}"
class Lambda(Expr):
@ -119,7 +120,7 @@ class Lambda(Expr):
self.body = body
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} }}"
@ -205,7 +206,7 @@ class Call(Expr):
self.arguments = arguments
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} }}"
class UnaryType(Enum):
@ -292,7 +293,7 @@ class Function(Expr):
self.body = body
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} }}"
class Return(Expr):

View File

@ -2,7 +2,7 @@ from tokens import Token, TokenType, TokenIterator
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 typing import List, Optional
from utils import Result, Ok, Err
from utils import Result, Ok, Err, unescape_string
class Parser:
@ -217,24 +217,28 @@ class Parser:
def parse_operand(self) -> Node[Expr]:
if self.current_is(TokenType.Id):
token = self.current()
value = token.text_slice(self.text)
self.step()
value = token.text_slice(self.text)
return Node(Id(value), token.span)
elif self.current_is(TokenType.Int):
token = self.current()
value = int(token.text_slice(self.text))
self.step()
value = int(token.text_slice(self.text))
return Node(Int(value), token.span)
elif self.current_is(TokenType.Char):
token = self.current()
value = token.text_slice(self.text)
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):
token = self.current()
value = token.text_slice(self.text)
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):
return self.parse_unit_group_tuple()
elif self.current_is(TokenType.LBrace):

View File

@ -1,12 +1,14 @@
from __future__ import annotations
from typing import NamedTuple, TypeVar, Generic
class Position(NamedTuple):
index: int
line: int
col: int
def __str__(self) -> str:
return f"{self.line}:{self.col}"
class Span(NamedTuple):
begin: Position
end: Position
@ -14,6 +16,9 @@ class Span(NamedTuple):
def to(self, end: Span) -> Span:
return Span(self.begin, end.end)
def __str__(self) -> str:
return f"{self.begin} to {self.end}"
T = TypeVar("T")
@ -25,4 +30,4 @@ class Node(Generic[T]):
self.span = span
def __str__(self) -> str:
return self.value.__str__()
return str(self.value)

View File

@ -48,3 +48,47 @@ class Err(Result[T, E]):
def error(self) -> E:
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