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 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))

View File

@ -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()

View File

@ -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):

View File

@ -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):

View File

@ -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)

View File

@ -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