-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtesting.py
More file actions
111 lines (77 loc) · 2.97 KB
/
testing.py
File metadata and controls
111 lines (77 loc) · 2.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
from typing import Any
from compilertoolkit.ast import AbstractAstNode, abstractcompilationstep, compilationstep
from compilertoolkit.parsing import ParseThenCheck, Parser, ParsingPattern, TokenHasType
from compilertoolkit.tokens import Ignore, Source, SourcePosition, TokenEnum, TokenType, create_lexer
class Token[T](TokenEnum[T]):
"""Part of our own Stuff"""
Comma: TokenType[str] = TokenType(pattern=r"\,")
Number: TokenType[str] = TokenType(pattern=r"\d+")
Keyword: TokenType[str] = TokenType(pattern=r"\w+")
Plus: TokenType[str] = TokenType(pattern=r"\+")
Expression: TokenType["ExpressionNode"] = TokenType()
Statement: TokenType["AstNode"] = TokenType()
EOF: TokenType[None] = TokenType()
whitespace = Ignore(r"\s+") # ignore all whitespace
class AstNode(AbstractAstNode):
"""Basic Ast Node"""
__slots__ = ()
@abstractcompilationstep(0)
def analyze_types(self, ctx):
pass
@abstractcompilationstep(1)
def compile(self, ctx) -> Any:
pass
class ExpressionNode(AstNode):
"""Basic Ast Node"""
__slots__ = "return_type"
# instance variables
return_type: None # Your own type class
class NumberLiteral(ExpressionNode):
"""Basic Ast Node"""
__slots__ = "value"
class ParserPattern(ParsingPattern, token_type=Token.Expression):
value = TokenHasType(Token.Number)
# instance variables
value: int
def __init__(self, tokens: ParserPattern):
super().__init__(tokens)
self.value = int(tokens.value.value)
@compilationstep
def analyze_types(self, ctx):
self.return_type = int
@compilationstep
def compile(self, ctx):
return self.value
class SumNode(ExpressionNode):
"""Basic Ast Node"""
__slots__ = ("lhs", "rhs")
class ParserPattern(ParsingPattern, token_type=Token.Expression, precedence=1):
lhs = TokenHasType(Token.Expression)
operation = TokenHasType(Token.Plus)
# Parses, then checks for the specified case, errors if the value of the token is unparsed
rhs = ParseThenCheck(TokenHasType(Token.Expression))
# instance variables
lhs: ExpressionNode
rhs: ExpressionNode
def __init__(self, tokens: ParserPattern):
super().__init__(tokens)
self.rhs = tokens.rhs.value
self.lhs = tokens.lhs.value
@compilationstep
def analyze_types(self, ctx):
self.lhs.analyze_types(ctx)
self.rhs.analyze_types(ctx)
self.return_type = int
@compilationstep
def compile(self, ctx):
return self.lhs.compile(ctx) + self.rhs.compile(ctx)
source = Source("8 + 12")
lexer = create_lexer(Token)
tokens: list[Token[Any]] = lexer.lex(source)
parser = Parser(Token.EOF(SourcePosition(-1, -1, -1, -1, Source("")), None))
parser.add_rule(NumberLiteral.ParserPattern)\
.add_rule(SumNode.ParserPattern)
tokens = parser.parse(tokens, 0, 0)
print(tokens[0].value)
tokens[0].value.analyze_types({})
print(tokens[0].value.compile({}))