-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtesting.py
More file actions
122 lines (88 loc) · 3.03 KB
/
Copy pathtesting.py
File metadata and controls
122 lines (88 loc) · 3.03 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
112
113
114
115
116
117
118
119
120
121
122
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 | type # 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 = lexer.lex(source)
EOF = Token.EOF(SourcePosition(-1, -1, -1, -1, source), None)
parser = Parser(EOF)
parser.add_rule(NumberLiteral.ParserPattern).add_rule(SumNode.ParserPattern)
parsed_tokens = parser.parse(tokens, 0, 0)
print(parsed_tokens[0].value)
parsed_tokens[0].value.analyze_types({})
print(parsed_tokens[0].value.compile({}))