bxcode-ar 1.0.0__tar.gz → 1.2.0__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.
- {bxcode_ar-1.0.0/src/bxcode_ar.egg-info → bxcode_ar-1.2.0}/PKG-INFO +2 -2
- {bxcode_ar-1.0.0 → bxcode_ar-1.2.0}/pyproject.toml +2 -2
- {bxcode_ar-1.0.0 → bxcode_ar-1.2.0}/src/bxcode_ar/__init__.py +1 -1
- bxcode_ar-1.2.0/src/bxcode_ar/compiler.py +557 -0
- {bxcode_ar-1.0.0 → bxcode_ar-1.2.0/src/bxcode_ar.egg-info}/PKG-INFO +2 -2
- bxcode_ar-1.0.0/src/bxcode_ar/compiler.py +0 -131
- {bxcode_ar-1.0.0 → bxcode_ar-1.2.0}/LICENSE +0 -0
- {bxcode_ar-1.0.0 → bxcode_ar-1.2.0}/README.md +0 -0
- {bxcode_ar-1.0.0 → bxcode_ar-1.2.0}/setup.cfg +0 -0
- {bxcode_ar-1.0.0 → bxcode_ar-1.2.0}/src/bxcode_ar/cli.py +0 -0
- {bxcode_ar-1.0.0 → bxcode_ar-1.2.0}/src/bxcode_ar.egg-info/SOURCES.txt +0 -0
- {bxcode_ar-1.0.0 → bxcode_ar-1.2.0}/src/bxcode_ar.egg-info/dependency_links.txt +0 -0
- {bxcode_ar-1.0.0 → bxcode_ar-1.2.0}/src/bxcode_ar.egg-info/entry_points.txt +0 -0
- {bxcode_ar-1.0.0 → bxcode_ar-1.2.0}/src/bxcode_ar.egg-info/top_level.txt +0 -0
|
@@ -4,11 +4,11 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "bxcode_ar"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.2.0"
|
|
8
8
|
description = "Arabic syntax compiler for Python"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
11
|
-
license =
|
|
11
|
+
license = "MIT"
|
|
12
12
|
|
|
13
13
|
[tool.setuptools.packages.find]
|
|
14
14
|
where = ["src"]
|
|
@@ -0,0 +1,557 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import webbrowser
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
# ==========================================
|
|
6
|
+
# BXCode AR
|
|
7
|
+
# Arabic Syntax Compiler for Python
|
|
8
|
+
# ==========================================
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# الكلمات العربية الأساسية
|
|
12
|
+
KEYWORDS = {
|
|
13
|
+
# Conditions
|
|
14
|
+
"وإلا": "else",
|
|
15
|
+
"والا": "else",
|
|
16
|
+
|
|
17
|
+
# Loops
|
|
18
|
+
"لكل": "for",
|
|
19
|
+
"بينما": "while",
|
|
20
|
+
|
|
21
|
+
# Functions
|
|
22
|
+
"دالة": "def",
|
|
23
|
+
"ارجع": "return",
|
|
24
|
+
"لامدا": "lambda",
|
|
25
|
+
"انتج": "yield",
|
|
26
|
+
|
|
27
|
+
# Input
|
|
28
|
+
"ادخل": "input",
|
|
29
|
+
|
|
30
|
+
# Boolean / values
|
|
31
|
+
"صح": "True",
|
|
32
|
+
"خطأ": "False",
|
|
33
|
+
"فارغ": "None",
|
|
34
|
+
|
|
35
|
+
# Logic
|
|
36
|
+
"و": "and",
|
|
37
|
+
"او": "or",
|
|
38
|
+
"ليس": "not",
|
|
39
|
+
"في": "in",
|
|
40
|
+
"ليس_في": "not in",
|
|
41
|
+
"هو": "is",
|
|
42
|
+
"ليس_هو": "is not",
|
|
43
|
+
|
|
44
|
+
# Loop control
|
|
45
|
+
"كسر": "break",
|
|
46
|
+
"استمر": "continue",
|
|
47
|
+
"مرر": "pass",
|
|
48
|
+
|
|
49
|
+
# Exceptions
|
|
50
|
+
"حاول": "try",
|
|
51
|
+
"عدا": "except",
|
|
52
|
+
"اخيرا": "finally",
|
|
53
|
+
"ارفع": "raise",
|
|
54
|
+
|
|
55
|
+
# Context managers
|
|
56
|
+
"مع": "with",
|
|
57
|
+
|
|
58
|
+
# Classes
|
|
59
|
+
"صنف": "class",
|
|
60
|
+
|
|
61
|
+
# Imports
|
|
62
|
+
"استورد": "import",
|
|
63
|
+
"من": "from",
|
|
64
|
+
"باسم": "as",
|
|
65
|
+
|
|
66
|
+
# Variables / scope
|
|
67
|
+
"احذف": "del",
|
|
68
|
+
"عالمي": "global",
|
|
69
|
+
"غير_محلي": "nonlocal",
|
|
70
|
+
|
|
71
|
+
# Assertions
|
|
72
|
+
"تاكد": "assert",
|
|
73
|
+
|
|
74
|
+
# Async
|
|
75
|
+
"غير_متزامن": "async",
|
|
76
|
+
"انتظر": "await",
|
|
77
|
+
|
|
78
|
+
# Exit
|
|
79
|
+
"انهاء": "exit",
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# معاملات المقارنة
|
|
84
|
+
OPERATORS = {
|
|
85
|
+
"اكبر_او_يساوي": ">=",
|
|
86
|
+
"اصغر_او_يساوي": "<=",
|
|
87
|
+
"لايساوي": "!=",
|
|
88
|
+
"اكبر": ">",
|
|
89
|
+
"اصغر": "<",
|
|
90
|
+
"يساوي": "==",
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# رسائل الأخطاء العربية
|
|
95
|
+
ERROR_MESSAGES = {
|
|
96
|
+
"SyntaxError": {
|
|
97
|
+
"title": "خطأ في الصياغة",
|
|
98
|
+
"description": "الكود يحتوي على صياغة غير صحيحة أو ناقصة.",
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
"NameError": {
|
|
102
|
+
"title": "اسم غير معروف",
|
|
103
|
+
"description": "تم استخدام متغير أو دالة غير موجودة أو لم يتم تعريفها.",
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
"TypeError": {
|
|
107
|
+
"title": "خطأ في نوع البيانات",
|
|
108
|
+
"description": "تم استخدام نوع بيانات بطريقة غير مناسبة.",
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
"ValueError": {
|
|
112
|
+
"title": "قيمة غير صحيحة",
|
|
113
|
+
"description": "القيمة المستخدمة لا تناسب العملية المطلوبة.",
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
"IndexError": {
|
|
117
|
+
"title": "رقم عنصر غير صحيح",
|
|
118
|
+
"description": "تم الوصول إلى عنصر غير موجود داخل القائمة.",
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
"KeyError": {
|
|
122
|
+
"title": "المفتاح غير موجود",
|
|
123
|
+
"description": "تم استخدام مفتاح غير موجود داخل القاموس.",
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
"ZeroDivisionError": {
|
|
127
|
+
"title": "القسمة على صفر",
|
|
128
|
+
"description": "لا يمكن قسمة رقم على صفر.",
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
"AttributeError": {
|
|
132
|
+
"title": "خاصية أو دالة غير موجودة",
|
|
133
|
+
"description": "الخاصية أو الدالة المطلوبة غير موجودة.",
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
"ModuleNotFoundError": {
|
|
137
|
+
"title": "المكتبة غير موجودة",
|
|
138
|
+
"description": "المكتبة التي حاولت استيرادها غير مثبتة أو غير موجودة.",
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
"FileNotFoundError": {
|
|
142
|
+
"title": "الملف غير موجود",
|
|
143
|
+
"description": "الملف المطلوب لم يتم العثور عليه.",
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
"IndentationError": {
|
|
147
|
+
"title": "خطأ في المسافات البادئة",
|
|
148
|
+
"description": "ترتيب المسافات داخل الكود غير صحيح.",
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
"TabError": {
|
|
152
|
+
"title": "خطأ في المسافات",
|
|
153
|
+
"description": "تم خلط Tab مع المسافات داخل الكود.",
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
"UnboundLocalError": {
|
|
157
|
+
"title": "متغير محلي غير معروف",
|
|
158
|
+
"description": "تم استخدام متغير محلي قبل إعطائه قيمة.",
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
"RecursionError": {
|
|
162
|
+
"title": "تكرار لا نهائي",
|
|
163
|
+
"description": "الدالة تستدعي نفسها بشكل متكرر دون توقف.",
|
|
164
|
+
},
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
# ==========================================
|
|
169
|
+
# أدوات مساعدة
|
|
170
|
+
# ==========================================
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def count_code_lines(code):
|
|
174
|
+
"""
|
|
175
|
+
يحسب الأسطر غير الفارغة.
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
return len([
|
|
179
|
+
line
|
|
180
|
+
for line in code.splitlines()
|
|
181
|
+
if line.strip()
|
|
182
|
+
])
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def open_channel_for_large_code(code):
|
|
186
|
+
"""
|
|
187
|
+
يفتح قناة BXCode إذا تجاوز الكود 20 سطر.
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
if count_code_lines(code) > 20:
|
|
191
|
+
try:
|
|
192
|
+
webbrowser.open("https://t.me/bxcode")
|
|
193
|
+
except Exception:
|
|
194
|
+
pass
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
# ==========================================
|
|
198
|
+
# ترجمة اطبع
|
|
199
|
+
# ==========================================
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def translate_print(line):
|
|
203
|
+
match = re.match(
|
|
204
|
+
r'^(\s*)اطبع\((.*)\)\s*$',
|
|
205
|
+
line
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
if not match:
|
|
209
|
+
return None
|
|
210
|
+
|
|
211
|
+
indent = match.group(1)
|
|
212
|
+
value = match.group(2).strip()
|
|
213
|
+
|
|
214
|
+
return f"{indent}print({value})"
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
# ==========================================
|
|
218
|
+
# ترجمة اذا
|
|
219
|
+
# ==========================================
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def translate_if(line):
|
|
223
|
+
|
|
224
|
+
match = re.match(
|
|
225
|
+
r'^(\s*)اذا\s+(.+?)\s+'
|
|
226
|
+
r'(اكبر_او_يساوي|اصغر_او_يساوي|لايساوي|'
|
|
227
|
+
r'اكبر|اصغر|يساوي)'
|
|
228
|
+
r'\s+(.+):\s*$',
|
|
229
|
+
line
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
if not match:
|
|
233
|
+
return None
|
|
234
|
+
|
|
235
|
+
indent = match.group(1)
|
|
236
|
+
left = match.group(2)
|
|
237
|
+
operator = match.group(3)
|
|
238
|
+
right = match.group(4)
|
|
239
|
+
|
|
240
|
+
return (
|
|
241
|
+
f"{indent}if "
|
|
242
|
+
f"{left} "
|
|
243
|
+
f"{OPERATORS[operator]} "
|
|
244
|
+
f"{right}:"
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
# ==========================================
|
|
249
|
+
# ترجمة وإلا إذا
|
|
250
|
+
# ==========================================
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def translate_elif(line):
|
|
254
|
+
|
|
255
|
+
match = re.match(
|
|
256
|
+
r'^(\s*)(?:وإلا_اذا|والا_اذا)\s+'
|
|
257
|
+
r'(.+?)\s+'
|
|
258
|
+
r'(اكبر_او_يساوي|اصغر_او_يساوي|لايساوي|'
|
|
259
|
+
r'اكبر|اصغر|يساوي)'
|
|
260
|
+
r'\s+(.+):\s*$',
|
|
261
|
+
line
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
if not match:
|
|
265
|
+
return None
|
|
266
|
+
|
|
267
|
+
indent = match.group(1)
|
|
268
|
+
left = match.group(2)
|
|
269
|
+
operator = match.group(3)
|
|
270
|
+
right = match.group(4)
|
|
271
|
+
|
|
272
|
+
return (
|
|
273
|
+
f"{indent}elif "
|
|
274
|
+
f"{left} "
|
|
275
|
+
f"{OPERATORS[operator]} "
|
|
276
|
+
f"{right}:"
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
# ==========================================
|
|
281
|
+
# ترجمة السطر
|
|
282
|
+
# ==========================================
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def translate_line(line):
|
|
286
|
+
|
|
287
|
+
# اطبع
|
|
288
|
+
result = translate_print(line)
|
|
289
|
+
|
|
290
|
+
if result is not None:
|
|
291
|
+
return result
|
|
292
|
+
|
|
293
|
+
# اذا
|
|
294
|
+
result = translate_if(line)
|
|
295
|
+
|
|
296
|
+
if result is not None:
|
|
297
|
+
return result
|
|
298
|
+
|
|
299
|
+
# وإلا اذا
|
|
300
|
+
result = translate_elif(line)
|
|
301
|
+
|
|
302
|
+
if result is not None:
|
|
303
|
+
return result
|
|
304
|
+
|
|
305
|
+
# الكلمات العامة
|
|
306
|
+
for arabic, python in KEYWORDS.items():
|
|
307
|
+
|
|
308
|
+
line = re.sub(
|
|
309
|
+
rf"\b{re.escape(arabic)}\b",
|
|
310
|
+
python,
|
|
311
|
+
line
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
return line
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
# ==========================================
|
|
318
|
+
# Compile
|
|
319
|
+
# ==========================================
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def compile_code(code):
|
|
323
|
+
|
|
324
|
+
return "\n".join(
|
|
325
|
+
translate_line(line)
|
|
326
|
+
for line in code.splitlines()
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
# ==========================================
|
|
331
|
+
# Compile File
|
|
332
|
+
# ==========================================
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def compile_file(filename):
|
|
336
|
+
|
|
337
|
+
with open(
|
|
338
|
+
filename,
|
|
339
|
+
"r",
|
|
340
|
+
encoding="utf-8"
|
|
341
|
+
) as file:
|
|
342
|
+
|
|
343
|
+
return compile_code(file.read())
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
# ==========================================
|
|
347
|
+
# رسائل الأخطاء
|
|
348
|
+
# ==========================================
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
def show_arabic_error(error, code):
|
|
352
|
+
|
|
353
|
+
error_type = type(error).__name__
|
|
354
|
+
|
|
355
|
+
info = ERROR_MESSAGES.get(
|
|
356
|
+
error_type,
|
|
357
|
+
{
|
|
358
|
+
"title": "خطأ أثناء تشغيل البرنامج",
|
|
359
|
+
"description": "حدث خطأ غير معروف أثناء تنفيذ الكود.",
|
|
360
|
+
}
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
print()
|
|
364
|
+
print("╔══════════════════════════════════════════╗")
|
|
365
|
+
print("║ ❌ خطأ في BXCode AR ║")
|
|
366
|
+
print("╚══════════════════════════════════════════╝")
|
|
367
|
+
print()
|
|
368
|
+
|
|
369
|
+
print(f"نوع الخطأ: {info['title']}")
|
|
370
|
+
print(f"الشرح: {info['description']}")
|
|
371
|
+
|
|
372
|
+
# رقم السطر
|
|
373
|
+
line_number = getattr(
|
|
374
|
+
error,
|
|
375
|
+
"lineno",
|
|
376
|
+
None
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
if line_number:
|
|
380
|
+
print(f"رقم السطر: {line_number}")
|
|
381
|
+
|
|
382
|
+
# رسالة Python الأصلية
|
|
383
|
+
error_message = str(error)
|
|
384
|
+
|
|
385
|
+
if error_message:
|
|
386
|
+
print()
|
|
387
|
+
print(f"تفاصيل الخطأ: {error_message}")
|
|
388
|
+
|
|
389
|
+
# عرض السطر
|
|
390
|
+
lines = code.splitlines()
|
|
391
|
+
|
|
392
|
+
if line_number and 1 <= line_number <= len(lines):
|
|
393
|
+
|
|
394
|
+
print()
|
|
395
|
+
print("السطر الذي حدث فيه الخطأ:")
|
|
396
|
+
print(
|
|
397
|
+
f" {line_number} | "
|
|
398
|
+
f"{lines[line_number - 1]}"
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
# نصائح
|
|
402
|
+
print()
|
|
403
|
+
print("💡 الحل المقترح:")
|
|
404
|
+
|
|
405
|
+
if error_type == "NameError":
|
|
406
|
+
|
|
407
|
+
print(
|
|
408
|
+
"تأكد من أن اسم المتغير أو الدالة "
|
|
409
|
+
"مكتوب بشكل صحيح وتم تعريفه قبل استخدامه."
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
elif error_type == "SyntaxError":
|
|
413
|
+
|
|
414
|
+
print(
|
|
415
|
+
"راجع صياغة السطر، الأقواس، "
|
|
416
|
+
"النقطتين : والمسافات."
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
elif error_type == "TypeError":
|
|
420
|
+
|
|
421
|
+
print(
|
|
422
|
+
"تأكد أن أنواع البيانات المستخدمة "
|
|
423
|
+
"مناسبة للعملية."
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
elif error_type == "ValueError":
|
|
427
|
+
|
|
428
|
+
print(
|
|
429
|
+
"تأكد من أن القيمة المدخلة "
|
|
430
|
+
"بالصيغة الصحيحة."
|
|
431
|
+
)
|
|
432
|
+
|
|
433
|
+
elif error_type == "IndentationError":
|
|
434
|
+
|
|
435
|
+
print(
|
|
436
|
+
"تأكد من ترتيب المسافات داخل الكود "
|
|
437
|
+
"واستخدم نفس نوع المسافات."
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
elif error_type == "ZeroDivisionError":
|
|
441
|
+
|
|
442
|
+
print(
|
|
443
|
+
"تأكد أن الرقم الذي تقسم عليه "
|
|
444
|
+
"ليس صفرًا."
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
elif error_type == "IndexError":
|
|
448
|
+
|
|
449
|
+
print(
|
|
450
|
+
"تأكد أن رقم العنصر موجود "
|
|
451
|
+
"داخل القائمة."
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
elif error_type == "KeyError":
|
|
455
|
+
|
|
456
|
+
print(
|
|
457
|
+
"تأكد أن المفتاح موجود "
|
|
458
|
+
"داخل القاموس."
|
|
459
|
+
)
|
|
460
|
+
|
|
461
|
+
elif error_type == "ModuleNotFoundError":
|
|
462
|
+
|
|
463
|
+
print(
|
|
464
|
+
"ثبت المكتبة المطلوبة باستخدام pip "
|
|
465
|
+
"أو تأكد من اسمها."
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
else:
|
|
469
|
+
|
|
470
|
+
print(
|
|
471
|
+
"راجع السطر المذكور أعلاه "
|
|
472
|
+
"وتأكد من القيم والصياغة."
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
print()
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
# ==========================================
|
|
479
|
+
# تشغيل الكود
|
|
480
|
+
# ==========================================
|
|
481
|
+
|
|
482
|
+
|
|
483
|
+
def run(code):
|
|
484
|
+
|
|
485
|
+
# إذا تجاوز الكود 20 سطر
|
|
486
|
+
open_channel_for_large_code(code)
|
|
487
|
+
|
|
488
|
+
try:
|
|
489
|
+
|
|
490
|
+
# تحويل BXCode AR إلى Python
|
|
491
|
+
python_code = compile_code(code)
|
|
492
|
+
|
|
493
|
+
# بيئة التنفيذ
|
|
494
|
+
namespace = {
|
|
495
|
+
"__name__": "__main__"
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
# تشغيل الكود
|
|
499
|
+
exec(
|
|
500
|
+
python_code,
|
|
501
|
+
namespace
|
|
502
|
+
)
|
|
503
|
+
|
|
504
|
+
except Exception as error:
|
|
505
|
+
|
|
506
|
+
# عرض الخطأ بالعربي
|
|
507
|
+
show_arabic_error(
|
|
508
|
+
error,
|
|
509
|
+
code
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
# فتح قناة BXCode بعد الخطأ
|
|
513
|
+
try:
|
|
514
|
+
webbrowser.open(
|
|
515
|
+
"https://t.me/bxcode"
|
|
516
|
+
)
|
|
517
|
+
except Exception:
|
|
518
|
+
pass
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
# ==========================================
|
|
522
|
+
# تشغيل ملف .bx
|
|
523
|
+
# ==========================================
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
def run_file(filename):
|
|
527
|
+
|
|
528
|
+
try:
|
|
529
|
+
|
|
530
|
+
code = compile_file(filename)
|
|
531
|
+
|
|
532
|
+
namespace = {
|
|
533
|
+
"__name__": "__main__"
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
exec(
|
|
537
|
+
code,
|
|
538
|
+
namespace
|
|
539
|
+
)
|
|
540
|
+
|
|
541
|
+
except Exception as error:
|
|
542
|
+
|
|
543
|
+
try:
|
|
544
|
+
with open(
|
|
545
|
+
filename,
|
|
546
|
+
"r",
|
|
547
|
+
encoding="utf-8"
|
|
548
|
+
) as file:
|
|
549
|
+
original_code = file.read()
|
|
550
|
+
|
|
551
|
+
except Exception:
|
|
552
|
+
original_code = ""
|
|
553
|
+
|
|
554
|
+
show_arabic_error(
|
|
555
|
+
error,
|
|
556
|
+
original_code
|
|
557
|
+
)
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
import sys
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
KEYWORDS = {
|
|
6
|
-
"وإلا": "else",
|
|
7
|
-
"وإلا_اذا": "elif",
|
|
8
|
-
|
|
9
|
-
"لكل": "for",
|
|
10
|
-
"بينما": "while",
|
|
11
|
-
|
|
12
|
-
"دالة": "def",
|
|
13
|
-
"ارجع": "return",
|
|
14
|
-
|
|
15
|
-
"ادخل": "input",
|
|
16
|
-
|
|
17
|
-
"صح": "True",
|
|
18
|
-
"خطأ": "False",
|
|
19
|
-
"فارغ": "None",
|
|
20
|
-
|
|
21
|
-
"و": "and",
|
|
22
|
-
"او": "or",
|
|
23
|
-
"ليس": "not",
|
|
24
|
-
"في": "in",
|
|
25
|
-
|
|
26
|
-
"كسر": "break",
|
|
27
|
-
"استمر": "continue",
|
|
28
|
-
"مرر": "pass",
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
OPERATORS = {
|
|
33
|
-
"اكبر_او_يساوي": ">=",
|
|
34
|
-
"اصغر_او_يساوي": "<=",
|
|
35
|
-
"لايساوي": "!=",
|
|
36
|
-
"اكبر": ">",
|
|
37
|
-
"اصغر": "<",
|
|
38
|
-
"يساوي": "==",
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def translate_print(line):
|
|
43
|
-
match = re.match(r'^(\s*)اطبع\((.*)\)\s*$', line)
|
|
44
|
-
|
|
45
|
-
if not match:
|
|
46
|
-
return None
|
|
47
|
-
|
|
48
|
-
indent = match.group(1)
|
|
49
|
-
value = match.group(2).strip()
|
|
50
|
-
|
|
51
|
-
return f"{indent}print({value})"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def translate_if(line):
|
|
55
|
-
match = re.match(
|
|
56
|
-
r'^(\s*)اذا\s+(.+?)\s+(اكبر_او_يساوي|اصغر_او_يساوي|لايساوي|اكبر|اصغر|يساوي)\s+(.+):\s*$',
|
|
57
|
-
line
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
if not match:
|
|
61
|
-
return None
|
|
62
|
-
|
|
63
|
-
indent = match.group(1)
|
|
64
|
-
left = match.group(2)
|
|
65
|
-
operator = match.group(3)
|
|
66
|
-
right = match.group(4)
|
|
67
|
-
|
|
68
|
-
return (
|
|
69
|
-
f"{indent}if "
|
|
70
|
-
f"{left} "
|
|
71
|
-
f"{OPERATORS[operator]} "
|
|
72
|
-
f"{right}:"
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
def translate_line(line):
|
|
77
|
-
|
|
78
|
-
result = translate_print(line)
|
|
79
|
-
|
|
80
|
-
if result is not None:
|
|
81
|
-
return result
|
|
82
|
-
|
|
83
|
-
result = translate_if(line)
|
|
84
|
-
|
|
85
|
-
if result is not None:
|
|
86
|
-
return result
|
|
87
|
-
|
|
88
|
-
for arabic, python in KEYWORDS.items():
|
|
89
|
-
line = re.sub(
|
|
90
|
-
rf"\b{re.escape(arabic)}\b",
|
|
91
|
-
python,
|
|
92
|
-
line
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
return line
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def compile_code(code):
|
|
99
|
-
|
|
100
|
-
return "\n".join(
|
|
101
|
-
translate_line(line)
|
|
102
|
-
for line in code.splitlines()
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def compile_file(filename):
|
|
107
|
-
|
|
108
|
-
with open(filename, "r", encoding="utf-8") as file:
|
|
109
|
-
return compile_code(file.read())
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def run(code):
|
|
113
|
-
|
|
114
|
-
python_code = compile_code(code)
|
|
115
|
-
|
|
116
|
-
namespace = {
|
|
117
|
-
"__name__": "__main__"
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
exec(python_code, namespace)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
def run_file(filename):
|
|
124
|
-
|
|
125
|
-
code = compile_file(filename)
|
|
126
|
-
|
|
127
|
-
namespace = {
|
|
128
|
-
"__name__": "__main__"
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
exec(code, namespace)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|