pyindo 1.0.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.
- pyindo-1.0.0/CHANGELOG.md +87 -0
- pyindo-1.0.0/LICENSE +21 -0
- pyindo-1.0.0/MANIFEST.in +5 -0
- pyindo-1.0.0/PKG-INFO +314 -0
- pyindo-1.0.0/README.md +298 -0
- pyindo-1.0.0/pyproject.toml +31 -0
- pyindo-1.0.0/setup.cfg +4 -0
- pyindo-1.0.0/setup.py +3 -0
- pyindo-1.0.0/src/indpy/__init__.py +1 -0
- pyindo-1.0.0/src/indpy/__main__.py +4 -0
- pyindo-1.0.0/src/indpy/errors.py +89 -0
- pyindo-1.0.0/src/indpy/keywords.py +96 -0
- pyindo-1.0.0/src/indpy/lexer.py +400 -0
- pyindo-1.0.0/src/indpy/main.py +371 -0
- pyindo-1.0.0/src/indpy/parser.py +845 -0
- pyindo-1.0.0/src/indpy/transpiler.py +460 -0
- pyindo-1.0.0/src/pyindo.egg-info/PKG-INFO +314 -0
- pyindo-1.0.0/src/pyindo.egg-info/SOURCES.txt +23 -0
- pyindo-1.0.0/src/pyindo.egg-info/dependency_links.txt +1 -0
- pyindo-1.0.0/src/pyindo.egg-info/entry_points.txt +2 -0
- pyindo-1.0.0/src/pyindo.egg-info/top_level.txt +1 -0
- pyindo-1.0.0/tests/__init__.py +1 -0
- pyindo-1.0.0/tests/test_lexer.py +266 -0
- pyindo-1.0.0/tests/test_parser.py +290 -0
- pyindo-1.0.0/tests/test_transpiler.py +330 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Semua perubahan penting pada proyek Indpy dicatat di sini.
|
|
4
|
+
|
|
5
|
+
Format mengikuti [Keep a Changelog](https://keepachangelog.com/id/1.0.0/),
|
|
6
|
+
versi mengikuti [Semantic Versioning](https://semver.org/lang/id/).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## [1.0.0] — 2026-07-06
|
|
11
|
+
|
|
12
|
+
Rilis perdana Indpy — transpiler Bahasa Indonesia ke Python.
|
|
13
|
+
|
|
14
|
+
### Ditambahkan
|
|
15
|
+
|
|
16
|
+
#### Inti Transpiler
|
|
17
|
+
- **Lexer** (`lexer.py`) — tokenizer rekursif karakter-per-karakter; mendukung 46 kata kunci Bahasa Indonesia, string literal dijaga utuh (tidak diterjemahkan), longest-match-first untuk operator multi-karakter (`**=`, `//=`, dsb.)
|
|
18
|
+
- **Parser** (`parser.py`) — recursive descent parser; membangun AST lengkap; mendukung tuple unpacking, eksponen kanan-asosiatif, serta keyword yang valid sebagai identifier (mis. `fungsi kosong(diri):`)
|
|
19
|
+
- **Transpiler** (`transpiler.py`) — traversal AST rekursif; menghasilkan kode Python valid dengan indentasi otomatis; penanganan presedensi operator yang benar untuk `**`
|
|
20
|
+
- **Keywords** (`keywords.py`) — peta 46 kata kunci Indonesia→Python beserta operator satu, dua, dan tiga karakter
|
|
21
|
+
- **Errors** (`errors.py`) — hierarki `IndpyError` dengan pesan kesalahan dalam Bahasa Indonesia
|
|
22
|
+
|
|
23
|
+
#### CLI (`main.py`)
|
|
24
|
+
- `indpy` — masuk REPL interaktif langsung tanpa argumen
|
|
25
|
+
- `indpy namafile.indpy` — shortcut jalankan file tanpa subperintah
|
|
26
|
+
- `indpy jalankan namafile.indpy` — transpilasi + eksekusi; flag `--tampilkan` untuk lihat kode Python hasil
|
|
27
|
+
- `indpy ekspor namafile.indpy` — transpilasi + simpan ke `.py`; flag `-o` untuk tentukan nama output
|
|
28
|
+
- `indpy --versi` — tampilkan versi
|
|
29
|
+
- `indpy --bantuan` — tampilkan bantuan
|
|
30
|
+
|
|
31
|
+
#### REPL Interaktif
|
|
32
|
+
- Prompt `>>> ` dan `... ` persis seperti Python REPL
|
|
33
|
+
- Namespace persisten — variabel, fungsi, kelas, dan impor tetap hidup antar perintah
|
|
34
|
+
- Hasil ekspresi ditampilkan otomatis (`repr`)
|
|
35
|
+
- Deteksi blok multi-baris otomatis (blok berakhir dengan baris kosong)
|
|
36
|
+
- `q`, `keluar()`, `exit()`, `quit()` → keluar dari REPL
|
|
37
|
+
- Ctrl+C → keluar dari REPL
|
|
38
|
+
- Ctrl+D → eksekusi sisa buffer lalu keluar
|
|
39
|
+
- Error runtime ditampilkan tanpa menutup REPL
|
|
40
|
+
|
|
41
|
+
#### Installer (`install.sh`)
|
|
42
|
+
- Deteksi environment otomatis: **Termux**, **Acode Terminal**, **Linux**
|
|
43
|
+
- Instalasi dependensi via `pkg` (Termux), `apt`, `apk`, `dnf`, atau `pacman`
|
|
44
|
+
- Cek versi Python minimum (3.7+) dengan pesan kesalahan jelas
|
|
45
|
+
- Update otomatis jika Indpy sudah terpasang (`git pull`)
|
|
46
|
+
- Buat symlink global `indpy` di `$PREFIX/bin` (Termux), `/usr/local/bin`, atau `~/.local/bin`
|
|
47
|
+
- Tambah `$BIN_DIR` ke PATH di `.bashrc`, `.bash_profile`, `.zshrc`, dan `.profile`
|
|
48
|
+
|
|
49
|
+
#### Lainnya
|
|
50
|
+
- **131 unit test** — mencakup Lexer, Parser, dan Transpiler (`pytest tests/ -v`)
|
|
51
|
+
- **3 file contoh** — `halo_dunia.indpy`, `kalkulator.indpy`, `loop_dan_fungsi.indpy`
|
|
52
|
+
- **VS Code Extension** (`indpy-syntax/`) — syntax highlighting untuk file `.indpy`
|
|
53
|
+
- **Lisensi MIT** — Copyright 2026 Zandero
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Kata Kunci yang Didukung (46)
|
|
58
|
+
|
|
59
|
+
| Indonesia | Python | Indonesia | Python |
|
|
60
|
+
|-----------------|-------------|--------------|------------|
|
|
61
|
+
| `fungsi` | `def` | `impor` | `import` |
|
|
62
|
+
| `kelas` | `class` | `dari` | `from` |
|
|
63
|
+
| `kembali` | `return` | `sebagai` | `as` |
|
|
64
|
+
| `kembalikan` | `return` | `menjadi` | `as` |
|
|
65
|
+
| `jika` | `if` | `coba` | `try` |
|
|
66
|
+
| `jika_tidak` | `elif` | `kecuali` | `except` |
|
|
67
|
+
| `lainnya` | `else` | `akhirnya` | `finally` |
|
|
68
|
+
| `untuk` | `for` | `naikkan` | `raise` |
|
|
69
|
+
| `selama` | `while` | `bersama` | `with` |
|
|
70
|
+
| `dalam` | `in` | `dan` | `and` |
|
|
71
|
+
| `hentikan` | `break` | `atau` | `or` |
|
|
72
|
+
| `lanjut` | `continue` | `bukan` | `not` |
|
|
73
|
+
| `lewati` | `pass` | `tidak` | `not` |
|
|
74
|
+
| `lewat` | `pass` | `benar` | `True` |
|
|
75
|
+
| `global` | `global` | `salah` | `False` |
|
|
76
|
+
| `nonlokal` | `nonlocal` | `kosong` | `None` |
|
|
77
|
+
| `hapus` | `del` | `cetak` | `print` |
|
|
78
|
+
| `lambda` | `lambda` | `masukkan` | `input` |
|
|
79
|
+
| `pernyataan` | `assert` | `panjang` | `len` |
|
|
80
|
+
| `bilangan` | `int` | `rentang` | `range` |
|
|
81
|
+
| `desimal` | `float` | `tipe` | `type` |
|
|
82
|
+
| `teks` | `str` | `daftar` | `list` |
|
|
83
|
+
| `himpunan` | `set` | `kamus` | `dict` |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
[1.0.0]: https://github.com/ZanderoDev/Indpy/releases/tag/v1.0.0
|
pyindo-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zandero
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
pyindo-1.0.0/MANIFEST.in
ADDED
pyindo-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyindo
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Transpiler Bahasa Indonesia ke Python
|
|
5
|
+
Author: Zandero
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: python,indonesia,transpiler,cli
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.8
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Dynamic: license-file
|
|
16
|
+
|
|
17
|
+
# Indpy 🇮🇩
|
|
18
|
+
|
|
19
|
+
**Indpy** adalah transpiler yang mengubah kode dengan sintaks **Bahasa Indonesia** menjadi kode Python valid, lalu langsung menjalankannya.
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
Kode .indpy → Lexer → Parser → AST → Transpiler → Python
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Instalasi
|
|
28
|
+
|
|
29
|
+
### Termux / Acode Terminal / Linux
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
curl -fsSL https://raw.githubusercontent.com/ZanderoDev/Indpy/main/install.sh | bash
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
atau jika sudah di-clone:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
bash install.sh
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Setelah instalasi, buka terminal baru lalu jalankan:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
indpy --versi
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Persyaratan
|
|
48
|
+
|
|
49
|
+
- Python 3.7 atau lebih baru
|
|
50
|
+
- Git (untuk instalasi otomatis)
|
|
51
|
+
- pytest — hanya untuk menjalankan unit test
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install pytest
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Struktur Folder
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
Indpy/
|
|
63
|
+
├── main.py # CLI entry point
|
|
64
|
+
├── lexer.py # Tokenizer — teks → token
|
|
65
|
+
├── parser.py # Parser — token → AST
|
|
66
|
+
├── transpiler.py # Generator — AST → kode Python
|
|
67
|
+
├── keywords.py # Peta kata kunci Bahasa Indonesia → Python
|
|
68
|
+
├── errors.py # Kelas error berbahasa Indonesia
|
|
69
|
+
├── install.sh # Installer otomatis
|
|
70
|
+
├── tests/
|
|
71
|
+
│ ├── test_lexer.py
|
|
72
|
+
│ ├── test_parser.py
|
|
73
|
+
│ └── test_transpiler.py
|
|
74
|
+
└── contoh/
|
|
75
|
+
├── halo_dunia.indpy # Contoh 1: Halo Dunia
|
|
76
|
+
├── kalkulator.indpy # Contoh 2: Kalkulator
|
|
77
|
+
└── loop_dan_fungsi.indpy # Contoh 3: Loop & Fungsi
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Cara Pakai
|
|
83
|
+
|
|
84
|
+
### Setelah install global (`indpy`)
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Masuk REPL interaktif
|
|
88
|
+
indpy
|
|
89
|
+
|
|
90
|
+
# Jalankan file .indpy
|
|
91
|
+
indpy namafile.indpy
|
|
92
|
+
indpy jalankan namafile.indpy
|
|
93
|
+
|
|
94
|
+
# Lihat kode Python yang dihasilkan sebelum dijalankan
|
|
95
|
+
indpy jalankan namafile.indpy --tampilkan
|
|
96
|
+
|
|
97
|
+
# Ekspor ke file .py (tanpa menjalankan)
|
|
98
|
+
indpy ekspor namafile.indpy
|
|
99
|
+
indpy ekspor namafile.indpy -o output.py
|
|
100
|
+
|
|
101
|
+
# Cek versi
|
|
102
|
+
indpy --versi
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Tanpa install (langsung dari folder)
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
python main.py jalankan contoh/halo_dunia.indpy
|
|
109
|
+
python main.py ekspor contoh/kalkulator.indpy -o hasil.py
|
|
110
|
+
python main.py repl
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## REPL Interaktif
|
|
116
|
+
|
|
117
|
+
Jalankan `indpy` tanpa argumen untuk masuk ke mode interaktif:
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
$ indpy
|
|
121
|
+
Indpy v1.0.0 (Python 3.11.6)
|
|
122
|
+
Ketik 'keluar()' atau tekan Ctrl+D untuk keluar.
|
|
123
|
+
>>> x = 10
|
|
124
|
+
>>> x * 3
|
|
125
|
+
30
|
|
126
|
+
>>> cetak("halo dari REPL")
|
|
127
|
+
halo dari REPL
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Blok multi-baris
|
|
131
|
+
|
|
132
|
+
Blok yang dibuka dengan `:` otomatis masuk ke mode multi-baris. Tekan **Enter kosong** untuk mengeksekusi:
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
>>> fungsi kuadrat(n):
|
|
136
|
+
... kembali n ** 2
|
|
137
|
+
...
|
|
138
|
+
>>> kuadrat(7)
|
|
139
|
+
49
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Pintasan keyboard
|
|
143
|
+
|
|
144
|
+
| Tombol | Aksi |
|
|
145
|
+
|--------|------|
|
|
146
|
+
| `keluar()` / `exit()` | Keluar dari REPL |
|
|
147
|
+
| Ctrl+D | Keluar dari REPL |
|
|
148
|
+
| Ctrl+C | Batalkan input saat ini (tidak keluar) |
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Kata Kunci yang Didukung
|
|
153
|
+
|
|
154
|
+
| Bahasa Indonesia | Python | Keterangan |
|
|
155
|
+
|-------------------|-------------|-------------------------|
|
|
156
|
+
| `fungsi` | `def` | Definisi fungsi |
|
|
157
|
+
| `kelas` | `class` | Definisi kelas |
|
|
158
|
+
| `kembali` | `return` | Nilai kembalian |
|
|
159
|
+
| `kembalikan` | `return` | Alias `kembali` |
|
|
160
|
+
| `jika` | `if` | Kondisi |
|
|
161
|
+
| `jika_tidak` | `elif` | Kondisi lanjutan |
|
|
162
|
+
| `lainnya` | `else` | Kondisi default |
|
|
163
|
+
| `untuk` | `for` | Loop iterasi |
|
|
164
|
+
| `selama` | `while` | Loop kondisi |
|
|
165
|
+
| `dalam` | `in` | Operator keanggotaan |
|
|
166
|
+
| `hentikan` | `break` | Keluar dari loop |
|
|
167
|
+
| `lanjut` | `continue` | Lanjut iterasi |
|
|
168
|
+
| `lewati` | `pass` | Pernyataan kosong |
|
|
169
|
+
| `lewat` | `pass` | Alias `lewati` |
|
|
170
|
+
| `impor` | `import` | Impor modul |
|
|
171
|
+
| `dari` | `from` | Impor dari modul |
|
|
172
|
+
| `sebagai` | `as` | Alias impor |
|
|
173
|
+
| `menjadi` | `as` | Alias `sebagai` |
|
|
174
|
+
| `coba` | `try` | Blok percobaan |
|
|
175
|
+
| `kecuali` | `except` | Tangkap exception |
|
|
176
|
+
| `akhirnya` | `finally` | Selalu dijalankan |
|
|
177
|
+
| `naikkan` | `raise` | Lempar exception |
|
|
178
|
+
| `bersama` | `with` | Context manager |
|
|
179
|
+
| `dan` | `and` | Operator logika |
|
|
180
|
+
| `atau` | `or` | Operator logika |
|
|
181
|
+
| `bukan` | `not` | Negasi logika |
|
|
182
|
+
| `tidak` | `not` | Alias `bukan` |
|
|
183
|
+
| `benar` | `True` | Nilai boolean |
|
|
184
|
+
| `salah` | `False` | Nilai boolean |
|
|
185
|
+
| `kosong` | `None` | Nilai null |
|
|
186
|
+
| `global` | `global` | Variabel global |
|
|
187
|
+
| `nonlokal` | `nonlocal` | Variabel closure |
|
|
188
|
+
| `hapus` | `del` | Hapus variabel |
|
|
189
|
+
| `lambda` | `lambda` | Fungsi anonim |
|
|
190
|
+
| `pernyataan` | `assert` | Pernyataan asersi |
|
|
191
|
+
| `cetak` | `print` | Tampilkan output |
|
|
192
|
+
| `masukkan` | `input` | Baca input |
|
|
193
|
+
| `panjang` | `len` | Panjang koleksi |
|
|
194
|
+
| `rentang` | `range` | Rentang angka |
|
|
195
|
+
| `tipe` | `type` | Tipe data |
|
|
196
|
+
| `bilangan` | `int` | Konversi ke bilangan |
|
|
197
|
+
| `desimal` | `float` | Konversi ke desimal |
|
|
198
|
+
| `teks` | `str` | Konversi ke teks |
|
|
199
|
+
| `daftar` | `list` | Tipe list |
|
|
200
|
+
| `kamus` | `dict` | Tipe dictionary |
|
|
201
|
+
| `himpunan` | `set` | Tipe set |
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Contoh Kode
|
|
206
|
+
|
|
207
|
+
### Halo Dunia
|
|
208
|
+
|
|
209
|
+
```indpy
|
|
210
|
+
cetak("Halo, Dunia!")
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Fungsi dan kondisi
|
|
214
|
+
|
|
215
|
+
```indpy
|
|
216
|
+
fungsi sapa(nama):
|
|
217
|
+
jika nama == "":
|
|
218
|
+
kembali "Halo, Anonim!"
|
|
219
|
+
kembali "Halo, " + nama + "!"
|
|
220
|
+
|
|
221
|
+
cetak(sapa("Budi"))
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Loop
|
|
225
|
+
|
|
226
|
+
```indpy
|
|
227
|
+
untuk i dalam rentang(1, 6):
|
|
228
|
+
cetak("Iterasi ke-" + teks(i))
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Kelas
|
|
232
|
+
|
|
233
|
+
```indpy
|
|
234
|
+
kelas Hewan:
|
|
235
|
+
fungsi __init__(diri, nama):
|
|
236
|
+
diri.nama = nama
|
|
237
|
+
|
|
238
|
+
fungsi suara(diri):
|
|
239
|
+
cetak(diri.nama, "bersuara!")
|
|
240
|
+
|
|
241
|
+
h = Hewan("Kucing")
|
|
242
|
+
h.suara()
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Penanganan error
|
|
246
|
+
|
|
247
|
+
```indpy
|
|
248
|
+
coba:
|
|
249
|
+
hasil = 10 / 0
|
|
250
|
+
kecuali ZeroDivisionError:
|
|
251
|
+
cetak("Tidak bisa membagi dengan nol!")
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Impor modul
|
|
255
|
+
|
|
256
|
+
```indpy
|
|
257
|
+
dari math impor sqrt sebagai akar_kuadrat
|
|
258
|
+
|
|
259
|
+
cetak(akar_kuadrat(16)) # → 4.0
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Keamanan String
|
|
265
|
+
|
|
266
|
+
Kata kunci di dalam tanda kutip **tidak** diterjemahkan:
|
|
267
|
+
|
|
268
|
+
```indpy
|
|
269
|
+
cetak("jika hujan, bawa payung")
|
|
270
|
+
# → print("jika hujan, bawa payung") ✓ bukan "if hujan, bawa payung"
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Menjalankan Unit Test
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
pytest tests/ -v
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Arsitektur
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
Lexer (lexer.py)
|
|
287
|
+
Membaca source code karakter per karakter.
|
|
288
|
+
Menghasilkan token: KATA_KUNCI, NAMA, ANGKA, TEKS, OP, DELIMITER,
|
|
289
|
+
INDENT, DEDENT, BARIS_BARU, EOF.
|
|
290
|
+
Longest-match-first: operator tiga karakter (mis. **=) dicek sebelum dua karakter.
|
|
291
|
+
String literal dijaga utuh — isinya tidak diproses.
|
|
292
|
+
|
|
293
|
+
Parser (parser.py)
|
|
294
|
+
Recursive Descent Parser.
|
|
295
|
+
Mengonsumsi token dan membangun AST (pohon dict Python).
|
|
296
|
+
Mendukung: penugasan, if/elif/else, while, for, def, class,
|
|
297
|
+
try/except/finally, with, import, return, break, continue, pass,
|
|
298
|
+
lambda, assert, del, global, nonlocal, eksponen kanan-asosiatif, dsb.
|
|
299
|
+
|
|
300
|
+
Transpiler (transpiler.py)
|
|
301
|
+
Menelusuri AST secara rekursif.
|
|
302
|
+
Menghasilkan kode Python valid dengan indentasi otomatis.
|
|
303
|
+
|
|
304
|
+
main.py (CLI)
|
|
305
|
+
Subperintah: jalankan | ekspor | repl
|
|
306
|
+
indpy (tanpa argumen) → langsung masuk REPL.
|
|
307
|
+
Mengorkestrasi Lexer → Parser → Transpiler → exec().
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## Lisensi
|
|
313
|
+
|
|
314
|
+
MIT — bebas digunakan dan dimodifikasi.
|