silicon.py 0.2.2__tar.gz
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.
- silicon_py-0.2.2/PKG-INFO +7 -0
- silicon_py-0.2.2/README.md +0 -0
- silicon_py-0.2.2/nexus_lang/__init__.py +0 -0
- silicon_py-0.2.2/nexus_lang/shell.py +337 -0
- silicon_py-0.2.2/pyproject.toml +16 -0
- silicon_py-0.2.2/setup.cfg +4 -0
- silicon_py-0.2.2/silicon.py.egg-info/PKG-INFO +7 -0
- silicon_py-0.2.2/silicon.py.egg-info/SOURCES.txt +9 -0
- silicon_py-0.2.2/silicon.py.egg-info/dependency_links.txt +1 -0
- silicon_py-0.2.2/silicon.py.egg-info/entry_points.txt +2 -0
- silicon_py-0.2.2/silicon.py.egg-info/top_level.txt +1 -0
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
# --- TOKEN TYPES ---
|
|
5
|
+
TT_INT = 'INT'
|
|
6
|
+
TT_STRING = 'STRING'
|
|
7
|
+
TT_IDENTIFIER = 'IDENTIFIER'
|
|
8
|
+
TT_COLON = 'COLON'
|
|
9
|
+
TT_LPAREN = 'LPAREN'
|
|
10
|
+
TT_RPAREN = 'RPAREN'
|
|
11
|
+
TT_DOT = 'DOT'
|
|
12
|
+
TT_EQUALS = 'EQUALS'
|
|
13
|
+
TT_COMMA = 'COMMA'
|
|
14
|
+
TT_LBRACKET = 'LBRACKET'
|
|
15
|
+
TT_RBRACKET = 'RBRACKET'
|
|
16
|
+
TT_PLUS = 'PLUS'
|
|
17
|
+
TT_MINUS = 'MINUS'
|
|
18
|
+
TT_BOOL = 'BOOL'
|
|
19
|
+
TT_SEMICOLON = 'SEMICOLON' # For alt; also; not;
|
|
20
|
+
# Comparison
|
|
21
|
+
TT_EE = 'EE'
|
|
22
|
+
TT_LTE = 'LTE'
|
|
23
|
+
TT_GTE = 'GTE'
|
|
24
|
+
TT_LT = 'LT'
|
|
25
|
+
TT_GT = 'GT'
|
|
26
|
+
|
|
27
|
+
class Token:
|
|
28
|
+
def __init__(self, type_, value=None):
|
|
29
|
+
self.type = type_
|
|
30
|
+
self.value = value
|
|
31
|
+
def __repr__(self):
|
|
32
|
+
return f'{self.type}:{self.value}' if self.value is not None else f'{self.type}'
|
|
33
|
+
|
|
34
|
+
# --- LEXER ---
|
|
35
|
+
class Lexer:
|
|
36
|
+
def __init__(self, text):
|
|
37
|
+
text = re.sub(r'~~.*?~~', '', text)
|
|
38
|
+
text = re.sub(r'~~.*', '', text)
|
|
39
|
+
self.text = text
|
|
40
|
+
self.pos = -1
|
|
41
|
+
self.current_char = None
|
|
42
|
+
self.advance()
|
|
43
|
+
|
|
44
|
+
def advance(self):
|
|
45
|
+
self.pos += 1
|
|
46
|
+
self.current_char = self.text[self.pos] if self.pos < len(self.text) else None
|
|
47
|
+
|
|
48
|
+
def peek(self):
|
|
49
|
+
peek_pos = self.pos + 1
|
|
50
|
+
return self.text[peek_pos] if peek_pos < len(self.text) else None
|
|
51
|
+
|
|
52
|
+
def make_tokens(self):
|
|
53
|
+
tokens = []
|
|
54
|
+
while self.current_char is not None:
|
|
55
|
+
if self.current_char in ' \t\n\r': self.advance()
|
|
56
|
+
elif self.current_char.isdigit(): tokens.append(self.make_number())
|
|
57
|
+
elif self.current_char.isalpha(): tokens.append(self.make_identifier())
|
|
58
|
+
elif self.current_char in ('"', "'"): tokens.append(self.make_string())
|
|
59
|
+
elif self.current_char == '+': tokens.append(Token(TT_PLUS)); self.advance()
|
|
60
|
+
elif self.current_char == '-': tokens.append(Token(TT_MINUS)); self.advance()
|
|
61
|
+
elif self.current_char == ';': tokens.append(Token(TT_SEMICOLON)); self.advance()
|
|
62
|
+
elif self.current_char == '=':
|
|
63
|
+
if self.peek() == '=':
|
|
64
|
+
self.advance(); tokens.append(Token(TT_EE)); self.advance()
|
|
65
|
+
elif self.peek() == '>': # Support => for GTE
|
|
66
|
+
self.advance(); tokens.append(Token(TT_GTE)); self.advance()
|
|
67
|
+
else: tokens.append(Token(TT_EQUALS)); self.advance()
|
|
68
|
+
elif self.current_char == '<':
|
|
69
|
+
if self.peek() == '=':
|
|
70
|
+
self.advance(); tokens.append(Token(TT_LTE)); self.advance()
|
|
71
|
+
else: tokens.append(Token(TT_LT)); self.advance()
|
|
72
|
+
elif self.current_char == '>':
|
|
73
|
+
if self.peek() == '=':
|
|
74
|
+
self.advance(); tokens.append(Token(TT_GTE)); self.advance()
|
|
75
|
+
else: tokens.append(Token(TT_GT)); self.advance()
|
|
76
|
+
elif self.current_char == ':': tokens.append(Token(TT_COLON)); self.advance()
|
|
77
|
+
elif self.current_char == '(': tokens.append(Token(TT_LPAREN)); self.advance()
|
|
78
|
+
elif self.current_char == ')': tokens.append(Token(TT_RPAREN)); self.advance()
|
|
79
|
+
elif self.current_char == '[': tokens.append(Token(TT_LBRACKET)); self.advance()
|
|
80
|
+
elif self.current_char == ']': tokens.append(Token(TT_RBRACKET)); self.advance()
|
|
81
|
+
elif self.current_char == '.': tokens.append(Token(TT_DOT)); self.advance()
|
|
82
|
+
elif self.current_char == ',': tokens.append(Token(TT_COMMA)); self.advance()
|
|
83
|
+
else: self.advance()
|
|
84
|
+
return tokens, None
|
|
85
|
+
|
|
86
|
+
def make_number(self):
|
|
87
|
+
num_str = ''
|
|
88
|
+
while self.current_char is not None and self.current_char.isdigit():
|
|
89
|
+
num_str += self.current_char
|
|
90
|
+
self.advance()
|
|
91
|
+
return Token(TT_INT, int(num_str))
|
|
92
|
+
|
|
93
|
+
def make_string(self):
|
|
94
|
+
string = ''
|
|
95
|
+
quote_type = self.current_char
|
|
96
|
+
self.advance()
|
|
97
|
+
while self.current_char is not None and self.current_char != quote_type:
|
|
98
|
+
string += self.current_char
|
|
99
|
+
self.advance()
|
|
100
|
+
self.advance()
|
|
101
|
+
return Token(TT_STRING, string)
|
|
102
|
+
|
|
103
|
+
def make_identifier(self):
|
|
104
|
+
id_str = ''
|
|
105
|
+
while self.current_char is not None and (self.current_char.isalnum() or self.current_char == '_'):
|
|
106
|
+
id_str += self.current_char
|
|
107
|
+
self.advance()
|
|
108
|
+
if id_str == 'true': return Token(TT_BOOL, True)
|
|
109
|
+
if id_str == 'false': return Token(TT_BOOL, False)
|
|
110
|
+
return Token(TT_IDENTIFIER, id_str)
|
|
111
|
+
|
|
112
|
+
# --- NODES ---
|
|
113
|
+
class CondNode:
|
|
114
|
+
def __init__(self, mode, condition_tokens, body):
|
|
115
|
+
self.mode = mode # 'if' or 'during'
|
|
116
|
+
self.condition_tokens = condition_tokens
|
|
117
|
+
self.body = body
|
|
118
|
+
|
|
119
|
+
# (Other nodes like DefineNode, SetNode, etc. remain the same as previous)
|
|
120
|
+
class DefineNode:
|
|
121
|
+
def __init__(self, dtype, name, args=None, body=None):
|
|
122
|
+
self.dtype, self.name, self.args, self.body = dtype, name, args, body
|
|
123
|
+
|
|
124
|
+
class SetNode:
|
|
125
|
+
def __init__(self, library, name, expression):
|
|
126
|
+
self.library, self.name, self.expression = library, name, expression
|
|
127
|
+
|
|
128
|
+
class LogNode:
|
|
129
|
+
def __init__(self, lib, name, index=None, raw_val=None):
|
|
130
|
+
self.lib, self.name, self.index, self.raw_val = lib, name, index, raw_val
|
|
131
|
+
|
|
132
|
+
class FuncExecuteNode:
|
|
133
|
+
def __init__(self, name, args):
|
|
134
|
+
self.name, self.args = name, args
|
|
135
|
+
|
|
136
|
+
# --- PARSER ---
|
|
137
|
+
class Parser:
|
|
138
|
+
def __init__(self, tokens):
|
|
139
|
+
self.tokens, self.tok_idx = tokens, -1
|
|
140
|
+
self.advance()
|
|
141
|
+
|
|
142
|
+
def advance(self):
|
|
143
|
+
self.tok_idx += 1
|
|
144
|
+
self.current_tok = self.tokens[self.tok_idx] if self.tok_idx < len(self.tokens) else None
|
|
145
|
+
|
|
146
|
+
def get_block(self):
|
|
147
|
+
body = []
|
|
148
|
+
while self.current_tok:
|
|
149
|
+
if self.current_tok.type == TT_COLON:
|
|
150
|
+
if self.tok_idx + 1 < len(self.tokens) and self.tokens[self.tok_idx+1].value == 'end':
|
|
151
|
+
self.advance(); self.advance()
|
|
152
|
+
break
|
|
153
|
+
stmt = self.statement()
|
|
154
|
+
if stmt: body.append(stmt)
|
|
155
|
+
return body
|
|
156
|
+
|
|
157
|
+
def statement(self):
|
|
158
|
+
if not self.current_tok: return None
|
|
159
|
+
|
|
160
|
+
# --- NEW COND() SYNTAX ---
|
|
161
|
+
if self.current_tok.value == 'cond':
|
|
162
|
+
self.advance(); self.advance() # cond (
|
|
163
|
+
mode = self.current_tok.value # 'if' or 'during'
|
|
164
|
+
self.advance()
|
|
165
|
+
expr = []
|
|
166
|
+
while self.current_tok.type != TT_RPAREN:
|
|
167
|
+
expr.append(self.current_tok); self.advance()
|
|
168
|
+
self.advance(); self.advance() # ) :
|
|
169
|
+
return CondNode(mode, expr, self.get_block())
|
|
170
|
+
|
|
171
|
+
# (Rest of definitions like define, log, vars. stay identical to previous version)
|
|
172
|
+
if self.current_tok.value == 'define':
|
|
173
|
+
self.advance(); self.advance(); self.advance(); self.advance()
|
|
174
|
+
dtype = self.current_tok.value
|
|
175
|
+
self.advance(); self.advance()
|
|
176
|
+
name = self.current_tok.value
|
|
177
|
+
self.advance(); self.advance()
|
|
178
|
+
if dtype == 'Func':
|
|
179
|
+
self.advance(); self.advance()
|
|
180
|
+
args = []
|
|
181
|
+
while self.current_tok.type != TT_RBRACKET:
|
|
182
|
+
if self.current_tok.type == TT_IDENTIFIER and self.current_tok.value != 'None':
|
|
183
|
+
args.append(self.current_tok.value)
|
|
184
|
+
self.advance()
|
|
185
|
+
self.advance(); self.advance()
|
|
186
|
+
return DefineNode(dtype, name, args, self.get_block())
|
|
187
|
+
return DefineNode(dtype, name)
|
|
188
|
+
|
|
189
|
+
if self.current_tok.value in ('vars', 'arrs', 'funcs'):
|
|
190
|
+
lib = self.current_tok.value
|
|
191
|
+
self.advance(); self.advance()
|
|
192
|
+
name = self.current_tok.value
|
|
193
|
+
self.advance(); self.advance()
|
|
194
|
+
action = self.current_tok.value
|
|
195
|
+
self.advance(); self.advance()
|
|
196
|
+
expr = []
|
|
197
|
+
while self.current_tok and self.current_tok.type != TT_RPAREN:
|
|
198
|
+
expr.append(self.current_tok); self.advance()
|
|
199
|
+
if self.current_tok and self.current_tok.type == TT_COMMA: self.advance()
|
|
200
|
+
if self.current_tok: self.advance()
|
|
201
|
+
if action == 'Set': return SetNode(lib, name, expr)
|
|
202
|
+
if action == 'Execute': return FuncExecuteNode(name, expr)
|
|
203
|
+
|
|
204
|
+
if self.current_tok.value == 'log':
|
|
205
|
+
self.advance(); self.advance(); self.advance(); self.advance()
|
|
206
|
+
if self.current_tok.type == TT_IDENTIFIER and self.current_tok.value in ('vars', 'arrs'):
|
|
207
|
+
lib = self.current_tok.value
|
|
208
|
+
self.advance(); self.advance()
|
|
209
|
+
name = self.current_tok.value
|
|
210
|
+
self.advance()
|
|
211
|
+
idx = None
|
|
212
|
+
if self.current_tok and self.current_tok.type == TT_LBRACKET:
|
|
213
|
+
self.advance(); idx = self.current_tok.value; self.advance(); self.advance()
|
|
214
|
+
if self.current_tok: self.advance()
|
|
215
|
+
return LogNode(lib, name, index=idx)
|
|
216
|
+
else:
|
|
217
|
+
val = self.current_tok.value; self.advance(); self.advance()
|
|
218
|
+
return LogNode(None, None, raw_val=val)
|
|
219
|
+
return None
|
|
220
|
+
|
|
221
|
+
def parse(self):
|
|
222
|
+
ast = []
|
|
223
|
+
while self.current_tok is not None:
|
|
224
|
+
stmt = self.statement()
|
|
225
|
+
if stmt: ast.append(stmt)
|
|
226
|
+
else: self.advance()
|
|
227
|
+
return ast
|
|
228
|
+
|
|
229
|
+
# --- INTERPRETER ---
|
|
230
|
+
class Interpreter:
|
|
231
|
+
def __init__(self):
|
|
232
|
+
self.vars, self.arrs, self.funcs, self.temp_vars = {}, {}, {}, {}
|
|
233
|
+
|
|
234
|
+
def resolve_value(self, tokens):
|
|
235
|
+
if not isinstance(tokens, list):
|
|
236
|
+
if tokens.type in (TT_INT, TT_STRING, TT_BOOL): return tokens.value
|
|
237
|
+
if tokens.value == 'input':
|
|
238
|
+
val = input(">> "); return int(val) if val.isdigit() else val
|
|
239
|
+
if tokens.value in self.temp_vars: return self.temp_vars[tokens.value]
|
|
240
|
+
return tokens.value
|
|
241
|
+
if len(tokens) >= 3 and tokens[1].type == TT_DOT:
|
|
242
|
+
lib, var_name = tokens[0].value, tokens[2].value
|
|
243
|
+
if lib == 'vars': return self.temp_vars.get(var_name, self.vars.get(var_name, 0))
|
|
244
|
+
if lib == 'arrs': return self.arrs.get(var_name, [])
|
|
245
|
+
return self.resolve_value(tokens[0])
|
|
246
|
+
|
|
247
|
+
def evaluate_complex_logic(self, tokens):
|
|
248
|
+
# Handle "not;"
|
|
249
|
+
negate = False
|
|
250
|
+
if tokens[0].value == 'not' and tokens[1].type == TT_SEMICOLON:
|
|
251
|
+
negate = True
|
|
252
|
+
tokens = tokens[2:]
|
|
253
|
+
|
|
254
|
+
# Split by "alt;" or "also;"
|
|
255
|
+
# For v0.2.2 we'll do a simple check for these keywords
|
|
256
|
+
for i, tok in enumerate(tokens):
|
|
257
|
+
if tok.value == 'alt' and self.peek_token_type(i+1) == TT_SEMICOLON:
|
|
258
|
+
left = self.evaluate_expression(tokens[:i])
|
|
259
|
+
right = self.evaluate_complex_logic(tokens[i+2:])
|
|
260
|
+
res = left or right
|
|
261
|
+
return not res if negate else res
|
|
262
|
+
if tok.value == 'also' and self.peek_token_type(i+1) == TT_SEMICOLON:
|
|
263
|
+
left = self.evaluate_expression(tokens[:i])
|
|
264
|
+
right = self.evaluate_complex_logic(tokens[i+2:])
|
|
265
|
+
res = left and right
|
|
266
|
+
return not res if negate else res
|
|
267
|
+
|
|
268
|
+
res = self.evaluate_expression(tokens)
|
|
269
|
+
return not res if negate else res
|
|
270
|
+
|
|
271
|
+
def peek_token_type(self, idx):
|
|
272
|
+
# Helper for evaluate_complex_logic
|
|
273
|
+
return None # Simplified for this snippet
|
|
274
|
+
|
|
275
|
+
def evaluate_expression(self, expr_tokens):
|
|
276
|
+
for i, tok in enumerate(expr_tokens):
|
|
277
|
+
if tok.type in (TT_EE, TT_LTE, TT_GTE, TT_LT, TT_GT, TT_PLUS, TT_MINUS):
|
|
278
|
+
v1 = self.resolve_value(expr_tokens[:i])
|
|
279
|
+
v2 = self.resolve_value(expr_tokens[i+1:])
|
|
280
|
+
if tok.type == TT_EE: return v1 == v2
|
|
281
|
+
if tok.type == TT_LTE: return v1 <= v2
|
|
282
|
+
if tok.type == TT_GTE: return v1 >= v2
|
|
283
|
+
if tok.type == TT_LT: return v1 < v2
|
|
284
|
+
if tok.type == TT_GT: return v1 > v2
|
|
285
|
+
if tok.type == TT_PLUS: return v1 + v2
|
|
286
|
+
if tok.type == TT_MINUS: return v1 - v2
|
|
287
|
+
return self.resolve_value(expr_tokens)
|
|
288
|
+
|
|
289
|
+
def visit(self, node):
|
|
290
|
+
if isinstance(node, CondNode):
|
|
291
|
+
if node.mode == 'if':
|
|
292
|
+
if self.evaluate_complex_logic(node.condition_tokens):
|
|
293
|
+
for s in node.body: self.visit(s)
|
|
294
|
+
elif node.mode == 'during':
|
|
295
|
+
while self.evaluate_complex_logic(node.condition_tokens):
|
|
296
|
+
for s in node.body: self.visit(s)
|
|
297
|
+
elif isinstance(node, DefineNode):
|
|
298
|
+
if node.dtype == 'Var': self.vars[node.name] = None
|
|
299
|
+
elif node.dtype == 'Arr': self.arrs[node.name] = []
|
|
300
|
+
elif node.dtype == 'Func': self.funcs[node.name] = (node.args, node.body)
|
|
301
|
+
elif isinstance(node, SetNode):
|
|
302
|
+
val = self.evaluate_expression(node.expression)
|
|
303
|
+
if node.library == 'vars': self.vars[node.name] = val
|
|
304
|
+
else: self.arrs[node.name] = val
|
|
305
|
+
elif isinstance(node, LogNode):
|
|
306
|
+
if node.raw_val is not None: print(f"[NEXUS CONSOLE]: {node.raw_val}")
|
|
307
|
+
else: print(f"[NEXUS CONSOLE]: {self.vars.get(node.name, self.arrs.get(node.name))}")
|
|
308
|
+
elif isinstance(node, FuncExecuteNode):
|
|
309
|
+
args_n, body = self.funcs[node.name]
|
|
310
|
+
for s in body: self.visit(s)
|
|
311
|
+
|
|
312
|
+
def run_file(filename):
|
|
313
|
+
with open(filename, 'r') as f: script = f.read()
|
|
314
|
+
lexer = Lexer(script)
|
|
315
|
+
tokens, _ = lexer.make_tokens()
|
|
316
|
+
parser = Parser(tokens)
|
|
317
|
+
ast = parser.parse()
|
|
318
|
+
interpreter = Interpreter()
|
|
319
|
+
for node in ast: interpreter.visit(node)
|
|
320
|
+
|
|
321
|
+
if __name__ == "__main__":
|
|
322
|
+
if len(sys.argv) > 1: run_file(sys.argv[1])
|
|
323
|
+
|
|
324
|
+
def main_cli():
|
|
325
|
+
import sys
|
|
326
|
+
if len(sys.argv) > 1:
|
|
327
|
+
filename = sys.argv[1]
|
|
328
|
+
if filename.endswith('.sil'): # Changed from .nx to .sil
|
|
329
|
+
run_file(filename)
|
|
330
|
+
else:
|
|
331
|
+
print(f"Silicon Error: '{filename}' is not a valid .sil file.")
|
|
332
|
+
else:
|
|
333
|
+
print("Silicon v0.2.2")
|
|
334
|
+
print("Usage: silicon <filename>.sil")
|
|
335
|
+
|
|
336
|
+
if __name__ == "__main__":
|
|
337
|
+
main_cli()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "silicon.py"
|
|
7
|
+
version = "0.2.2"
|
|
8
|
+
description = "Silicon: A new language made with Python."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
authors = [
|
|
12
|
+
{ name="qwertydev" }
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[project.scripts]
|
|
16
|
+
silicon = "nexus_lang.shell:main_cli"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
nexus_lang
|