gemite 0.1.0
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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +519 -0
- data/examples/comments/README.md +13 -0
- data/examples/comments/index.gmt +65 -0
- data/examples/comments/public/css/style.css +44 -0
- data/exe/gemite +6 -0
- data/lib/gemite/ast.rb +42 -0
- data/lib/gemite/cli.rb +81 -0
- data/lib/gemite/database.rb +101 -0
- data/lib/gemite/environment.rb +73 -0
- data/lib/gemite/errors.rb +39 -0
- data/lib/gemite/function.rb +21 -0
- data/lib/gemite/http_server.rb +181 -0
- data/lib/gemite/interpreter.rb +435 -0
- data/lib/gemite/lexer.rb +289 -0
- data/lib/gemite/parser.rb +433 -0
- data/lib/gemite/request.rb +49 -0
- data/lib/gemite/router.rb +98 -0
- data/lib/gemite/sqlite3_ffi.rb +223 -0
- data/lib/gemite/template_parser.rb +305 -0
- data/lib/gemite/token.rb +11 -0
- data/lib/gemite/version.rb +5 -0
- data/lib/gemite.rb +21 -0
- metadata +69 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: eedb79d9169824c4dd1acd1b0d458c406641a99d6ee73ad54b9fd8a611145ba1
|
|
4
|
+
data.tar.gz: 6819f25750a7c35ea9f7cd801291eb00f2a756f03c17d43457476e1408f2f191
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: f1b830f0c22159cf6ba313d15c1089914f504dfacdaa802130816e981017799e848b1a0699c053d6a244e8e5c72db418894ad76df3332b91873212d9a96cfea5
|
|
7
|
+
data.tar.gz: 48fa83f5f96976adfb69ee4461351ae6425cc199c5ecb6e08a09de549a254790845058e113f023fe4e98105317c45a581dc559d536542cbe48217890cf1dd84f
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Araki-Tomoya
|
|
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.
|
data/README.md
ADDED
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+
# Gemite
|
|
2
|
+
|
|
3
|
+
> **A lightweight HTML-first programming language for building small web applications.**
|
|
4
|
+
|
|
5
|
+
Gemite is a lightweight programming language inspired by PHP. It lets you create dynamic web applications by embedding Gemite code directly into HTML.
|
|
6
|
+
|
|
7
|
+
Its philosophy is simple:
|
|
8
|
+
|
|
9
|
+
* HTML first
|
|
10
|
+
* No framework
|
|
11
|
+
* No configuration
|
|
12
|
+
* Small and fast
|
|
13
|
+
* Easy deployment
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Features
|
|
18
|
+
|
|
19
|
+
* HTML-first syntax
|
|
20
|
+
* File-based routing
|
|
21
|
+
* Built-in development server
|
|
22
|
+
* SQLite support
|
|
23
|
+
* Cross-platform (Windows, Linux, macOS)
|
|
24
|
+
* Minimal dependencies
|
|
25
|
+
* Easy to learn
|
|
26
|
+
* Ruby-powered runtime
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
# Installation
|
|
31
|
+
|
|
32
|
+
Install from RubyGems.
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
gem install gemite
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Check the installed version.
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
gemite version
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
# Quick Start
|
|
47
|
+
|
|
48
|
+
Create a new project.
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
mkdir myapp
|
|
52
|
+
cd myapp
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Create `index.gmt`.
|
|
56
|
+
|
|
57
|
+
```html
|
|
58
|
+
<?gemite
|
|
59
|
+
name = "Gemite"
|
|
60
|
+
?>
|
|
61
|
+
|
|
62
|
+
<!DOCTYPE html>
|
|
63
|
+
|
|
64
|
+
<html>
|
|
65
|
+
<head>
|
|
66
|
+
<title>Gemite</title>
|
|
67
|
+
</head>
|
|
68
|
+
|
|
69
|
+
<body>
|
|
70
|
+
<h1>Hello, {name}!</h1>
|
|
71
|
+
</body>
|
|
72
|
+
</html>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Run the development server.
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
gemite
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Open your browser.
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
http://localhost:8000
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
# Project Structure
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
myapp/
|
|
93
|
+
|
|
94
|
+
├── index.gmt
|
|
95
|
+
├── about.gmt
|
|
96
|
+
├── users/
|
|
97
|
+
│ └── list.gmt
|
|
98
|
+
│
|
|
99
|
+
├── public/
|
|
100
|
+
│ ├── css/
|
|
101
|
+
│ ├── js/
|
|
102
|
+
│ └── images/
|
|
103
|
+
│
|
|
104
|
+
└── database.db
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
URL mapping
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
index.gmt
|
|
111
|
+
↓
|
|
112
|
+
/
|
|
113
|
+
|
|
114
|
+
about.gmt
|
|
115
|
+
↓
|
|
116
|
+
/about
|
|
117
|
+
|
|
118
|
+
users/list.gmt
|
|
119
|
+
↓
|
|
120
|
+
/users/list
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
# Language Guide
|
|
126
|
+
|
|
127
|
+
## Comments
|
|
128
|
+
|
|
129
|
+
```gemite
|
|
130
|
+
// Single line comment
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Variables
|
|
136
|
+
|
|
137
|
+
```gemite
|
|
138
|
+
name = "Gemite"
|
|
139
|
+
count = 10
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Numbers
|
|
145
|
+
|
|
146
|
+
```gemite
|
|
147
|
+
a = 10
|
|
148
|
+
b = 3.14
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Strings
|
|
154
|
+
|
|
155
|
+
```gemite
|
|
156
|
+
name = "Gemite"
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Boolean
|
|
162
|
+
|
|
163
|
+
```gemite
|
|
164
|
+
true
|
|
165
|
+
false
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Arrays
|
|
171
|
+
|
|
172
|
+
```gemite
|
|
173
|
+
items = [1,2,3]
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Maps
|
|
179
|
+
|
|
180
|
+
```gemite
|
|
181
|
+
user = Map()
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Operators
|
|
187
|
+
|
|
188
|
+
Arithmetic
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
+
|
|
192
|
+
-
|
|
193
|
+
*
|
|
194
|
+
/
|
|
195
|
+
%
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Comparison
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
==
|
|
202
|
+
!=
|
|
203
|
+
<
|
|
204
|
+
<=
|
|
205
|
+
>
|
|
206
|
+
>=
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Logical
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
&&
|
|
213
|
+
||
|
|
214
|
+
!
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## if
|
|
220
|
+
|
|
221
|
+
```gemite
|
|
222
|
+
if score >= 60
|
|
223
|
+
print("Pass")
|
|
224
|
+
end
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## unless
|
|
230
|
+
|
|
231
|
+
```gemite
|
|
232
|
+
unless logged_in
|
|
233
|
+
print("Login required")
|
|
234
|
+
end
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## while
|
|
240
|
+
|
|
241
|
+
```gemite
|
|
242
|
+
while i < 10
|
|
243
|
+
i += 1
|
|
244
|
+
end
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## for
|
|
250
|
+
|
|
251
|
+
```gemite
|
|
252
|
+
for i = 0; i < 10; i += 1
|
|
253
|
+
print(i)
|
|
254
|
+
end
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## foreach
|
|
260
|
+
|
|
261
|
+
```gemite
|
|
262
|
+
foreach item in items
|
|
263
|
+
print(item)
|
|
264
|
+
end
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## break
|
|
270
|
+
|
|
271
|
+
```gemite
|
|
272
|
+
break
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## continue
|
|
278
|
+
|
|
279
|
+
```gemite
|
|
280
|
+
continue
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## return
|
|
286
|
+
|
|
287
|
+
```gemite
|
|
288
|
+
return value
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## Functions
|
|
294
|
+
|
|
295
|
+
```gemite
|
|
296
|
+
func hello(name)
|
|
297
|
+
print(name)
|
|
298
|
+
end
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## HTML Output
|
|
304
|
+
|
|
305
|
+
```html
|
|
306
|
+
<h1>{title}</h1>
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
Expressions inside `{}` are evaluated and inserted into HTML.
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
# Built-in Functions
|
|
314
|
+
|
|
315
|
+
String
|
|
316
|
+
|
|
317
|
+
```
|
|
318
|
+
len()
|
|
319
|
+
|
|
320
|
+
substr()
|
|
321
|
+
|
|
322
|
+
split()
|
|
323
|
+
|
|
324
|
+
join()
|
|
325
|
+
|
|
326
|
+
replace()
|
|
327
|
+
|
|
328
|
+
upper()
|
|
329
|
+
|
|
330
|
+
lower()
|
|
331
|
+
|
|
332
|
+
trim()
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Math
|
|
336
|
+
|
|
337
|
+
```
|
|
338
|
+
abs()
|
|
339
|
+
|
|
340
|
+
rand()
|
|
341
|
+
|
|
342
|
+
min()
|
|
343
|
+
|
|
344
|
+
max()
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Time
|
|
348
|
+
|
|
349
|
+
```
|
|
350
|
+
time()
|
|
351
|
+
|
|
352
|
+
sleep()
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Files
|
|
356
|
+
|
|
357
|
+
```
|
|
358
|
+
exists()
|
|
359
|
+
|
|
360
|
+
read()
|
|
361
|
+
|
|
362
|
+
write()
|
|
363
|
+
|
|
364
|
+
append()
|
|
365
|
+
|
|
366
|
+
delete()
|
|
367
|
+
|
|
368
|
+
mkdir()
|
|
369
|
+
|
|
370
|
+
copy()
|
|
371
|
+
|
|
372
|
+
move()
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
JSON
|
|
376
|
+
|
|
377
|
+
```
|
|
378
|
+
json_encode()
|
|
379
|
+
|
|
380
|
+
json_decode()
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
SQLite
|
|
384
|
+
|
|
385
|
+
```
|
|
386
|
+
db.open()
|
|
387
|
+
|
|
388
|
+
db.query()
|
|
389
|
+
|
|
390
|
+
db.exec()
|
|
391
|
+
|
|
392
|
+
db.close()
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
# CLI Commands
|
|
398
|
+
|
|
399
|
+
Start the development server.
|
|
400
|
+
|
|
401
|
+
```sh
|
|
402
|
+
gemite
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
Specify a port.
|
|
406
|
+
|
|
407
|
+
```sh
|
|
408
|
+
gemite s 3000
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
Show the version.
|
|
412
|
+
|
|
413
|
+
```sh
|
|
414
|
+
gemite version
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
Show help.
|
|
418
|
+
|
|
419
|
+
```sh
|
|
420
|
+
gemite help
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
# Examples
|
|
426
|
+
|
|
427
|
+
## Hello World
|
|
428
|
+
|
|
429
|
+
```html
|
|
430
|
+
<?gemite
|
|
431
|
+
name = "World"
|
|
432
|
+
?>
|
|
433
|
+
|
|
434
|
+
<h1>Hello, {name}!</h1>
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
## Counter
|
|
440
|
+
|
|
441
|
+
```gemite
|
|
442
|
+
count = count + 1
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## SQLite
|
|
448
|
+
|
|
449
|
+
```gemite
|
|
450
|
+
db = db.open("database.db")
|
|
451
|
+
rows = db.query("SELECT * FROM users")
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
# Build
|
|
457
|
+
|
|
458
|
+
Clone the repository.
|
|
459
|
+
|
|
460
|
+
```sh
|
|
461
|
+
git clone https://github.com/<YOUR_GITHUB>/gemite.git
|
|
462
|
+
cd gemite
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
Build the gem.
|
|
466
|
+
|
|
467
|
+
```sh
|
|
468
|
+
gem build gemite.gemspec
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
This creates:
|
|
472
|
+
|
|
473
|
+
```
|
|
474
|
+
gemite-x.y.z.gem
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
# Install from Source
|
|
480
|
+
|
|
481
|
+
```sh
|
|
482
|
+
gem install ./gemite-x.y.z.gem
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
Verify the installation.
|
|
486
|
+
|
|
487
|
+
```sh
|
|
488
|
+
gemite version
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
---
|
|
492
|
+
|
|
493
|
+
# Development
|
|
494
|
+
|
|
495
|
+
Install dependencies.
|
|
496
|
+
|
|
497
|
+
```sh
|
|
498
|
+
bundle install
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
Run Gemite from the source tree.
|
|
502
|
+
|
|
503
|
+
```sh
|
|
504
|
+
bundle exec gemite
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
or
|
|
508
|
+
|
|
509
|
+
```sh
|
|
510
|
+
ruby exe/gemite
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
---
|
|
514
|
+
|
|
515
|
+
# License
|
|
516
|
+
|
|
517
|
+
Gemite is released under the MIT License.
|
|
518
|
+
|
|
519
|
+
See the `LICENSE` file for details.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<?gemite
|
|
2
|
+
|
|
3
|
+
db = sqlite("comments.db")
|
|
4
|
+
|
|
5
|
+
db.exec("
|
|
6
|
+
CREATE TABLE IF NOT EXISTS comments(
|
|
7
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
8
|
+
body TEXT
|
|
9
|
+
)
|
|
10
|
+
")
|
|
11
|
+
|
|
12
|
+
@if post
|
|
13
|
+
|
|
14
|
+
db.insert(
|
|
15
|
+
"comments",
|
|
16
|
+
{
|
|
17
|
+
body: post.body
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
redirect("/")
|
|
22
|
+
|
|
23
|
+
@endif
|
|
24
|
+
|
|
25
|
+
comments =
|
|
26
|
+
db.select(
|
|
27
|
+
"comments"
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
?>
|
|
31
|
+
|
|
32
|
+
<!DOCTYPE html>
|
|
33
|
+
<html>
|
|
34
|
+
<head>
|
|
35
|
+
<meta charset="utf-8">
|
|
36
|
+
<title>コメント - Gemite Example</title>
|
|
37
|
+
<link rel="stylesheet" href="/css/style.css">
|
|
38
|
+
</head>
|
|
39
|
+
<body>
|
|
40
|
+
|
|
41
|
+
<h1>コメント</h1>
|
|
42
|
+
|
|
43
|
+
<form method="post">
|
|
44
|
+
|
|
45
|
+
<input
|
|
46
|
+
type="text"
|
|
47
|
+
name="body"
|
|
48
|
+
placeholder="コメントを入力">
|
|
49
|
+
|
|
50
|
+
<input
|
|
51
|
+
type="submit"
|
|
52
|
+
value="投稿">
|
|
53
|
+
|
|
54
|
+
</form>
|
|
55
|
+
|
|
56
|
+
<hr>
|
|
57
|
+
|
|
58
|
+
@for comment in comments
|
|
59
|
+
|
|
60
|
+
<p>{comment.body}</p>
|
|
61
|
+
|
|
62
|
+
@end
|
|
63
|
+
|
|
64
|
+
</body>
|
|
65
|
+
</html>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
body {
|
|
2
|
+
font-family: -apple-system, "Hiragino Kaku Gothic ProN", sans-serif;
|
|
3
|
+
max-width: 640px;
|
|
4
|
+
margin: 3rem auto;
|
|
5
|
+
padding: 0 1rem;
|
|
6
|
+
color: #222;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
h1 {
|
|
10
|
+
border-bottom: 3px solid #333;
|
|
11
|
+
padding-bottom: 0.5rem;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
form {
|
|
15
|
+
display: flex;
|
|
16
|
+
gap: 0.5rem;
|
|
17
|
+
margin: 1.5rem 0;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
input[type="text"] {
|
|
21
|
+
flex: 1;
|
|
22
|
+
padding: 0.5rem;
|
|
23
|
+
border: 1px solid #ccc;
|
|
24
|
+
border-radius: 4px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
input[type="submit"] {
|
|
28
|
+
padding: 0.5rem 1rem;
|
|
29
|
+
border: none;
|
|
30
|
+
border-radius: 4px;
|
|
31
|
+
background: #333;
|
|
32
|
+
color: #fff;
|
|
33
|
+
cursor: pointer;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
input[type="submit"]:hover {
|
|
37
|
+
background: #555;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
hr {
|
|
41
|
+
border: none;
|
|
42
|
+
border-top: 1px solid #eee;
|
|
43
|
+
margin: 1.5rem 0;
|
|
44
|
+
}
|
data/exe/gemite
ADDED
data/lib/gemite/ast.rb
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Gemite
|
|
4
|
+
module AST
|
|
5
|
+
# ---------- 式 (Expression) ----------
|
|
6
|
+
IntLiteral = Struct.new(:value)
|
|
7
|
+
FloatLiteral = Struct.new(:value)
|
|
8
|
+
# parts: [:str, "text"] または [:expr, ast] の配列("#{}"補間対応)
|
|
9
|
+
StringLiteral = Struct.new(:parts)
|
|
10
|
+
BoolLiteral = Struct.new(:value)
|
|
11
|
+
NilLiteral = Struct.new(:value)
|
|
12
|
+
ArrayLiteral = Struct.new(:elements)
|
|
13
|
+
# pairs: [key_symbol, value_ast] の配列
|
|
14
|
+
HashLiteral = Struct.new(:pairs)
|
|
15
|
+
Identifier = Struct.new(:name)
|
|
16
|
+
BinaryOp = Struct.new(:op, :left, :right)
|
|
17
|
+
UnaryOp = Struct.new(:op, :operand)
|
|
18
|
+
LogicalOp = Struct.new(:op, :left, :right)
|
|
19
|
+
MemberAccess = Struct.new(:receiver, :name)
|
|
20
|
+
IndexAccess = Struct.new(:receiver, :index)
|
|
21
|
+
CallExpr = Struct.new(:callee_name, :args)
|
|
22
|
+
MethodCallExpr = Struct.new(:receiver, :method_name, :args)
|
|
23
|
+
|
|
24
|
+
# ---------- 文 (Statement) ----------
|
|
25
|
+
Assignment = Struct.new(:name, :value)
|
|
26
|
+
FunctionDef = Struct.new(:name, :params, :body)
|
|
27
|
+
ReturnStmt = Struct.new(:value)
|
|
28
|
+
ExprStmt = Struct.new(:expr)
|
|
29
|
+
# branches: [[cond_ast, [stmt,...]], ...]
|
|
30
|
+
IfStmt = Struct.new(:branches, :else_body)
|
|
31
|
+
ForStmt = Struct.new(:var_name, :iterable, :body)
|
|
32
|
+
BeginCatchStmt = Struct.new(:begin_body, :err_name, :catch_body)
|
|
33
|
+
|
|
34
|
+
# ---------- テンプレートノード (HTML生テキスト側) ----------
|
|
35
|
+
TplText = Struct.new(:text)
|
|
36
|
+
TplExpr = Struct.new(:expr)
|
|
37
|
+
TplCode = Struct.new(:statements)
|
|
38
|
+
# branches: [[cond_ast, [tpl_node,...]], ...]
|
|
39
|
+
TplIf = Struct.new(:branches, :else_body)
|
|
40
|
+
TplFor = Struct.new(:var_name, :iterable, :body)
|
|
41
|
+
end
|
|
42
|
+
end
|