lucidaflow 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of lucidaflow might be problematic. Click here for more details.

@@ -0,0 +1,248 @@
1
+ T_INT, T_FLOAT, T_STRING, T_IDENTIFIER, T_KEYWORD = 'INT', 'FLOAT', 'STRING', 'IDENTIFIER', 'KEYWORD'
2
+ T_PLUS, T_MINUS, T_MUL, T_DIV, T_POW, T_MOD = 'PLUS', 'MINUS', 'MUL', 'DIV', 'POW', 'MOD'
3
+ T_ASSIGN, T_EQ, T_NE, T_LT, T_GT, T_LTE, T_GTE = 'ASSIGN', 'EQ', 'NE', 'LT', 'GT', 'LTE', 'GTE'
4
+ T_PLUS_ASSIGN, T_MINUS_ASSIGN, T_MUL_ASSIGN, T_DIV_ASSIGN, T_POW_ASSIGN, T_MOD_ASSIGN = 'PLUS_ASSIGN', 'MINUS_ASSIGN', 'MUL_ASSIGN', 'DIV_ASSIGN', 'POW_ASSIGN', 'MOD_ASSIGN'
5
+ T_LPAREN, T_RPAREN, T_LBRACE, T_RBRACE, T_LBRACKET, T_RBRACKET = 'LPAREN', 'RPAREN', 'LBRACE', 'RBRACE', 'LBRACKET', 'RBRACKET'
6
+ T_COMMA, T_COLON, T_ARROW, T_DOT, T_QUESTION, T_EOF = 'COMMA', 'COLON', 'ARROW', 'DOT', 'QUESTION', 'EOF'
7
+ T_AMPERSAND, T_PIPE, T_CARET, T_TILDE, T_LSHIFT, T_RSHIFT = 'AMPERSAND', 'PIPE', 'CARET', 'TILDE', 'LSHIFT', 'RSHIFT'
8
+ T_F_STRING = 'F_STRING'
9
+
10
+ class Token:
11
+ """Um Token agora carrega seu tipo, valor e sua localização no código-fonte."""
12
+ def __init__(self, type, value=None, line=0, col=0):
13
+ self.type = type
14
+ self.value = value
15
+ self.line = line
16
+ self.col = col
17
+
18
+ def __repr__(self):
19
+ # A nova representação ajuda muito no debugging!
20
+ return f'Token({self.type}, {repr(self.value)}, L{self.line}:C{self.col})'
21
+
22
+ class Lexer:
23
+ def __init__(self, text):
24
+ self.text = text
25
+ self.pos = 0
26
+ self.current_char = self.text[self.pos] if self.pos < len(self.text) else None
27
+ # Adicionamos os contadores de linha e coluna
28
+ self.line = 1
29
+ self.col = 1
30
+ self.KEYWORDS = {
31
+ 'let': Token(T_KEYWORD, 'let'),
32
+ 'const': Token(T_KEYWORD, 'const'),
33
+ 'when': Token(T_KEYWORD, 'when'),
34
+ 'else': Token(T_KEYWORD, 'else'),
35
+ 'otherwise': Token(T_KEYWORD, 'otherwise'),
36
+ 'for': Token(T_KEYWORD, 'for'),
37
+ 'each': Token(T_KEYWORD, 'each'),
38
+ 'in': Token(T_KEYWORD, 'in'),
39
+ 'while': Token(T_KEYWORD, 'while'),
40
+ 'define': Token(T_KEYWORD, 'define'),
41
+ 'process': Token(T_KEYWORD, 'process'),
42
+ 'type': Token(T_KEYWORD, 'type'),
43
+ 'return': Token(T_KEYWORD, 'return'),
44
+ 'true': Token(T_KEYWORD, 'true'),
45
+ 'false': Token(T_KEYWORD, 'false'),
46
+ 'and': Token(T_KEYWORD, 'and'),
47
+ 'or': Token(T_KEYWORD, 'or'),
48
+ 'not': Token(T_KEYWORD, 'not'),
49
+ 'null': Token(T_KEYWORD, 'null'),
50
+ 'break': Token(T_KEYWORD, 'break'),
51
+ 'continue': Token(T_KEYWORD, 'continue'),
52
+ 'import': Token(T_KEYWORD, 'import'),
53
+ 'as': Token(T_KEYWORD, 'as'),
54
+ 'self': Token(T_KEYWORD, 'self'),
55
+ 'super': Token(T_KEYWORD, 'super'),
56
+ 'enum': Token(T_KEYWORD, 'enum'),
57
+ 'try': Token(T_KEYWORD, 'try'), # <--- ADICIONE
58
+ 'catch': Token(T_KEYWORD, 'catch'), # <--- ADICIONE
59
+ 'finally': Token(T_KEYWORD, 'finally') # <--- ADICIONE
60
+ }
61
+
62
+ def error(self, msg='Caractere inválido'):
63
+ raise Exception(f'{msg}: {self.current_char}')
64
+
65
+ def advance(self):
66
+ """Avança o ponteiro e atualiza os contadores de linha/coluna."""
67
+ if self.current_char is not None:
68
+ if self.current_char == '\n':
69
+ self.line += 1
70
+ self.col = 0 # A coluna é resetada após a quebra de linha
71
+
72
+ self.pos += 1
73
+ self.col += 1 # A coluna sempre avança com o caractere
74
+
75
+ self.current_char = self.text[self.pos] if self.pos < len(self.text) else None
76
+
77
+ def peek(self):
78
+ peek_pos = self.pos + 1
79
+ return self.text[peek_pos] if peek_pos < len(self.text) else None
80
+
81
+ def skip_whitespace(self):
82
+ while self.current_char is not None and self.current_char.isspace():
83
+ self.advance()
84
+
85
+ def skip_comment(self):
86
+ while self.current_char is not None and self.current_char != '\n':
87
+ self.advance()
88
+
89
+ def _number(self):
90
+ result = ''
91
+ while self.current_char is not None and self.current_char.isdigit():
92
+ result += self.current_char
93
+ self.advance()
94
+ if self.current_char == '.':
95
+ result += '.'
96
+ self.advance()
97
+ while self.current_char is not None and self.current_char.isdigit():
98
+ result += self.current_char
99
+ self.advance()
100
+ if '.' in result:
101
+ return Token(T_FLOAT, float(result))
102
+ else:
103
+ return Token(T_INT, int(result))
104
+
105
+ def _string(self):
106
+ result = ''
107
+ self.advance() # Pula o " inicial
108
+ while self.current_char is not None and self.current_char != '"':
109
+ result += self.current_char
110
+ self.advance()
111
+ self.advance() # Pula o " final
112
+ return Token(T_STRING, result)
113
+
114
+ def _identifier(self):
115
+ start_line, start_col = self.line, self.col # Guarda a posição inicial
116
+ result = ''
117
+ while self.current_char is not None and (self.current_char.isalnum() or self.current_char == '_'):
118
+ result += self.current_char
119
+ self.advance()
120
+
121
+ # Pega o token do keyword ou cria um novo IDENTIFIER, passando a posição
122
+ token = self.KEYWORDS.get(result, Token(T_IDENTIFIER, result, start_line, start_col))
123
+
124
+ # Se o token veio do dicionário, ele não tem posição, então atualizamos
125
+ token.line = start_line
126
+ token.col = start_col
127
+
128
+ return token
129
+
130
+ def peek_token(self):
131
+ saved_pos = self.pos
132
+ saved_char = self.current_char
133
+ token = self.get_next_token()
134
+ self.pos = saved_pos
135
+ self.current_char = saved_char
136
+ return token
137
+
138
+ def get_next_token(self):
139
+ while self.current_char is not None:
140
+ if self.current_char.isspace():
141
+ self.skip_whitespace()
142
+ continue
143
+ if (self.current_char == '/' and self.peek() == '/') or self.current_char == '#':
144
+ self.skip_comment()
145
+ continue
146
+ if self.current_char == 'f' and self.peek() == '"':
147
+ return self._f_string()
148
+ if self.current_char.isdigit():
149
+ return self._number()
150
+ if self.current_char in ('"', "'"):
151
+ return self._string()
152
+ if self.current_char.isalnum() or self.current_char == '_':
153
+ return self._identifier()
154
+
155
+ # Operadores de múltiplos caracteres
156
+ if self.current_char == '=' and self.peek() == '=':
157
+ self.advance(); self.advance(); return Token(T_EQ, '==')
158
+ if self.current_char == '!' and self.peek() == '=':
159
+ self.advance(); self.advance(); return Token(T_NE, '!=')
160
+ if self.current_char == '<' and self.peek() == '=':
161
+ self.advance(); self.advance(); return Token(T_LTE, '<=')
162
+ if self.current_char == '>' and self.peek() == '=':
163
+ self.advance(); self.advance(); return Token(T_GTE, '>=')
164
+ if self.current_char == '-' and self.peek() == '>':
165
+ self.advance(); self.advance(); return Token(T_ARROW, '->')
166
+ if self.current_char == '+' and self.peek() == '=':
167
+ self.advance(); self.advance(); return Token(T_PLUS_ASSIGN, '+=')
168
+ if self.current_char == '-' and self.peek() == '=':
169
+ self.advance(); self.advance(); return Token(T_MINUS_ASSIGN, '-=')
170
+ if self.current_char == '*' and self.peek() == '=':
171
+ self.advance(); self.advance(); return Token(T_MUL_ASSIGN, '*=')
172
+ if self.current_char == '/' and self.peek() == '=':
173
+ self.advance(); self.advance(); return Token(T_DIV_ASSIGN, '/=')
174
+ if self.current_char == '*' and self.peek() == '*':
175
+ self.advance()
176
+ if self.peek() == '=':
177
+ self.advance(); self.advance(); return Token(T_POW_ASSIGN, '**=')
178
+ self.advance(); return Token(T_POW, '**')
179
+ if self.current_char == '%' and self.peek() == '=':
180
+ self.advance(); self.advance(); return Token(T_MOD_ASSIGN, '%=')
181
+ if self.current_char == '<' and self.peek() == '<':
182
+ self.advance(); self.advance(); return Token(T_LSHIFT, '<<')
183
+ if self.current_char == '>' and self.peek() == '>':
184
+ self.advance(); self.advance(); return Token(T_RSHIFT, '>>')
185
+
186
+ start_line, start_col = self.line, self.col
187
+ if self.current_char == '=' and self.peek() == '=': self.advance(); self.advance(); return Token(T_EQ, '==', start_line, start_col)
188
+
189
+ # Operadores de um caractere
190
+ token_map = {'+':T_PLUS,'-':T_MINUS,'*':T_MUL,'/':T_DIV,'%':T_MOD,'(':T_LPAREN,')':T_RPAREN,'{':T_LBRACE,'}':T_RBRACE,'[':T_LBRACKET,']':T_RBRACKET,',':T_COMMA,':':T_COLON,'.':T_DOT,'=':T_ASSIGN,'<':T_LT,'>':T_GT, '&':T_AMPERSAND, '|':T_PIPE, '^':T_CARET, '~':T_TILDE, '?':T_QUESTION}
191
+ if self.current_char in token_map:
192
+ char = self.current_char
193
+ start_line, start_col = self.line, self.col # Guarda a posição
194
+ self.advance()
195
+ return Token(token_map[char], char, start_line, start_col)
196
+
197
+ self.error()
198
+ return Token(T_EOF)
199
+
200
+ def _string(self):
201
+ start_line, start_col = self.line, self.col
202
+ result = ''
203
+ quote_char = self.current_char # Salva o caractere de aspas (' ou ")
204
+ self.advance() # Pula a aspa inicial
205
+
206
+ while self.current_char is not None and self.current_char != quote_char:
207
+ # --- LÓGICA DE ESCAPE ---
208
+ if self.current_char == '\\':
209
+ self.advance() # Pula a barra
210
+ if self.current_char == 'n':
211
+ result += '\n'
212
+ elif self.current_char == 't':
213
+ result += '\t'
214
+ elif self.current_char == quote_char: # Escapando a própria aspa
215
+ result += quote_char
216
+ elif self.current_char == '\\':
217
+ result += '\\'
218
+ else:
219
+ # Se for uma sequência desconhecida, apenas adiciona o caractere literal
220
+ result += self.current_char
221
+ else:
222
+ result += self.current_char
223
+ # --- FIM DA LÓGICA DE ESCAPE ---
224
+ self.advance()
225
+
226
+ if self.current_char is None:
227
+ self.error(f"String iniciada com {quote_char} não foi fechada.")
228
+
229
+ self.advance() # Pula a aspa final
230
+ return Token(T_STRING, result, start_line, start_col)
231
+
232
+ def _f_string(self):
233
+ start_line, start_col = self.line, self.col
234
+ self.advance() # Consome o 'f'
235
+ self.advance() # Consome o '"' inicial
236
+
237
+ result = ''
238
+ while self.current_char is not None and self.current_char != '"':
239
+ result += self.current_char
240
+ self.advance()
241
+
242
+ if self.current_char is None:
243
+ self.error("F-string não foi fechada.")
244
+
245
+ self.advance() # Consome o '"' final
246
+
247
+ # O token T_F_STRING foi definido em um passo anterior
248
+ return Token(T_F_STRING, result, start_line, start_col)