add parser
This commit is contained in:
parent
4f2bf4f2ba
commit
5135c149ef
81
parsed.py
81
parsed.py
@ -2,6 +2,15 @@ from enum import Enum, auto
|
|||||||
from position import Node
|
from position import Node
|
||||||
from typing import Optional, List
|
from typing import Optional, List
|
||||||
|
|
||||||
|
class Type:
|
||||||
|
def __str__(self) -> str:
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
class TypeError(Type):
|
||||||
|
def __init__(self, message: str) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.message = message
|
||||||
|
|
||||||
class Pattern:
|
class Pattern:
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
@ -11,6 +20,14 @@ class PatternError(Pattern):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.message = message
|
self.message = message
|
||||||
|
|
||||||
|
class Parameter:
|
||||||
|
def __init__(self, subject: Pattern, value_type: Type) -> None:
|
||||||
|
self.subject = subject
|
||||||
|
self.value_type = value_type
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f"Parameter {{ subject: {self.subject}, value_type: {self.value_type} }}"
|
||||||
|
|
||||||
class Expr:
|
class Expr:
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
@ -76,6 +93,14 @@ class Unit(Expr):
|
|||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return "Unit"
|
return "Unit"
|
||||||
|
|
||||||
|
class Tuple(Expr):
|
||||||
|
def __init__(self, values: List[Node[Expr]]) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.values = values
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
values = ", ".join(node.__str__() for node in self.values)
|
||||||
|
return f"Tuple {{ values: [{values}] }}"
|
||||||
|
|
||||||
class Block(Expr):
|
class Block(Expr):
|
||||||
def __init__(self, statements: List[Node[Expr]], value: Optional[Node[Expr]]) -> None:
|
def __init__(self, statements: List[Node[Expr]], value: Optional[Node[Expr]]) -> None:
|
||||||
@ -87,6 +112,16 @@ class Block(Expr):
|
|||||||
statements = ", ".join(node.__str__() for node in self.statements)
|
statements = ", ".join(node.__str__() for node in self.statements)
|
||||||
return f"Block {{ statements: [{statements}], value: {self.value} }}"
|
return f"Block {{ statements: [{statements}], value: {self.value} }}"
|
||||||
|
|
||||||
|
class Lambda(Expr):
|
||||||
|
def __init__(self, params: List[Node[Parameter]], body: Node[Expr]) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.params = params
|
||||||
|
self.body = body
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
params = ", ".join(node.__str__() for node in self.params)
|
||||||
|
return f"Lambda {{ params: [{params}], body: {self.body} }}"
|
||||||
|
|
||||||
|
|
||||||
class If(Expr):
|
class If(Expr):
|
||||||
def __init__(self, condition: Node[Expr], truthy: Node[Expr], falsy: Optional[Node[Expr]]) -> None:
|
def __init__(self, condition: Node[Expr], truthy: Node[Expr], falsy: Optional[Node[Expr]]) -> None:
|
||||||
@ -238,3 +273,49 @@ class Assign(Expr):
|
|||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
return f"Assign {{ assign_type: {self.assign_type}, subject: {self.subject}, value: {self.value} }}"
|
return f"Assign {{ assign_type: {self.assign_type}, subject: {self.subject}, value: {self.value} }}"
|
||||||
|
|
||||||
|
class Let(Expr):
|
||||||
|
def __init__(self, subject: Node[Pattern], value_type: Optional[Node[Type]], value: Node[Expr]) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.subject = subject
|
||||||
|
self.value_type = value_type
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f"Let {{ subject: {self.subject}, value_type: {self.value_type}, value: {self.value} }}"
|
||||||
|
|
||||||
|
class Function(Expr):
|
||||||
|
def __init__(self, subject_id: str, params: List[Node[Parameter]], body: Node[Expr]) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.subject_id = subject_id
|
||||||
|
self.params = params
|
||||||
|
self.body = body
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
params = ", ".join(node.__str__() for node in self.params)
|
||||||
|
return f"Function {{ subject_id: {self.subject_id}, params: [{params}], body: {self.body} }}"
|
||||||
|
|
||||||
|
class Return(Expr):
|
||||||
|
def __init__(self, value: Optional[Node[Expr]]) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f"Return {{ value: {self.value} }}"
|
||||||
|
|
||||||
|
class Break(Expr):
|
||||||
|
def __init__(self, value: Optional[Node[Expr]]) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f"Break {{ value: {self.value} }}"
|
||||||
|
|
||||||
|
class Continue(Expr):
|
||||||
|
def __init__(self, value: Optional[Node[Expr]]) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return f"Continue {{ value: {self.value} }}"
|
||||||
|
|
||||||
|
113
parser.py
113
parser.py
@ -1,7 +1,8 @@
|
|||||||
from tokens import Token, TokenType, TokenIterator
|
from tokens import Token, TokenType, TokenIterator
|
||||||
from position import Span, Node
|
from position import Position, Span, Node
|
||||||
from parsed import Assign, AssignType, Binary, BinaryType, Block, Call, MatchArm, PatternError, Expr, For, Id, If, Index, Int, Char, Loop, Pattern, String, ExprError, StructMember, TupleMember, Unary, UnaryType, 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
|
||||||
|
|
||||||
|
|
||||||
class Parser:
|
class Parser:
|
||||||
@ -234,6 +235,8 @@ class Parser:
|
|||||||
value = token.text_slice(self.text)
|
value = token.text_slice(self.text)
|
||||||
self.step()
|
self.step()
|
||||||
return Node(String(value), token.span)
|
return Node(String(value), token.span)
|
||||||
|
elif self.current_is(TokenType.LParen):
|
||||||
|
return self.parse_unit_group_tuple()
|
||||||
elif self.current_is(TokenType.LBrace):
|
elif self.current_is(TokenType.LBrace):
|
||||||
return self.parse_block()
|
return self.parse_block()
|
||||||
elif self.current_is(TokenType.KwIf):
|
elif self.current_is(TokenType.KwIf):
|
||||||
@ -249,6 +252,38 @@ class Parser:
|
|||||||
self.step()
|
self.step()
|
||||||
return Node(ExprError("expected value"), token.span)
|
return Node(ExprError("expected value"), token.span)
|
||||||
|
|
||||||
|
def parse_unit_group_tuple(self) -> Node[Expr]:
|
||||||
|
begin = self.current().span
|
||||||
|
self.step()
|
||||||
|
if self.current_is(TokenType.RParen):
|
||||||
|
end = self.current().span
|
||||||
|
self.step()
|
||||||
|
return Node(Unit(), begin.to(end))
|
||||||
|
else:
|
||||||
|
first_expr = self.parse_expr()
|
||||||
|
if self.current_is(TokenType.RParen):
|
||||||
|
end = self.current().span
|
||||||
|
self.step()
|
||||||
|
return Node(first_expr.value, begin.to(end))
|
||||||
|
elif self.current_is(TokenType.Comma):
|
||||||
|
values = [first_expr]
|
||||||
|
end = self.current().span
|
||||||
|
while self.current_is(TokenType.Comma):
|
||||||
|
end = self.current().span
|
||||||
|
self.step()
|
||||||
|
if self.done() or self.current().token_type == TokenType.RParen:
|
||||||
|
break
|
||||||
|
value = self.parse_expr()
|
||||||
|
end = value.span
|
||||||
|
values.append(value)
|
||||||
|
if not self.current_is(TokenType.RParen):
|
||||||
|
return Node(ExprError("expected ')'"), begin.to(end))
|
||||||
|
end = self.current().span
|
||||||
|
self.step()
|
||||||
|
return Node(Tuple(values), begin.to(end))
|
||||||
|
else:
|
||||||
|
return Node(ExprError("expected ')' or ','"), begin.to(first_expr.span))
|
||||||
|
|
||||||
def parse_block(self) -> Node[Expr]:
|
def parse_block(self) -> Node[Expr]:
|
||||||
begin = self.current().span
|
begin = self.current().span
|
||||||
self.step()
|
self.step()
|
||||||
@ -288,17 +323,58 @@ class Parser:
|
|||||||
def parse_match(self) -> Node[Expr]:
|
def parse_match(self) -> Node[Expr]:
|
||||||
begin = self.current().span
|
begin = self.current().span
|
||||||
self.step()
|
self.step()
|
||||||
|
value = self.parse_expr()
|
||||||
if not self.current_is(TokenType.LBrace):
|
if not self.current_is(TokenType.LBrace):
|
||||||
return Node(ExprError("expected '{'"), begin)
|
return Node(ExprError("expected '{'"), begin)
|
||||||
|
lbrace_span = self.current().span
|
||||||
self.step()
|
self.step()
|
||||||
arms: List[Node[MatchArm]] = []
|
arms: List[Node[MatchArm]] = []
|
||||||
if not self.done() and self.current() != TokenType.RBrace:
|
if not self.done() and self.current() != TokenType.RBrace:
|
||||||
|
arm = self.parse_match_arm()
|
||||||
|
if not arm.ok():
|
||||||
|
return Node(ExprError(arm.error().value), begin.to(arm.error().span))
|
||||||
|
arms.append(arm.value())
|
||||||
|
while not self.done() and self.current() != TokenType.RBrace:
|
||||||
|
arm = self.parse_match_arm()
|
||||||
|
if not arm.ok():
|
||||||
|
return Node(ExprError(arm.error().value), begin.to(arm.error().span))
|
||||||
|
arms.append(arm.value())
|
||||||
|
if not self.current_is(TokenType.RBrace):
|
||||||
|
if len(arms) > 0:
|
||||||
|
end = arms[-1].span
|
||||||
|
else:
|
||||||
|
end = lbrace_span
|
||||||
|
return Node(ExprError("expected '}'"), begin.to(end))
|
||||||
|
rbrace_span = self.current().span
|
||||||
|
self.step()
|
||||||
|
return Node(Match(value, arms), begin.to(rbrace_span))
|
||||||
|
|
||||||
def parse_match_arm(self) -> Node[MatchArm]:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def parse_match_arm_statement(self) -> Node[Expr]:
|
def parse_match_arm(self) -> Result[Node[MatchArm], Node[str]]:
|
||||||
pass
|
pattern = self.parse_pattern()
|
||||||
|
if not self.current_is(TokenType.EqualLT):
|
||||||
|
return Err(Node("expected '=>'", pattern.span.to(pattern.span)))
|
||||||
|
self.step()
|
||||||
|
if self.current_is(TokenType.LParen):
|
||||||
|
expr = self.parse_block()
|
||||||
|
if self.current_is(TokenType.Comma):
|
||||||
|
self.step()
|
||||||
|
else:
|
||||||
|
expr = self.parse_match_arm_expr()
|
||||||
|
if not self.current_is(TokenType.Comma):
|
||||||
|
return Err(Node("expected ','", pattern.span.to(expr.span)))
|
||||||
|
self.step()
|
||||||
|
return Ok(Node(MatchArm(pattern, expr), pattern.span.to(expr.span)))
|
||||||
|
|
||||||
|
def parse_match_arm_expr(self) -> Node[Expr]:
|
||||||
|
if self.current_is(TokenType.KwReturn):
|
||||||
|
return self.parse_return()
|
||||||
|
elif self.current_is(TokenType.KwBreak):
|
||||||
|
return self.parse_break()
|
||||||
|
elif self.current_is(TokenType.KwContinue):
|
||||||
|
return self.parse_continue()
|
||||||
|
else:
|
||||||
|
return self.parse_expr()
|
||||||
|
|
||||||
def parse_loop(self) -> Node[Expr]:
|
def parse_loop(self) -> Node[Expr]:
|
||||||
begin = self.current().span
|
begin = self.current().span
|
||||||
@ -332,6 +408,31 @@ class Parser:
|
|||||||
body = self.parse_block()
|
body = self.parse_block()
|
||||||
return Node(For(subject, value, body), begin.to(body.span))
|
return Node(For(subject, value, body), begin.to(body.span))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def parse_return(self) -> Node[Expr]:
|
||||||
|
begin = self.current().span
|
||||||
|
self.step()
|
||||||
|
value: Optional[Node[Expr]] = None
|
||||||
|
if not self.done() and self.current() not in [TokenType.Comma, TokenType.Semicolon]:
|
||||||
|
value = self.parse_expr()
|
||||||
|
return Node(Return(value), begin.to(value.span if value is not None else begin))
|
||||||
|
|
||||||
|
def parse_break(self) -> Node[Expr]:
|
||||||
|
begin = self.current().span
|
||||||
|
self.step()
|
||||||
|
value: Optional[Node[Expr]] = None
|
||||||
|
if not self.done() and self.current() not in [TokenType.Comma, TokenType.Semicolon]:
|
||||||
|
value = self.parse_expr()
|
||||||
|
return Node(Break(value), begin.to(value.span if value is not None else begin))
|
||||||
|
|
||||||
|
def parse_continue(self) -> Node[Expr]:
|
||||||
|
begin = self.current().span
|
||||||
|
self.step()
|
||||||
|
value: Optional[Node[Expr]] = None
|
||||||
|
if not self.done() and self.current() not in [TokenType.Comma, TokenType.Semicolon]:
|
||||||
|
value = self.parse_expr()
|
||||||
|
return Node(Continue(value), begin.to(value.span if value is not None else begin))
|
||||||
def parse_pattern(self) -> Node[Pattern]:
|
def parse_pattern(self) -> Node[Pattern]:
|
||||||
return Node(PatternError("not implemented"), self.current().span)
|
return Node(PatternError("not implemented"), self.current().span)
|
||||||
|
|
||||||
|
50
utils.py
Normal file
50
utils.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
from typing import Generic, TypeVar
|
||||||
|
|
||||||
|
class UnwrapException(Exception):
|
||||||
|
def __init__(self, *args: object) -> None:
|
||||||
|
super().__init__(*args)
|
||||||
|
|
||||||
|
T = TypeVar("T")
|
||||||
|
E = TypeVar("E")
|
||||||
|
|
||||||
|
class Result(Generic[T, E]):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def ok(self) -> bool:
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def value(self) -> T:
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def error(self) -> E:
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
class Ok(Result[T, E]):
|
||||||
|
def __init__(self, value: T) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.__value = value
|
||||||
|
|
||||||
|
def ok(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def value(self) -> T:
|
||||||
|
return self.__value
|
||||||
|
|
||||||
|
def error(self) -> E:
|
||||||
|
raise UnwrapException("cannot unwrap error of ok result")
|
||||||
|
|
||||||
|
class Err(Result[T, E]):
|
||||||
|
def __init__(self, error: E) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.__error = error
|
||||||
|
|
||||||
|
def ok(self) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def value(self) -> T:
|
||||||
|
raise UnwrapException("cannot unwrap value of error result")
|
||||||
|
|
||||||
|
def error(self) -> E:
|
||||||
|
return self.__error
|
||||||
|
|
Loading…
Reference in New Issue
Block a user