shell-lite 0.3.5__py3-none-any.whl → 0.4.1__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.
- shell_lite/ast_nodes.py +24 -1
- shell_lite/compiler.py +14 -2
- shell_lite/interpreter.py +212 -17
- shell_lite/js_compiler.py +17 -3
- shell_lite/lexer.py +4 -1
- shell_lite/main.py +263 -81
- shell_lite/parser.py +227 -23
- shell_lite-0.4.1.dist-info/METADATA +77 -0
- shell_lite-0.4.1.dist-info/RECORD +17 -0
- shell_lite-0.3.5.dist-info/METADATA +0 -40
- shell_lite-0.3.5.dist-info/RECORD +0 -17
- {shell_lite-0.3.5.dist-info → shell_lite-0.4.1.dist-info}/LICENSE +0 -0
- {shell_lite-0.3.5.dist-info → shell_lite-0.4.1.dist-info}/WHEEL +0 -0
- {shell_lite-0.3.5.dist-info → shell_lite-0.4.1.dist-info}/entry_points.txt +0 -0
- {shell_lite-0.3.5.dist-info → shell_lite-0.4.1.dist-info}/top_level.txt +0 -0
shell_lite/parser.py
CHANGED
|
@@ -32,6 +32,8 @@ class Parser:
|
|
|
32
32
|
def parse_statement(self) -> Node:
|
|
33
33
|
if self.check('USE'):
|
|
34
34
|
return self.parse_import()
|
|
35
|
+
elif self.check('APP'):
|
|
36
|
+
return self.parse_app()
|
|
35
37
|
elif self.check('ON'):
|
|
36
38
|
return self.parse_on()
|
|
37
39
|
elif self.check('CONST'):
|
|
@@ -301,12 +303,25 @@ class Parser:
|
|
|
301
303
|
node.line = token.line
|
|
302
304
|
return node
|
|
303
305
|
def parse_make(self) -> Node:
|
|
306
|
+
node = self.parse_make_expr()
|
|
307
|
+
self.consume('NEWLINE')
|
|
308
|
+
return node
|
|
309
|
+
|
|
310
|
+
def parse_make_expr(self) -> Make:
|
|
304
311
|
token = self.consume('MAKE')
|
|
305
312
|
class_name = self.consume('ID').value
|
|
306
313
|
args = []
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
314
|
+
if self.check('LPAREN'):
|
|
315
|
+
self.consume('LPAREN')
|
|
316
|
+
if not self.check('RPAREN'):
|
|
317
|
+
args.append(self.parse_expression())
|
|
318
|
+
while self.check('COMMA'):
|
|
319
|
+
self.consume('COMMA')
|
|
320
|
+
args.append(self.parse_expression())
|
|
321
|
+
self.consume('RPAREN')
|
|
322
|
+
else:
|
|
323
|
+
while not self.check('NEWLINE') and not self.check('EOF'):
|
|
324
|
+
args.append(self.parse_expression())
|
|
310
325
|
node = Make(class_name, args)
|
|
311
326
|
node.line = token.line
|
|
312
327
|
return node
|
|
@@ -501,7 +516,10 @@ class Parser:
|
|
|
501
516
|
start_token = self.consume('STRUCTURE')
|
|
502
517
|
name = self.consume('ID').value
|
|
503
518
|
parent = None
|
|
504
|
-
if self.check('
|
|
519
|
+
if self.check('EXTENDS'):
|
|
520
|
+
self.consume('EXTENDS')
|
|
521
|
+
parent = self.consume('ID').value
|
|
522
|
+
elif self.check('LPAREN'):
|
|
505
523
|
self.consume('LPAREN')
|
|
506
524
|
parent = self.consume('ID').value
|
|
507
525
|
self.consume('RPAREN')
|
|
@@ -512,10 +530,29 @@ class Parser:
|
|
|
512
530
|
while not self.check('DEDENT') and not self.check('EOF'):
|
|
513
531
|
if self.check('HAS'):
|
|
514
532
|
self.consume()
|
|
515
|
-
|
|
533
|
+
prop_name = None
|
|
534
|
+
if self.check('MAKE'):
|
|
535
|
+
prop_name = self.consume().value
|
|
536
|
+
else:
|
|
537
|
+
prop_name = self.consume('ID').value
|
|
538
|
+
|
|
539
|
+
default_val = None
|
|
540
|
+
if self.check('ASSIGN'):
|
|
541
|
+
self.consume('ASSIGN')
|
|
542
|
+
default_val = self.parse_expression()
|
|
543
|
+
|
|
544
|
+
properties.append((prop_name, default_val))
|
|
516
545
|
self.consume('NEWLINE')
|
|
517
546
|
elif self.check('TO'):
|
|
518
547
|
methods.append(self.parse_function_def())
|
|
548
|
+
elif self.check('ID'):
|
|
549
|
+
prop_name = self.consume('ID').value
|
|
550
|
+
default_val = None
|
|
551
|
+
if self.check('ASSIGN'):
|
|
552
|
+
self.consume('ASSIGN')
|
|
553
|
+
default_val = self.parse_expression()
|
|
554
|
+
properties.append((prop_name, default_val))
|
|
555
|
+
self.consume('NEWLINE')
|
|
519
556
|
elif self.check('NEWLINE'):
|
|
520
557
|
self.consume()
|
|
521
558
|
else:
|
|
@@ -597,6 +634,22 @@ class Parser:
|
|
|
597
634
|
node = Assign(name, value)
|
|
598
635
|
node.line = token_is.line
|
|
599
636
|
return node
|
|
637
|
+
elif self.check('LBRACKET'):
|
|
638
|
+
self.consume('LBRACKET')
|
|
639
|
+
index = self.parse_expression()
|
|
640
|
+
self.consume('RBRACKET')
|
|
641
|
+
self.consume('ASSIGN')
|
|
642
|
+
val = self.parse_expression()
|
|
643
|
+
self.consume('NEWLINE')
|
|
644
|
+
# Convert simple assignment to PropertyAssign-like or specific set call?
|
|
645
|
+
# interpreter.visit_IndexAccess handles get.
|
|
646
|
+
# We need a node for IndexAssign. parser snippet doesn't show one.
|
|
647
|
+
# But visit_PropertyAssign handles dict keys.
|
|
648
|
+
# Let's map d[k] = v to PropertyAssign(d, k, v)?
|
|
649
|
+
# No, PropertyAssign takes member name as string. Here index handles expressions.
|
|
650
|
+
# I need to check if there is a node for this.
|
|
651
|
+
# If not, I'll return Call('set', [VarAccess(name), index, val])
|
|
652
|
+
return Call('set', [VarAccess(name), index, val])
|
|
600
653
|
elif self.check('DOT'):
|
|
601
654
|
self.consume('DOT')
|
|
602
655
|
member_token = self.consume()
|
|
@@ -606,13 +659,40 @@ class Parser:
|
|
|
606
659
|
value = self.parse_expression()
|
|
607
660
|
self.consume('NEWLINE')
|
|
608
661
|
return PropertyAssign(name, member, value)
|
|
662
|
+
|
|
609
663
|
args = []
|
|
664
|
+
if self.check('LPAREN'):
|
|
665
|
+
self.consume('LPAREN')
|
|
666
|
+
if not self.check('RPAREN'):
|
|
667
|
+
args.append(self.parse_expression())
|
|
668
|
+
while self.check('COMMA'):
|
|
669
|
+
self.consume('COMMA')
|
|
670
|
+
args.append(self.parse_expression())
|
|
671
|
+
self.consume('RPAREN')
|
|
672
|
+
self.consume('NEWLINE')
|
|
673
|
+
node = MethodCall(name, member, args)
|
|
674
|
+
node.line = name_token.line
|
|
675
|
+
return node
|
|
676
|
+
|
|
610
677
|
while not self.check('NEWLINE') and not self.check('EOF'):
|
|
611
678
|
args.append(self.parse_expression())
|
|
612
679
|
self.consume('NEWLINE')
|
|
613
680
|
node = MethodCall(name, member, args)
|
|
614
681
|
node.line = name_token.line
|
|
615
682
|
return node
|
|
683
|
+
elif self.check('LPAREN'):
|
|
684
|
+
self.consume('LPAREN')
|
|
685
|
+
args = []
|
|
686
|
+
if not self.check('RPAREN'):
|
|
687
|
+
args.append(self.parse_expression())
|
|
688
|
+
while self.check('COMMA'):
|
|
689
|
+
self.consume('COMMA')
|
|
690
|
+
args.append(self.parse_expression())
|
|
691
|
+
self.consume('RPAREN')
|
|
692
|
+
self.consume('NEWLINE')
|
|
693
|
+
node = Call(name, args)
|
|
694
|
+
node.line = name_token.line
|
|
695
|
+
return node
|
|
616
696
|
else:
|
|
617
697
|
if not self.check('NEWLINE') and not self.check('EOF') and not self.check('EQ') and not self.check('IS'):
|
|
618
698
|
args = []
|
|
@@ -855,7 +935,27 @@ class Parser:
|
|
|
855
935
|
return Assign(name, value)
|
|
856
936
|
def parse_import(self) -> Node:
|
|
857
937
|
token = self.consume('USE')
|
|
858
|
-
|
|
938
|
+
|
|
939
|
+
# Check for Python Import: use python "numpy" as np
|
|
940
|
+
if self.check('ID') and self.peek().value == 'python':
|
|
941
|
+
self.consume('ID') # consume 'python'
|
|
942
|
+
if self.check('STRING'):
|
|
943
|
+
module_name = self.consume('STRING').value
|
|
944
|
+
alias = None
|
|
945
|
+
if self.check('AS'):
|
|
946
|
+
self.consume('AS')
|
|
947
|
+
alias = self.consume('ID').value
|
|
948
|
+
self.consume('NEWLINE')
|
|
949
|
+
node = PythonImport(module_name, alias)
|
|
950
|
+
node.line = token.line
|
|
951
|
+
return node
|
|
952
|
+
else:
|
|
953
|
+
raise SyntaxError(f"Expected module name string after 'use python' at line {token.line}")
|
|
954
|
+
|
|
955
|
+
if self.check('STRING'):
|
|
956
|
+
path = self.consume('STRING').value
|
|
957
|
+
else:
|
|
958
|
+
path = self.consume('ID').value
|
|
859
959
|
if self.check('AS'):
|
|
860
960
|
self.consume('AS')
|
|
861
961
|
alias = self.consume('ID').value
|
|
@@ -1082,6 +1182,70 @@ class Parser:
|
|
|
1082
1182
|
node = Dictionary(pairs)
|
|
1083
1183
|
node.line = token.line
|
|
1084
1184
|
return node
|
|
1185
|
+
def parse_app(self) -> Node:
|
|
1186
|
+
token = self.consume('APP')
|
|
1187
|
+
title = self.consume('STRING').value
|
|
1188
|
+
|
|
1189
|
+
width = 500
|
|
1190
|
+
height = 400
|
|
1191
|
+
if self.check('SIZE'):
|
|
1192
|
+
self.consume('SIZE')
|
|
1193
|
+
width = int(self.consume('NUMBER').value)
|
|
1194
|
+
height = int(self.consume('NUMBER').value)
|
|
1195
|
+
|
|
1196
|
+
self.consume('COLON')
|
|
1197
|
+
self.consume('NEWLINE')
|
|
1198
|
+
self.consume('INDENT')
|
|
1199
|
+
|
|
1200
|
+
body = []
|
|
1201
|
+
while not self.check('DEDENT'):
|
|
1202
|
+
body.append(self.parse_ui_block())
|
|
1203
|
+
if self.check('NEWLINE'):
|
|
1204
|
+
self.consume('NEWLINE')
|
|
1205
|
+
|
|
1206
|
+
self.consume('DEDENT')
|
|
1207
|
+
return App(title, width, height, body)
|
|
1208
|
+
|
|
1209
|
+
def parse_ui_block(self) -> Node:
|
|
1210
|
+
token = self.peek()
|
|
1211
|
+
|
|
1212
|
+
if token.type in ('COLUMN', 'ROW'):
|
|
1213
|
+
layout_type = self.consume().value # column or row
|
|
1214
|
+
self.consume('COLON')
|
|
1215
|
+
self.consume('NEWLINE')
|
|
1216
|
+
self.consume('INDENT')
|
|
1217
|
+
children = []
|
|
1218
|
+
while not self.check('DEDENT'):
|
|
1219
|
+
children.append(self.parse_ui_block())
|
|
1220
|
+
if self.check('NEWLINE'): self.consume('NEWLINE')
|
|
1221
|
+
self.consume('DEDENT')
|
|
1222
|
+
return Layout(layout_type, children)
|
|
1223
|
+
|
|
1224
|
+
elif token.type in ('BUTTON', 'INPUT', 'HEADING', 'TEXT'):
|
|
1225
|
+
widget_type = self.consume().value
|
|
1226
|
+
label = self.consume('STRING').value
|
|
1227
|
+
|
|
1228
|
+
var_name = None
|
|
1229
|
+
if self.check('AS'):
|
|
1230
|
+
self.consume('AS')
|
|
1231
|
+
var_name = self.consume('ID').value
|
|
1232
|
+
|
|
1233
|
+
event_handler = None
|
|
1234
|
+
if token.type == 'BUTTON' and self.check('DO'):
|
|
1235
|
+
self.consume('DO')
|
|
1236
|
+
self.consume('COLON')
|
|
1237
|
+
self.consume('NEWLINE')
|
|
1238
|
+
self.consume('INDENT')
|
|
1239
|
+
event_handler = []
|
|
1240
|
+
while not self.check('DEDENT'):
|
|
1241
|
+
event_handler.append(self.parse_statement())
|
|
1242
|
+
self.consume('DEDENT')
|
|
1243
|
+
|
|
1244
|
+
return Widget(widget_type, label, var_name, event_handler)
|
|
1245
|
+
|
|
1246
|
+
else:
|
|
1247
|
+
raise SyntaxError(f"Unexpected token in UI block: {token.type} at line {token.line}")
|
|
1248
|
+
|
|
1085
1249
|
def parse_factor_simple(self) -> Node:
|
|
1086
1250
|
token = self.peek()
|
|
1087
1251
|
if token.type == 'NUMBER':
|
|
@@ -1178,12 +1342,23 @@ class Parser:
|
|
|
1178
1342
|
raise SyntaxError(f"Unexpected argument token {token.type} at line {token.line}")
|
|
1179
1343
|
def parse_factor(self) -> Node:
|
|
1180
1344
|
token = self.peek()
|
|
1181
|
-
if token.type == '
|
|
1345
|
+
if token.type == 'MINUS':
|
|
1182
1346
|
op = self.consume()
|
|
1183
|
-
right = self.parse_factor()
|
|
1184
|
-
node = UnaryOp(
|
|
1347
|
+
right = self.parse_factor()
|
|
1348
|
+
node = UnaryOp('-', right)
|
|
1185
1349
|
node.line = op.line
|
|
1186
1350
|
return node
|
|
1351
|
+
elif token.type == 'NOT':
|
|
1352
|
+
op = self.consume()
|
|
1353
|
+
right = self.parse_factor()
|
|
1354
|
+
node = UnaryOp('not', right)
|
|
1355
|
+
node.line = op.line
|
|
1356
|
+
return node
|
|
1357
|
+
elif token.type == 'LPAREN':
|
|
1358
|
+
self.consume('LPAREN')
|
|
1359
|
+
node = self.parse_expression()
|
|
1360
|
+
self.consume('RPAREN')
|
|
1361
|
+
return node
|
|
1187
1362
|
elif token.type == 'DB':
|
|
1188
1363
|
return self.parse_db_op()
|
|
1189
1364
|
elif token.type == 'SPAWN':
|
|
@@ -1263,10 +1438,7 @@ class Parser:
|
|
|
1263
1438
|
node.line = token.line
|
|
1264
1439
|
return node
|
|
1265
1440
|
elif token.type == 'STRING':
|
|
1266
|
-
self.
|
|
1267
|
-
node = String(token.value)
|
|
1268
|
-
node.line = token.line
|
|
1269
|
-
return node
|
|
1441
|
+
return self.parse_factor_simple()
|
|
1270
1442
|
elif token.type == 'YES':
|
|
1271
1443
|
self.consume()
|
|
1272
1444
|
node = Boolean(True)
|
|
@@ -1293,30 +1465,60 @@ class Parser:
|
|
|
1293
1465
|
if self.check('DOT'):
|
|
1294
1466
|
self.consume('DOT')
|
|
1295
1467
|
method_name = self.consume().value
|
|
1468
|
+
|
|
1296
1469
|
args = []
|
|
1470
|
+
# Check for C-style function call: func(arg1, arg2)
|
|
1471
|
+
if self.check('LPAREN'):
|
|
1472
|
+
self.consume('LPAREN')
|
|
1473
|
+
if not self.check('RPAREN'):
|
|
1474
|
+
args.append(self.parse_expression())
|
|
1475
|
+
while self.check('COMMA'):
|
|
1476
|
+
self.consume('COMMA')
|
|
1477
|
+
args.append(self.parse_expression())
|
|
1478
|
+
self.consume('RPAREN')
|
|
1479
|
+
if method_name:
|
|
1480
|
+
node = MethodCall(instance_name, method_name, args)
|
|
1481
|
+
else:
|
|
1482
|
+
node = Call(instance_name, args)
|
|
1483
|
+
node.line = token.line
|
|
1484
|
+
return node
|
|
1485
|
+
|
|
1486
|
+
# Fallback to command-style arguments: func arg1 arg2
|
|
1487
|
+
# But only if NOT a property access (method_name w/o args is property access,
|
|
1488
|
+
# but if it was method call it would use parens ideally, or spaces?)
|
|
1489
|
+
# Existing logic supported 'func arg1 arg2'.
|
|
1490
|
+
# We keep it for backward compatibility e.g. 'echo 123'.
|
|
1491
|
+
|
|
1297
1492
|
force_call = False
|
|
1298
1493
|
while True:
|
|
1299
1494
|
next_t = self.peek()
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1495
|
+
# If we see LPAREN now, it's ambiguous if we didn't handle it above.
|
|
1496
|
+
# But 'func (1)' is func called with 1 arg which is (1).
|
|
1497
|
+
# 'func (1, 2)' would fail in old logic too.
|
|
1498
|
+
# So the above block handles the explicit invocation.
|
|
1499
|
+
# This loop is for 'func 1 2'.
|
|
1500
|
+
|
|
1501
|
+
# Check for keywords or invalid start tokens
|
|
1502
|
+
if next_t.type not in ('NUMBER', 'STRING', 'REGEX', 'ID', 'LPAREN', 'INPUT', 'ASK', 'YES', 'NO', 'LBRACKET', 'LBRACE'):
|
|
1308
1503
|
break
|
|
1504
|
+
|
|
1505
|
+
# Special case: if we see LPAREN, is it part of command args?
|
|
1506
|
+
# e.g. 'func (1+2)' -> args=[(1+2)].
|
|
1507
|
+
args.append(self.parse_factor_simple())
|
|
1508
|
+
|
|
1309
1509
|
if method_name:
|
|
1310
|
-
if args
|
|
1510
|
+
if args:
|
|
1311
1511
|
node = MethodCall(instance_name, method_name, args)
|
|
1312
1512
|
else:
|
|
1313
1513
|
node = PropertyAccess(instance_name, method_name)
|
|
1314
1514
|
node.line = token.line
|
|
1315
1515
|
return node
|
|
1316
|
-
|
|
1516
|
+
|
|
1517
|
+
if args:
|
|
1317
1518
|
node = Call(instance_name, args)
|
|
1318
1519
|
node.line = token.line
|
|
1319
1520
|
return node
|
|
1521
|
+
|
|
1320
1522
|
node = VarAccess(instance_name)
|
|
1321
1523
|
node.line = token.line
|
|
1322
1524
|
return node
|
|
@@ -1349,6 +1551,8 @@ class Parser:
|
|
|
1349
1551
|
node = Confirm(prompt_expr)
|
|
1350
1552
|
node.line = token.line
|
|
1351
1553
|
return node
|
|
1554
|
+
elif token.type == 'MAKE':
|
|
1555
|
+
return self.parse_make_expr()
|
|
1352
1556
|
raise SyntaxError(f"Unexpected token {token.type} at line {token.line}")
|
|
1353
1557
|
def parse_for(self) -> Node:
|
|
1354
1558
|
if self.check('LOOP'):
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: shell-lite
|
|
3
|
+
Version: 0.4.1
|
|
4
|
+
Summary: A lightweight, English-like scripting language.
|
|
5
|
+
Author-email: Shrey Naithani <contact@shelllite.tech>
|
|
6
|
+
License: MIT
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.8
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: prompt-toolkit>=3.0.0
|
|
13
|
+
|
|
14
|
+
<img src="assets/logo.png" align="right" width="250" alt="ShellLite Logo" />
|
|
15
|
+
|
|
16
|
+
# ShellLite: The English-Like Programming Language
|
|
17
|
+
# By Shrey Naithani
|
|
18
|
+
ShellLite is a modern, interpreted programming language designed to prioritize human readability. It replaces complex syntax with natural English commands, making software development accessible and maintainable.
|
|
19
|
+
|
|
20
|
+
## Version 0.04.0 (Polaris Update)
|
|
21
|
+
|
|
22
|
+
This release transforms ShellLite from a scripting tool into a comprehensive platform with three major pillars:
|
|
23
|
+
1. **The Bridge**: Import and use any Python library (pandas, requests, etc.) natively.
|
|
24
|
+
2. **The Canvas**: Build native desktop GUI applications with declarative syntax.
|
|
25
|
+
3. **The Universe**: Integrated package management for project dependencies.
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
### Via PyPI (Recommended)
|
|
30
|
+
You can install ShellLite directly from PyPI:
|
|
31
|
+
```bash
|
|
32
|
+
pip install shell-lite
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Windows Installer
|
|
36
|
+
Download the latest `shl.exe` from the Releases page.
|
|
37
|
+
|
|
38
|
+
## Quick Start
|
|
39
|
+
|
|
40
|
+
### 1. Hello World
|
|
41
|
+
Save this as `hello.shl`:
|
|
42
|
+
```shell-lite
|
|
43
|
+
say "Hello, World"
|
|
44
|
+
```
|
|
45
|
+
Run it:
|
|
46
|
+
```bash
|
|
47
|
+
shl hello.shl
|
|
48
|
+
```
|
|
49
|
+
## Project Management
|
|
50
|
+
|
|
51
|
+
Initialize a new project:
|
|
52
|
+
```bash
|
|
53
|
+
shl init
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Install dependencies defined in `shell-lite.toml`:
|
|
57
|
+
```bash
|
|
58
|
+
shl install
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Ecosystem & Tools
|
|
62
|
+
|
|
63
|
+
| Tool | Description | Link |
|
|
64
|
+
| :--- | :--- | :--- |
|
|
65
|
+
| **ShellDesk** | The official IDE for ShellLite. | [GitHub](https://github.com/Shrey-N/ShellDesk) |
|
|
66
|
+
| **VS Code Extension** | Syntax highlighting and snippets. | [Marketplace](https://marketplace.visualstudio.com/items?itemName=ShellLite.shelllite-hello) / [OpenVSX](https://open-vsx.org/extension/shelllite/shelllite-hello) |
|
|
67
|
+
| **Website** | Official website source code. | [GitHub](https://github.com/Shrey-N/ShellLite-Website) |
|
|
68
|
+
|
|
69
|
+
## Documentation
|
|
70
|
+
|
|
71
|
+
Full documentation is available directly in this repository:
|
|
72
|
+
- [**Language Guide**](https://github.com/Shrey-N/ShellLite)
|
|
73
|
+
- [**Examples**](https://github.com/Shrey-N/ShellLite/tree/main/examples)
|
|
74
|
+
|
|
75
|
+
License: MIT
|
|
76
|
+
Made by Shrey Naithani
|
|
77
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
shell_lite/__init__.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
2
|
+
shell_lite/ast_nodes.py,sha256=KGFlZmP21MJXo6uRYRJfo_R3BEspfDD8xMBtAVfUDgU,5873
|
|
3
|
+
shell_lite/cli.py,sha256=14Kq1ohSXS3p-xdh0DPi7eXskUtSX81huSyGhktoOMA,250
|
|
4
|
+
shell_lite/compiler.py,sha256=FcwDLbrjnMnH0VMzEeYPSqD3nIeFAwKIdvEDAT1e3GE,24984
|
|
5
|
+
shell_lite/formatter.py,sha256=590BfQmhsX466i5_xONXAhgVE97zfcV79q1wA3DT47A,2952
|
|
6
|
+
shell_lite/interpreter.py,sha256=oyyFIe8bx4Tok09Nd-qIexU6D9rVdvyxe2JVzCaHHTY,74577
|
|
7
|
+
shell_lite/js_compiler.py,sha256=b2-XyGqm2BYUfwU0OsphpMxLNeho1ihL7htAcg3uWII,9438
|
|
8
|
+
shell_lite/lexer.py,sha256=UDQtFX7UW3HgMftQ3HsCu9tfImk9vsyMX5icsAI6NuE,12549
|
|
9
|
+
shell_lite/main.py,sha256=h-RIPB-QcfQdQslafILdztJqKcRf9exoNF0gYMXWVww,22517
|
|
10
|
+
shell_lite/parser.py,sha256=Eh-LjIX1AdYyuhPaL-_GPlDoSzDM0RxDNQsBWog-06k,73377
|
|
11
|
+
shell_lite/runtime.py,sha256=pSjBeA1dTQ-a94q3FLdv9lqZurdd6MJmfhFGHhOoQEM,16057
|
|
12
|
+
shell_lite-0.4.1.dist-info/LICENSE,sha256=33eziKLPxbqGCqdHtEHAFe1KSOgqc0-jWUQmdgKq85Q,1092
|
|
13
|
+
shell_lite-0.4.1.dist-info/METADATA,sha256=7S7UoqTYKp5Wq1oZhTscVOrhCAT64iQs_k8L9QDJxaI,2475
|
|
14
|
+
shell_lite-0.4.1.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
|
15
|
+
shell_lite-0.4.1.dist-info/entry_points.txt,sha256=tglL8tjyPIh1W85j6zFpNZjMpQe_xC-k-7BOhHLWfxc,45
|
|
16
|
+
shell_lite-0.4.1.dist-info/top_level.txt,sha256=hIln5ltrok_Mn3ijlQeqMFF6hHBHCyhzqCO7KL358cg,11
|
|
17
|
+
shell_lite-0.4.1.dist-info/RECORD,,
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: shell-lite
|
|
3
|
-
Version: 0.3.5
|
|
4
|
-
Summary: A lightweight, English-like scripting language.
|
|
5
|
-
Author-email: Shrey Naithani <contact@shelllite.tech>
|
|
6
|
-
License: MIT
|
|
7
|
-
Classifier: Programming Language :: Python :: 3
|
|
8
|
-
Classifier: Operating System :: OS Independent
|
|
9
|
-
Requires-Python: >=3.8
|
|
10
|
-
Description-Content-Type: text/markdown
|
|
11
|
-
License-File: LICENSE
|
|
12
|
-
|
|
13
|
-
# ShellLite
|
|
14
|
-
|
|
15
|
-
**ShellLite** is a programming language designed to be as readable as plain English. It strips away the complex syntax of traditional languages and replaces it with natural, human-friendly commands.
|
|
16
|
-
|
|
17
|
-
## ⭐ Support Us
|
|
18
|
-
|
|
19
|
-
If you like ShellLite, please kindly **star** our repository on GitHub! It helps us grow.
|
|
20
|
-
|
|
21
|
-
👉 [**GitHub Repository**](https://github.com/Shrey-N/ShellLite)
|
|
22
|
-
|
|
23
|
-
## 📦 Installation
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
pip install shell-lite
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
## 🔗 Ecosystem
|
|
30
|
-
|
|
31
|
-
- **Website & IDE**: [shelllite.tech](https://shelllite.tech)
|
|
32
|
-
- **VS Code Extension**: [Marketplace](https://marketplace.visualstudio.com/items?itemName=shelllite.shelllite-hello)
|
|
33
|
-
- **OpenVSX**: [OpenVSX Registry](https://open-vsx.org/extension/shelllite/shelllite-hello)
|
|
34
|
-
|
|
35
|
-
## 📞 Contact
|
|
36
|
-
|
|
37
|
-
To help in the development, please contact **Shrey Naithani** at [contact@shelllite.tech](mailto:contact@shelllite.tech).
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
**Made by Shrey Naithani**
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
shell_lite/__init__.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
2
|
-
shell_lite/ast_nodes.py,sha256=xbxIiUSduXWdq0DYQQLkWpW5TfmOFxmbpBRbe3YDyfI,5341
|
|
3
|
-
shell_lite/cli.py,sha256=14Kq1ohSXS3p-xdh0DPi7eXskUtSX81huSyGhktoOMA,250
|
|
4
|
-
shell_lite/compiler.py,sha256=nAWLyU1aLc5OJm5qpe3aHsKyVQ61JfHerOs3rl572xU,24600
|
|
5
|
-
shell_lite/formatter.py,sha256=590BfQmhsX466i5_xONXAhgVE97zfcV79q1wA3DT47A,2952
|
|
6
|
-
shell_lite/interpreter.py,sha256=yuGCdIL66SV9bwHGA2fUI6RwoJ45TheAiu_p0QZY8Z8,66858
|
|
7
|
-
shell_lite/js_compiler.py,sha256=yBAHRASGccKIe5-U_SbLO13TexhJydQ_bClDHzWhogI,8877
|
|
8
|
-
shell_lite/lexer.py,sha256=c8KpM9qtGmmUks3SlCZzEz-CdEj-Z1JC34FMr3WD9i0,12355
|
|
9
|
-
shell_lite/main.py,sha256=ubDEMXWlxT7eUyfRlnzDkc8CVCqqzYLpBHkh8EJ1-Mg,15469
|
|
10
|
-
shell_lite/parser.py,sha256=xT_CuN6Nz4Pz5sU5iM-KpnCWFde1txk1JRhhqFlckc8,64902
|
|
11
|
-
shell_lite/runtime.py,sha256=pSjBeA1dTQ-a94q3FLdv9lqZurdd6MJmfhFGHhOoQEM,16057
|
|
12
|
-
shell_lite-0.3.5.dist-info/LICENSE,sha256=33eziKLPxbqGCqdHtEHAFe1KSOgqc0-jWUQmdgKq85Q,1092
|
|
13
|
-
shell_lite-0.3.5.dist-info/METADATA,sha256=-mt7dpP-TJ93MWZEcytgaT6CG2MO7XlUnPjM00Lo4-I,1311
|
|
14
|
-
shell_lite-0.3.5.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
|
15
|
-
shell_lite-0.3.5.dist-info/entry_points.txt,sha256=tglL8tjyPIh1W85j6zFpNZjMpQe_xC-k-7BOhHLWfxc,45
|
|
16
|
-
shell_lite-0.3.5.dist-info/top_level.txt,sha256=hIln5ltrok_Mn3ijlQeqMFF6hHBHCyhzqCO7KL358cg,11
|
|
17
|
-
shell_lite-0.3.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|