-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutils.py
140 lines (112 loc) · 4.03 KB
/
utils.py
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import string
LETTERS = string.ascii_letters
DIGITS = "0123456789"
NUMERALS = ".0123456789"
BOOL_VAR = {"true", "false"}
TT_INT = "INT"
TT_FLOAT = "FLOAT"
TT_STR = "STRING"
TT_BOOL = "BOOL"
TT_PLUS = "PLUS"
TT_MINUS = "MINUS"
TT_MUL = "MUL"
TT_DIV = "DIV"
TT_POW = "POW"
TT_LPAREN = "LPAREN"
TT_RPAREN = "RPAREN"
TT_COMMA = "COMMA"
TT_NEWLINE = "NEWLINE"
TT_IDENTIFIER = "IDENTIFIER"
TT_KEYWORD = "KEYWORD"
TT_EQUALS = "EQUALS"
TT_ISEQ = "ISEQ"
TT_NOTEQ = "NOTEQ"
TT_LT = "LT"
TT_GT = "GT"
TT_LTE = "LTE"
TT_GTE = "GTE"
DATA_TYPES = (TT_INT, TT_FLOAT, TT_STR, TT_BOOL)
NUM_DATA_TYPES = (TT_INT, TT_FLOAT)
ARITH_OP = (TT_PLUS, TT_MINUS, TT_MUL, TT_DIV, TT_POW)
PAREN = (TT_LPAREN, TT_RPAREN)
COMPARATORS = (TT_ISEQ, TT_NOTEQ, TT_LT, TT_GT, TT_LTE, TT_GTE)
KEYWORDS = ["and", "or", "not", "print", "true", "false",
"if", "then", "end", "elif", "else","for", "to", "step", "while", "do"]
def line_in_text(text: str, line: int) -> str:
lines = text.split("\n")
return lines[line - 1] if line - 1 < len(lines) else ""
class PrintError:
def __init__(self, text: str, error_name: str, details: str, line: int, start_col: int = None):
error_line = line_in_text(text, line) + "\n"
if start_col is None:
start_col = len(error_line)
wiggle = " " * (start_col - 1) + "^^" + "\n"
message = f"\n{error_line}{wiggle}\n{error_name}: {details}\nline {line}, column {start_col}"
raise Exception(message)
class Token:
def __init__(self, line: int = 0, start_col: int = 0, type_: str = None, value_: str = None):
self.line = line
self.start_col = start_col
self.type = type_
self.value = value_
def __repr__(self) -> str:
if self.type == TT_STR:
return f"{self.type}('{self.value}')"
return f"{self.type}({self.value})" if self.value is not None else self.type
def __eq__(self, other: "Token") -> bool:
if not isinstance(other, Token):
return False
return self.type == other.type and self.value == other.value
class Node:
def __init__(self, token: Token):
self.token = token
def __repr__(self) -> str:
return f"{self.token}"
class varAssignNode:
def __init__(self, var_name: Token, value: Node):
self.var_name = var_name
self.value = value
def __repr__(self) -> str:
return f"{{assign {self.var_name.value} = {self.value}}}"
class varAccessNode:
def __init__(self, var_name: Token):
self.var_name = var_name
def __repr__(self) -> str:
return f"{{access {self.var_name.value}}}"
class BinOpNode:
def __init__(self, op: Token, left_node: Node, right_node: Node):
self.op = op
self.left_node = left_node
self.right_node = right_node
def __repr__(self) -> str:
return f"{{{self.left_node} {self.op} {self.right_node}}}"
class printNode:
def __init__(self, tokens: list[Node|varAccessNode|varAssignNode|BinOpNode]):
self.tokens = tokens
def __repr__(self) -> str:
return f"{{print {self.tokens}}}"
class ifNode:
def __init__(self, if_case: list[Node], else_case: list[Node]):
self.if_case = if_case
self.else_case = else_case
def __repr__(self) -> str:
string = ""
string += f"if {self.if_case[0]} then {self.if_case[1]}\n"
if self.else_case != None:
string += f"else {self.else_case}"
return f"{string}"
class forNode:
def __init__(self, identifier: Token, start: Node, end: Node, step: Node, body: list[Node]):
self.identifier = identifier
self.start = start
self.end = end
self.step = step
self.body = body
def __repr__(self) -> str:
return f"for {self.start} to {self.end} step {self.step} do {self.body}"
class WhileNode:
def __init__(self, condition: Node, body: list[Node]):
self.condition = condition
self.body = body
def __repr__(self) -> str:
return f"while {self.condition} do {self.body}"