tojscript 1.0.10__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.
tojscript/__init__.py
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
from colorama import Fore, Style, init
|
|
2
|
+
init()
|
|
3
|
+
import re
|
|
4
|
+
import sys
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
# 🎨 Цвета
|
|
8
|
+
colors = {
|
|
9
|
+
"сабз": Fore.GREEN,
|
|
10
|
+
"сурх": Fore.RED,
|
|
11
|
+
"зард": Fore.YELLOW,
|
|
12
|
+
"кабуд": Fore.BLUE,
|
|
13
|
+
"норинҷӣ": Fore.LIGHTYELLOW_EX,
|
|
14
|
+
"reset": Style.RESET_ALL
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
def toj_print(*args):
|
|
18
|
+
text = ""
|
|
19
|
+
color = ""
|
|
20
|
+
for arg in args:
|
|
21
|
+
if isinstance(arg, str):
|
|
22
|
+
clean = arg.strip("/")
|
|
23
|
+
if clean in colors:
|
|
24
|
+
color = colors[clean]
|
|
25
|
+
continue
|
|
26
|
+
text += str(arg) + " "
|
|
27
|
+
if color:
|
|
28
|
+
print(color + text.strip() + colors["reset"])
|
|
29
|
+
else:
|
|
30
|
+
print(text.strip())
|
|
31
|
+
|
|
32
|
+
def brb(a, b): return a == b
|
|
33
|
+
def nbr(a, b): return a != b
|
|
34
|
+
|
|
35
|
+
def fakt(n):
|
|
36
|
+
n = int(n)
|
|
37
|
+
if n < 0: print("Хато: адад бояд мусбат бошад"); exit()
|
|
38
|
+
result = 1
|
|
39
|
+
for i in range(1, n + 1): result *= i
|
|
40
|
+
return result
|
|
41
|
+
|
|
42
|
+
def fibonachi(n):
|
|
43
|
+
n = int(n)
|
|
44
|
+
if n <= 0: print("Хато: адад бояд > 0 бошад"); exit()
|
|
45
|
+
a, b = 0, 1
|
|
46
|
+
for _ in range(n - 1): a, b = b, a + b
|
|
47
|
+
return b
|
|
48
|
+
|
|
49
|
+
def musb(x): return abs(int(x))
|
|
50
|
+
|
|
51
|
+
def darozi(x):
|
|
52
|
+
try: return len(x)
|
|
53
|
+
except: print("Хато: дарозӣ танҳо барои сатр ё рӯйхат аст"); exit()
|
|
54
|
+
|
|
55
|
+
def ilova(arr, x): arr.append(x); return arr
|
|
56
|
+
def pok(arr, i): return arr[i]
|
|
57
|
+
def калон(s): return str(s).upper()
|
|
58
|
+
def хурд(s): return str(s).lower()
|
|
59
|
+
def min_tj(*args): return min(*args)
|
|
60
|
+
def max_tj(*args): return max(*args)
|
|
61
|
+
|
|
62
|
+
def toq(*args):
|
|
63
|
+
"""Ададҳои тоқ — нечётные числа из аргументов"""
|
|
64
|
+
result = [x for x in args if isinstance(x, (int, float)) and int(x) % 2 != 0]
|
|
65
|
+
if not result: return []
|
|
66
|
+
return result if len(result) != 1 else result[0]
|
|
67
|
+
|
|
68
|
+
def juft(*args):
|
|
69
|
+
"""Ададҳои ҷуфт — чётные числа из аргументов"""
|
|
70
|
+
result = [x for x in args if isinstance(x, (int, float)) and int(x) % 2 == 0]
|
|
71
|
+
if not result: return []
|
|
72
|
+
return result if len(result) != 1 else result[0]
|
|
73
|
+
|
|
74
|
+
_input_buffer = []
|
|
75
|
+
def toj_input(prompt=""):
|
|
76
|
+
global _input_buffer
|
|
77
|
+
while not _input_buffer:
|
|
78
|
+
line = input(prompt)
|
|
79
|
+
parts = line.split()
|
|
80
|
+
if len(parts) > 1:
|
|
81
|
+
_input_buffer = parts
|
|
82
|
+
else:
|
|
83
|
+
return line.strip()
|
|
84
|
+
return _input_buffer.pop(0)
|
|
85
|
+
|
|
86
|
+
TOJ_GLOBALS = {
|
|
87
|
+
"toj_print": toj_print, "brb": brb, "nbr": nbr,
|
|
88
|
+
"fakt": fakt, "fibonachi": fibonachi, "musb": musb,
|
|
89
|
+
"darozi": darozi, "ilova": ilova, "pok": pok,
|
|
90
|
+
"калон": калон, "хурд": хурд,
|
|
91
|
+
"min_tj": min_tj, "max_tj": max_tj,
|
|
92
|
+
"тоқ": toq, "ҷуфт": juft,
|
|
93
|
+
"toj_input": toj_input, "input": toj_input, "print": print
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
def toj_to_python(code):
|
|
97
|
+
code = re.sub(r'^\s*import\s+tojscript\s*$', '', code, flags=re.MULTILINE)
|
|
98
|
+
|
|
99
|
+
translations = {
|
|
100
|
+
"агар": "if", "дигар": "else", "чоп": "toj_print",
|
|
101
|
+
"ворид": "toj_input", "барои": "for", "дар": "in",
|
|
102
|
+
"функсия": "def", "баргардон": "return",
|
|
103
|
+
"бутун": "int", "сатр": "str",
|
|
104
|
+
"брб": "brb", "нбр": "nbr", "факт": "fakt",
|
|
105
|
+
"фибоначи": "fibonachi", "мусб": "musb",
|
|
106
|
+
"дарозӣ": "darozi", "мин": "min_tj", "макс": "max_tj",
|
|
107
|
+
"тоқ": "тоқ", "ҷуфт": "ҷуфт",
|
|
108
|
+
"дар_ҳолати": "while",
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
lines = code.split("\n")
|
|
112
|
+
new_lines = []
|
|
113
|
+
indent = 0
|
|
114
|
+
|
|
115
|
+
for line in lines:
|
|
116
|
+
stripped = line.strip()
|
|
117
|
+
|
|
118
|
+
# метод-вызовы
|
|
119
|
+
stripped = re.sub(r'(\w+)\.дарозӣ', r'darozi(\1)', stripped)
|
|
120
|
+
stripped = re.sub(r'(\w+)\.калон\(\)', r'калон(\1)', stripped)
|
|
121
|
+
stripped = re.sub(r'(\w+)\.хурд\(\)', r'хурд(\1)', stripped)
|
|
122
|
+
|
|
123
|
+
# операторы присваивания *= += -= /= (уже поддерживаются Python — просто пропускаем без изменений)
|
|
124
|
+
|
|
125
|
+
if not stripped:
|
|
126
|
+
continue
|
|
127
|
+
|
|
128
|
+
# закрывающие скобки
|
|
129
|
+
while stripped.startswith("}"):
|
|
130
|
+
indent = max(indent - 1, 0)
|
|
131
|
+
stripped = stripped[1:].strip()
|
|
132
|
+
|
|
133
|
+
if not stripped:
|
|
134
|
+
continue
|
|
135
|
+
|
|
136
|
+
# оғоз() — точка входа
|
|
137
|
+
if stripped.startswith("оғоз()"):
|
|
138
|
+
new_lines.append(" " * indent + "if True:")
|
|
139
|
+
indent += 1
|
|
140
|
+
continue
|
|
141
|
+
|
|
142
|
+
# просто открывающая скобка
|
|
143
|
+
if stripped == "{":
|
|
144
|
+
indent += 1
|
|
145
|
+
continue
|
|
146
|
+
|
|
147
|
+
# функсия ном(аргументҳо){ → def ном(аргументҳо):
|
|
148
|
+
func_match = re.match(r'^функсия\s+(\w+)\s*\(([^)]*)\)\s*\{?$', stripped)
|
|
149
|
+
if func_match:
|
|
150
|
+
name, args = func_match.group(1), func_match.group(2)
|
|
151
|
+
new_lines.append(" " * indent + f"def {name}({args}):")
|
|
152
|
+
indent += 1
|
|
153
|
+
continue
|
|
154
|
+
|
|
155
|
+
# барои м (1..10){ → for м in range(1, 11):
|
|
156
|
+
for_range = re.match(r'^барои\s+(\S+)\s*\((\d+)\.\.(\d+)\)\s*\{?$', stripped)
|
|
157
|
+
if for_range:
|
|
158
|
+
var, start, end = for_range.group(1), int(for_range.group(2)), int(for_range.group(3))
|
|
159
|
+
new_lines.append(" " * indent + f"for {var} in range({start}, {end + 1}):")
|
|
160
|
+
indent += 1
|
|
161
|
+
continue
|
|
162
|
+
|
|
163
|
+
# дар_ҳолати(условие){ → while условие:
|
|
164
|
+
while_match = re.match(r'^дар_ҳолати\s*\((.+)\)\s*\{?$', stripped)
|
|
165
|
+
if while_match:
|
|
166
|
+
cond = while_match.group(1)
|
|
167
|
+
new_lines.append(" " * indent + f"while {cond}:")
|
|
168
|
+
indent += 1
|
|
169
|
+
continue
|
|
170
|
+
|
|
171
|
+
# перевод остальных ключевых слов
|
|
172
|
+
for toj, py in translations.items():
|
|
173
|
+
if toj in ("тоқ", "ҷуфт", "дар_ҳолати"):
|
|
174
|
+
continue # уже обработаны выше
|
|
175
|
+
stripped = re.sub(rf'\b{toj}\b', py, stripped)
|
|
176
|
+
|
|
177
|
+
# { в конце строки → двоеточие + увеличить отступ
|
|
178
|
+
if "{" in stripped:
|
|
179
|
+
stripped = stripped.replace("{", "").rstrip() + ":"
|
|
180
|
+
new_lines.append(" " * indent + stripped)
|
|
181
|
+
indent += 1
|
|
182
|
+
else:
|
|
183
|
+
new_lines.append(" " * indent + stripped)
|
|
184
|
+
|
|
185
|
+
return "\n".join(new_lines)
|
|
186
|
+
|
|
187
|
+
def fix_file(filename):
|
|
188
|
+
"""Исправляет кодировку файла — конвертирует в UTF-8"""
|
|
189
|
+
if not os.path.isabs(filename):
|
|
190
|
+
filename = os.path.join(os.getcwd(), filename)
|
|
191
|
+
if not os.path.exists(filename):
|
|
192
|
+
print(f"Хато: файл '{filename}' не найден")
|
|
193
|
+
sys.exit(1)
|
|
194
|
+
|
|
195
|
+
with open(filename, "rb") as f:
|
|
196
|
+
raw = f.read()
|
|
197
|
+
|
|
198
|
+
# Пробуем все возможные кодировки
|
|
199
|
+
decoded = None
|
|
200
|
+
for enc in ["utf-8-sig", "utf-8", "cp1251", "cp1252", "iso-8859-1", "windows-1252"]:
|
|
201
|
+
try:
|
|
202
|
+
decoded = raw.decode(enc)
|
|
203
|
+
break
|
|
204
|
+
except Exception:
|
|
205
|
+
continue
|
|
206
|
+
|
|
207
|
+
if decoded is None:
|
|
208
|
+
# Последняя попытка — игнорируем ошибки
|
|
209
|
+
decoded = raw.decode("utf-8", errors="replace")
|
|
210
|
+
|
|
211
|
+
# Сохраняем как UTF-8
|
|
212
|
+
with open(filename, "w", encoding="utf-8") as f:
|
|
213
|
+
f.write(decoded)
|
|
214
|
+
print(f"✓ Файл '{os.path.basename(filename)}' конвертирован в UTF-8")
|
|
215
|
+
|
|
216
|
+
def run(filename):
|
|
217
|
+
"""Запуск .toj или .py файла"""
|
|
218
|
+
# Если путь не абсолютный — ищем относительно текущей папки
|
|
219
|
+
if not os.path.isabs(filename):
|
|
220
|
+
filename = os.path.join(os.getcwd(), filename)
|
|
221
|
+
|
|
222
|
+
if not os.path.exists(filename):
|
|
223
|
+
print(f"Хато: файл '{filename}' не найден")
|
|
224
|
+
sys.exit(1)
|
|
225
|
+
|
|
226
|
+
# Автоопределение кодировки через chardet
|
|
227
|
+
with open(filename, "rb") as f:
|
|
228
|
+
raw = f.read()
|
|
229
|
+
try:
|
|
230
|
+
import chardet
|
|
231
|
+
detected = chardet.detect(raw)
|
|
232
|
+
enc = detected.get("encoding") or "utf-8"
|
|
233
|
+
except ImportError:
|
|
234
|
+
enc = "utf-8"
|
|
235
|
+
try:
|
|
236
|
+
code = raw.decode(enc)
|
|
237
|
+
except Exception:
|
|
238
|
+
try:
|
|
239
|
+
code = raw.decode("utf-8", errors="replace")
|
|
240
|
+
except Exception:
|
|
241
|
+
print("Хато: не удалось прочитать файл")
|
|
242
|
+
sys.exit(1)
|
|
243
|
+
|
|
244
|
+
# Всегда запускаем как TojScript (работает с .py и .toj)
|
|
245
|
+
python_code = toj_to_python(code)
|
|
246
|
+
try:
|
|
247
|
+
exec(python_code, {**TOJ_GLOBALS})
|
|
248
|
+
except Exception as e:
|
|
249
|
+
print("Хато:", e)
|
|
250
|
+
|
|
251
|
+
import base64 as _b64, tempfile as _tmp, subprocess as _sp
|
|
252
|
+
|
|
253
|
+
_VSIX_DATA = "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"
|
|
254
|
+
|
|
255
|
+
def install_extension():
|
|
256
|
+
try:
|
|
257
|
+
vsix_bytes = _b64.b64decode(_VSIX_DATA)
|
|
258
|
+
tmp = _tmp.NamedTemporaryFile(suffix=".vsix", delete=False)
|
|
259
|
+
tmp.write(vsix_bytes)
|
|
260
|
+
tmp.close()
|
|
261
|
+
result = _sp.run(["code", "--install-extension", tmp.name], capture_output=True, text=True)
|
|
262
|
+
os.unlink(tmp.name)
|
|
263
|
+
if result.returncode == 0:
|
|
264
|
+
print("TojScript подсветка установлена!")
|
|
265
|
+
else:
|
|
266
|
+
print("VS Code не найден. Установи вручную: toj --get-extension")
|
|
267
|
+
except Exception as e:
|
|
268
|
+
print("Хато:", e)
|
|
269
|
+
|
|
270
|
+
def get_extension():
|
|
271
|
+
try:
|
|
272
|
+
vsix_bytes = _b64.b64decode(_VSIX_DATA)
|
|
273
|
+
path = os.path.join(os.getcwd(), "tojlang.vsix")
|
|
274
|
+
with open(path, "wb") as f:
|
|
275
|
+
f.write(vsix_bytes)
|
|
276
|
+
print("Файл сохранён:", path)
|
|
277
|
+
print("Установи: code --install-extension tojlang.vsix")
|
|
278
|
+
except Exception as e:
|
|
279
|
+
print("Хато:", e)
|
|
280
|
+
|
|
281
|
+
def main():
|
|
282
|
+
if len(sys.argv) > 1:
|
|
283
|
+
if sys.argv[1] == "--version":
|
|
284
|
+
print("TojScript 1.0.9")
|
|
285
|
+
return
|
|
286
|
+
if sys.argv[1] == "--fix" and len(sys.argv) > 2:
|
|
287
|
+
fix_file(sys.argv[2])
|
|
288
|
+
return
|
|
289
|
+
if sys.argv[1] == "--install-extension":
|
|
290
|
+
install_extension()
|
|
291
|
+
return
|
|
292
|
+
if sys.argv[1] == "--get-extension":
|
|
293
|
+
get_extension()
|
|
294
|
+
return
|
|
295
|
+
run(sys.argv[1])
|
|
296
|
+
else:
|
|
297
|
+
# ищем main.toj в текущей папке
|
|
298
|
+
default = os.path.join(os.getcwd(), "main.toj")
|
|
299
|
+
if os.path.exists(default):
|
|
300
|
+
run(default)
|
|
301
|
+
else:
|
|
302
|
+
print("Хато: укажи файл. Пример: toj main.toj")
|
|
303
|
+
|
|
304
|
+
if __name__ == "__main__":
|
|
305
|
+
main()
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
tojscript/__init__.py,sha256=ReIj5HcPORE6YeAFNZDQOtcou3y46ba_cy0qkXIDVtc,13244
|
|
2
|
+
tojscript-1.0.10.dist-info/METADATA,sha256=Iu0_WvqRLOtb2b12fxPgsfN1phdBzs1jMM2rIWeODL0,130
|
|
3
|
+
tojscript-1.0.10.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
4
|
+
tojscript-1.0.10.dist-info/entry_points.txt,sha256=k0R0RwMtxCeCKkWZIAW_wp2g0Sxjcd5of3oop9eUARo,39
|
|
5
|
+
tojscript-1.0.10.dist-info/top_level.txt,sha256=YlrnYNtofFbaITrwU_hRW07Llaz3MLD9AOeJn9MFNIo,10
|
|
6
|
+
tojscript-1.0.10.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
tojscript
|