darijacode 0.2.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.
- package/LICENSE +130 -0
- package/README.md +78 -0
- package/dist/cli.js +77 -0
- package/dist/compiler/ast.js +2 -0
- package/dist/compiler/checker/expressions.js +248 -0
- package/dist/compiler/checker/index.js +45 -0
- package/dist/compiler/checker/scope.js +57 -0
- package/dist/compiler/checker/statements.js +255 -0
- package/dist/compiler/checker/types.js +47 -0
- package/dist/compiler/codegen/codegen.js +122 -0
- package/dist/compiler/codegen/ctype.js +23 -0
- package/dist/compiler/codegen/expr.js +63 -0
- package/dist/compiler/codegen/infertype.js +70 -0
- package/dist/compiler/codegen/runtime.js +24 -0
- package/dist/compiler/codegen/scope.js +19 -0
- package/dist/compiler/codegen/stmts.js +90 -0
- package/dist/compiler/codegen/types.js +2 -0
- package/dist/compiler/compiler.js +115 -0
- package/dist/compiler/errors.js +59 -0
- package/dist/compiler/index.js +69 -0
- package/dist/compiler/lexer.js +303 -0
- package/dist/compiler/parser.js +513 -0
- package/dist/compiler/tokens.js +68 -0
- package/dist/utils/showType.js +10 -0
- package/package.json +58 -0
|
@@ -0,0 +1,513 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Parser = void 0;
|
|
4
|
+
const tokens_1 = require("./tokens");
|
|
5
|
+
const errors_1 = require("./errors");
|
|
6
|
+
// NOTE: class parsing (jdid / this) is intentionally not implemented yet.
|
|
7
|
+
// The lexer does not tokenize `this` or `jdid` as keywords, so classes
|
|
8
|
+
// stay identifiers-only for now. Add THIS/JDID token types first.
|
|
9
|
+
// NOTE: `dwr (item in array)` and `dwr (index, value of items)` are not
|
|
10
|
+
// implemented yet either — the lexer has no IN/OF tokens. Only the
|
|
11
|
+
// classic C-style `dwr (init; condition; update)` form is supported.
|
|
12
|
+
const masofa = "mosfofa[hoja1, hoja2, hoja3]";
|
|
13
|
+
class Parser {
|
|
14
|
+
tokens;
|
|
15
|
+
pos = 0;
|
|
16
|
+
constructor(tokens) {
|
|
17
|
+
this.tokens = tokens;
|
|
18
|
+
}
|
|
19
|
+
parse() {
|
|
20
|
+
const body = [];
|
|
21
|
+
this.skipNewlines();
|
|
22
|
+
while (!this.isEnd()) {
|
|
23
|
+
body.push(this.statement());
|
|
24
|
+
this.skipNewlines();
|
|
25
|
+
}
|
|
26
|
+
return { type: "Program", body, pos: { line: 1, column: 1 } };
|
|
27
|
+
}
|
|
28
|
+
statement() {
|
|
29
|
+
this.skipNewlines();
|
|
30
|
+
const token = this.peek();
|
|
31
|
+
switch (token.type) {
|
|
32
|
+
case tokens_1.TokenType.DIR:
|
|
33
|
+
return this.variableDeclaration("dir");
|
|
34
|
+
case tokens_1.TokenType.KHLI:
|
|
35
|
+
return this.variableDeclaration("khli");
|
|
36
|
+
case tokens_1.TokenType.FN:
|
|
37
|
+
return this.functionDeclaration();
|
|
38
|
+
case tokens_1.TokenType.RAJ3:
|
|
39
|
+
return this.returnStatement();
|
|
40
|
+
case tokens_1.TokenType.ILA:
|
|
41
|
+
return this.ifStatement();
|
|
42
|
+
case tokens_1.TokenType.MAHD:
|
|
43
|
+
return this.whileStatement();
|
|
44
|
+
case tokens_1.TokenType.DWR:
|
|
45
|
+
return this.forStatement();
|
|
46
|
+
case tokens_1.TokenType.QTA3:
|
|
47
|
+
return this.breakStatement();
|
|
48
|
+
case tokens_1.TokenType.KAML:
|
|
49
|
+
return this.continueStatement();
|
|
50
|
+
case tokens_1.TokenType.KTEB:
|
|
51
|
+
return this.printStatement();
|
|
52
|
+
case tokens_1.TokenType.LBRACE:
|
|
53
|
+
return this.block();
|
|
54
|
+
default:
|
|
55
|
+
return this.expressionStatement();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
variableDeclaration(kind) {
|
|
59
|
+
const pos = this.pos_();
|
|
60
|
+
this.advance(); // dir | khli
|
|
61
|
+
const name = this.expect(tokens_1.TokenType.IDENTF, "twa93na smya dyal mutaghayer", "DCE10").value;
|
|
62
|
+
let typeAnnotation = undefined;
|
|
63
|
+
if (this.match(tokens_1.TokenType.COLON)) {
|
|
64
|
+
typeAnnotation = this.typeAnnotation();
|
|
65
|
+
}
|
|
66
|
+
let init = null;
|
|
67
|
+
if (this.match(tokens_1.TokenType.EQUAL) || this.checkPrev(tokens_1.TokenType.COLONEQUAL)) {
|
|
68
|
+
init = this.expression();
|
|
69
|
+
}
|
|
70
|
+
else if (this.match(tokens_1.TokenType.COLONEQUAL)) {
|
|
71
|
+
init = this.expression();
|
|
72
|
+
}
|
|
73
|
+
this.consumeEOS();
|
|
74
|
+
return { type: "VariableDeclaration", kind, name, typeAnnotation, init, pos };
|
|
75
|
+
}
|
|
76
|
+
typeAnnotation() {
|
|
77
|
+
const djtype = { base: "khawi", d: 0 };
|
|
78
|
+
let type = this.expect(tokens_1.TokenType.IDENTF, "twa93na smya dyal chi naw3", "DCE10", "lanwa3 li mmkdin tdirhom : 'ra9m', 'nass', 'tona2i' awla dir khawi k9ima").value;
|
|
79
|
+
switch (type) {
|
|
80
|
+
case "ra9m":
|
|
81
|
+
case "nass":
|
|
82
|
+
case "tona2i":
|
|
83
|
+
case "khawi":
|
|
84
|
+
case "unknown":
|
|
85
|
+
case "walo":
|
|
86
|
+
djtype.base = type;
|
|
87
|
+
break;
|
|
88
|
+
default:
|
|
89
|
+
this.error(`naw3 dyal '${type}' makaynch awla mmd3omch`, "DCE15", "dir chi naw3 md3om bhal: 'ra9m', 'nass' etc ..");
|
|
90
|
+
}
|
|
91
|
+
while (this.check(tokens_1.TokenType.LBRACT)) {
|
|
92
|
+
this.advance();
|
|
93
|
+
this.expect(tokens_1.TokenType.RBRACT, "twa93na ']' mora '[' f naw3", "DCE3");
|
|
94
|
+
djtype.d = (djtype.d ?? 0) + 1;
|
|
95
|
+
}
|
|
96
|
+
return djtype;
|
|
97
|
+
}
|
|
98
|
+
params() {
|
|
99
|
+
const params = [];
|
|
100
|
+
this.expect(tokens_1.TokenType.LPAREN, "twa93na '(' 9bal mn lmo3amilat", "DCE5");
|
|
101
|
+
while (!this.check(tokens_1.TokenType.RPAREN)) {
|
|
102
|
+
const pos = this.pos_();
|
|
103
|
+
const name = this.expect(tokens_1.TokenType.IDENTF, "twa93na smya llmo3amilat", "DCE10").value;
|
|
104
|
+
let typeAnnotation = { base: "khawi", d: 0 };
|
|
105
|
+
if (this.match(tokens_1.TokenType.COLON)) {
|
|
106
|
+
typeAnnotation = this.typeAnnotation();
|
|
107
|
+
}
|
|
108
|
+
let defaultValue = null;
|
|
109
|
+
if (this.match(tokens_1.TokenType.EQUAL)) {
|
|
110
|
+
defaultValue = this.expression();
|
|
111
|
+
}
|
|
112
|
+
params.push({
|
|
113
|
+
type: "Param",
|
|
114
|
+
name,
|
|
115
|
+
typeAnnotation,
|
|
116
|
+
defaultValue,
|
|
117
|
+
rest: false,
|
|
118
|
+
pos,
|
|
119
|
+
});
|
|
120
|
+
if (!this.check(tokens_1.TokenType.RPAREN)) {
|
|
121
|
+
this.expect(tokens_1.TokenType.COMMA, "twa93nz ',' bin lmo3amilat", "DCE4");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
this.expect(tokens_1.TokenType.RPAREN, "twa93na ')' mora lmo3amilat", "DCE5");
|
|
125
|
+
return params;
|
|
126
|
+
}
|
|
127
|
+
functionDeclaration() {
|
|
128
|
+
const pos = this.pos_();
|
|
129
|
+
this.advance(); // fn
|
|
130
|
+
const name = this.expect(tokens_1.TokenType.IDENTF, "tw93na smya l ddalla", "DCE10", "fn smya(){}").value;
|
|
131
|
+
const fnParams = this.params();
|
|
132
|
+
let returnType = { base: "khawi", d: 0 };
|
|
133
|
+
if (this.match(tokens_1.TokenType.COLON)) {
|
|
134
|
+
returnType = this.typeAnnotation();
|
|
135
|
+
}
|
|
136
|
+
const body = this.block();
|
|
137
|
+
return { type: "FunctionDeclaration", name, params: fnParams, returnType: returnType ?? "khawi", body, pos };
|
|
138
|
+
}
|
|
139
|
+
returnStatement() {
|
|
140
|
+
const pos = this.pos_();
|
|
141
|
+
this.advance(); // raj3
|
|
142
|
+
let argument = null;
|
|
143
|
+
if (!this.check(tokens_1.TokenType.EOS) && !this.check(tokens_1.TokenType.RBRACE)) {
|
|
144
|
+
argument = this.expression();
|
|
145
|
+
}
|
|
146
|
+
this.consumeEOS();
|
|
147
|
+
return { type: "ReturnStatement", argument, pos };
|
|
148
|
+
}
|
|
149
|
+
ifStatement() {
|
|
150
|
+
const pos = this.pos_();
|
|
151
|
+
this.advance(); // ila
|
|
152
|
+
this.expect(tokens_1.TokenType.LPAREN, "tw93na '(' mora 'ila'", "DCE5");
|
|
153
|
+
const condition = this.expression();
|
|
154
|
+
this.expect(tokens_1.TokenType.RPAREN, "twa93na ')' more chart", "DCE5");
|
|
155
|
+
const consequent = this.block();
|
|
156
|
+
const elseIfs = [];
|
|
157
|
+
this.skipNewlines();
|
|
158
|
+
while (this.check(tokens_1.TokenType.AWLA)) {
|
|
159
|
+
this.advance();
|
|
160
|
+
this.expect(tokens_1.TokenType.LPAREN, "twa93na '(' mora 'awla'", "DCE5");
|
|
161
|
+
const elseIfCondition = this.expression();
|
|
162
|
+
this.expect(tokens_1.TokenType.RPAREN, "twa93na ')' mora chart", "DCE5");
|
|
163
|
+
const elseIfBody = this.block();
|
|
164
|
+
elseIfs.push({ condition: elseIfCondition, consequent: elseIfBody });
|
|
165
|
+
this.skipNewlines();
|
|
166
|
+
}
|
|
167
|
+
let alternate = null;
|
|
168
|
+
if (this.check(tokens_1.TokenType.WLA)) {
|
|
169
|
+
this.advance();
|
|
170
|
+
alternate = this.block();
|
|
171
|
+
}
|
|
172
|
+
return { type: "IfStatement", condition, consequent, elseIfs, alternate, pos };
|
|
173
|
+
}
|
|
174
|
+
whileStatement() {
|
|
175
|
+
const pos = this.pos_();
|
|
176
|
+
this.advance(); // mahd
|
|
177
|
+
this.expect(tokens_1.TokenType.LPAREN, "twa93na '(' mora 'mahd'", "DC5");
|
|
178
|
+
const condition = this.expression();
|
|
179
|
+
this.expect(tokens_1.TokenType.RPAREN, "twa93na ')' mora chart", "DCE5");
|
|
180
|
+
const body = this.block();
|
|
181
|
+
return { type: "WhileStatement", condition, body, pos };
|
|
182
|
+
}
|
|
183
|
+
forStatement() {
|
|
184
|
+
const pos = this.pos_();
|
|
185
|
+
this.advance(); // dwr
|
|
186
|
+
this.expect(tokens_1.TokenType.LPAREN, "twa93na '(' mora 'dwr'", "DCE5");
|
|
187
|
+
let init = null;
|
|
188
|
+
if (!this.check(tokens_1.TokenType.EOS)) {
|
|
189
|
+
init = this.check(tokens_1.TokenType.DIR)
|
|
190
|
+
? this.variableDeclaration("dir")
|
|
191
|
+
: this.expressionStatement();
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
this.advance(); // consume the ';'
|
|
195
|
+
}
|
|
196
|
+
let condition = null;
|
|
197
|
+
if (!this.check(tokens_1.TokenType.EOS)) {
|
|
198
|
+
condition = this.expression();
|
|
199
|
+
}
|
|
200
|
+
this.expect(tokens_1.TokenType.EOS, "twa93na ';' mora chart dyal tdwar", "DCE2");
|
|
201
|
+
let update = null;
|
|
202
|
+
if (!this.check(tokens_1.TokenType.RPAREN)) {
|
|
203
|
+
update = this.expression();
|
|
204
|
+
}
|
|
205
|
+
this.expect(tokens_1.TokenType.RPAREN, "twa93na ')' mora ljomla dyal 'dwr'", "DCE5");
|
|
206
|
+
const body = this.block();
|
|
207
|
+
return { type: "ForStatement", init, condition, update, body, pos };
|
|
208
|
+
}
|
|
209
|
+
breakStatement() {
|
|
210
|
+
const pos = this.pos_();
|
|
211
|
+
this.advance(); // qta3
|
|
212
|
+
this.consumeEOS();
|
|
213
|
+
return { type: "BreakStatement", pos };
|
|
214
|
+
}
|
|
215
|
+
continueStatement() {
|
|
216
|
+
const pos = this.pos_();
|
|
217
|
+
this.advance(); // kml
|
|
218
|
+
this.consumeEOS();
|
|
219
|
+
return { type: "ContinueStatement", pos };
|
|
220
|
+
}
|
|
221
|
+
printStatement() {
|
|
222
|
+
const pos = this.pos_();
|
|
223
|
+
this.advance(); // kteb
|
|
224
|
+
this.expect(tokens_1.TokenType.LPAREN, "twa93na '(' mora 'kteb'", "DCE5", "kteb(chi haja)");
|
|
225
|
+
const argument = this.expression();
|
|
226
|
+
this.expect(tokens_1.TokenType.RPAREN, "twa93na ')' mora lhoja dyal kteb", "DCE5", "kteb(chi haja)");
|
|
227
|
+
this.consumeEOS();
|
|
228
|
+
return { type: "PrintStatement", argument, pos };
|
|
229
|
+
}
|
|
230
|
+
block() {
|
|
231
|
+
const pos = this.pos_();
|
|
232
|
+
this.expect(tokens_1.TokenType.LBRACE, "twa93na '{'", "DCE9", "zid '{'");
|
|
233
|
+
this.skipNewlines();
|
|
234
|
+
const body = [];
|
|
235
|
+
while (!this.check(tokens_1.TokenType.RBRACE) && !this.isEnd()) {
|
|
236
|
+
body.push(this.statement());
|
|
237
|
+
this.skipNewlines();
|
|
238
|
+
}
|
|
239
|
+
this.expect(tokens_1.TokenType.RBRACE, "twa93na '}'", "DCE9", "zid '}'");
|
|
240
|
+
return { type: "BlockStatement", body, pos };
|
|
241
|
+
}
|
|
242
|
+
expressionStatement() {
|
|
243
|
+
const pos = this.pos_();
|
|
244
|
+
const expression = this.expression();
|
|
245
|
+
this.consumeEOS();
|
|
246
|
+
return { type: "ExpressionStatement", expression, pos };
|
|
247
|
+
}
|
|
248
|
+
// ---------------------------------------------
|
|
249
|
+
// Expressions (precedence climbing)
|
|
250
|
+
// ---------------------------------------------
|
|
251
|
+
expression() {
|
|
252
|
+
return this.assignment();
|
|
253
|
+
}
|
|
254
|
+
assignment() {
|
|
255
|
+
const target = this.conditional();
|
|
256
|
+
const assignOps = {
|
|
257
|
+
[tokens_1.TokenType.EQUAL]: "=",
|
|
258
|
+
};
|
|
259
|
+
if (this.check(tokens_1.TokenType.EQUAL)) {
|
|
260
|
+
const pos = this.pos_();
|
|
261
|
+
this.advance();
|
|
262
|
+
const value = this.assignment();
|
|
263
|
+
return { type: "AssignmentExpression", operator: "=", target, value, pos };
|
|
264
|
+
}
|
|
265
|
+
return target;
|
|
266
|
+
}
|
|
267
|
+
conditional() {
|
|
268
|
+
const condition = this.logicalOr();
|
|
269
|
+
if (this.check(tokens_1.TokenType.QUESTION)) {
|
|
270
|
+
const pos = this.pos_();
|
|
271
|
+
this.advance();
|
|
272
|
+
const consequent = this.assignment();
|
|
273
|
+
this.expect(tokens_1.TokenType.COLON, "twa93na ':' f ta3bir chart tolaty", "DCE8");
|
|
274
|
+
const alternate = this.assignment();
|
|
275
|
+
return { type: "ConditionalExpression", condition, consequent, alternate, pos };
|
|
276
|
+
}
|
|
277
|
+
return condition;
|
|
278
|
+
}
|
|
279
|
+
logicalOr() {
|
|
280
|
+
let left = this.logicalAnd();
|
|
281
|
+
while (this.check(tokens_1.TokenType.OR)) {
|
|
282
|
+
const pos = this.pos_();
|
|
283
|
+
this.advance();
|
|
284
|
+
const right = this.logicalAnd();
|
|
285
|
+
left = { type: "LogicalExpression", operator: "||", left, right, pos };
|
|
286
|
+
}
|
|
287
|
+
return left;
|
|
288
|
+
}
|
|
289
|
+
logicalAnd() {
|
|
290
|
+
let left = this.equality();
|
|
291
|
+
while (this.check(tokens_1.TokenType.AND)) {
|
|
292
|
+
const pos = this.pos_();
|
|
293
|
+
this.advance();
|
|
294
|
+
const right = this.equality();
|
|
295
|
+
left = { type: "LogicalExpression", operator: "&&", left, right, pos };
|
|
296
|
+
}
|
|
297
|
+
return left;
|
|
298
|
+
}
|
|
299
|
+
equality() {
|
|
300
|
+
let left = this.relational();
|
|
301
|
+
while (this.check(tokens_1.TokenType.EQEQ) || this.check(tokens_1.TokenType.NOTEQ)) {
|
|
302
|
+
const pos = this.pos_();
|
|
303
|
+
const operator = this.advance().type === tokens_1.TokenType.EQEQ ? "==" : "!=";
|
|
304
|
+
const right = this.relational();
|
|
305
|
+
left = { type: "BinaryExpression", operator, left, right, pos };
|
|
306
|
+
}
|
|
307
|
+
return left;
|
|
308
|
+
}
|
|
309
|
+
relational() {
|
|
310
|
+
let left = this.additive();
|
|
311
|
+
while (this.check(tokens_1.TokenType.LT) ||
|
|
312
|
+
this.check(tokens_1.TokenType.LTEQ) ||
|
|
313
|
+
this.check(tokens_1.TokenType.GT) ||
|
|
314
|
+
this.check(tokens_1.TokenType.GTEQ)) {
|
|
315
|
+
const pos = this.pos_();
|
|
316
|
+
const opToken = this.advance();
|
|
317
|
+
const operator = { LT: "<", LTEQ: "<=", GT: ">", GTEQ: ">=" }[opToken.type];
|
|
318
|
+
const right = this.additive();
|
|
319
|
+
left = { type: "BinaryExpression", operator, left, right, pos };
|
|
320
|
+
}
|
|
321
|
+
return left;
|
|
322
|
+
}
|
|
323
|
+
additive() {
|
|
324
|
+
let left = this.multiplicative();
|
|
325
|
+
while (this.check(tokens_1.TokenType.PLUS) || this.check(tokens_1.TokenType.MINUS)) {
|
|
326
|
+
const pos = this.pos_();
|
|
327
|
+
const operator = this.advance().type === tokens_1.TokenType.PLUS ? "+" : "-";
|
|
328
|
+
const right = this.multiplicative();
|
|
329
|
+
left = { type: "BinaryExpression", operator, left, right, pos };
|
|
330
|
+
}
|
|
331
|
+
return left;
|
|
332
|
+
}
|
|
333
|
+
multiplicative() {
|
|
334
|
+
let left = this.power();
|
|
335
|
+
while (this.check(tokens_1.TokenType.STAR) ||
|
|
336
|
+
this.check(tokens_1.TokenType.SLASH) ||
|
|
337
|
+
this.check(tokens_1.TokenType.PERCENT)) {
|
|
338
|
+
const pos = this.pos_();
|
|
339
|
+
const opToken = this.advance();
|
|
340
|
+
const operator = { STAR: "*", SLASH: "/", PERCENT: "%" }[opToken.type];
|
|
341
|
+
const right = this.power();
|
|
342
|
+
left = { type: "BinaryExpression", operator, left, right, pos };
|
|
343
|
+
}
|
|
344
|
+
return left;
|
|
345
|
+
}
|
|
346
|
+
power() {
|
|
347
|
+
const left = this.unary();
|
|
348
|
+
if (this.check(tokens_1.TokenType.POWER)) {
|
|
349
|
+
const pos = this.pos_();
|
|
350
|
+
this.advance();
|
|
351
|
+
const right = this.power(); // right-associative
|
|
352
|
+
return { type: "BinaryExpression", operator: "**", left, right, pos };
|
|
353
|
+
}
|
|
354
|
+
return left;
|
|
355
|
+
}
|
|
356
|
+
unary() {
|
|
357
|
+
if (this.check(tokens_1.TokenType.NOT) || this.check(tokens_1.TokenType.MINUS)) {
|
|
358
|
+
const pos = this.pos_();
|
|
359
|
+
const operator = this.advance().type === tokens_1.TokenType.NOT ? "!" : "-";
|
|
360
|
+
const argument = this.unary();
|
|
361
|
+
return { type: "UnaryExpression", operator, argument, pos };
|
|
362
|
+
}
|
|
363
|
+
return this.postfix();
|
|
364
|
+
}
|
|
365
|
+
postfix() {
|
|
366
|
+
let expr = this.call();
|
|
367
|
+
if (this.check(tokens_1.TokenType.PLUSPLUS) || this.check(tokens_1.TokenType.MINUSMINUS)) {
|
|
368
|
+
const pos = this.pos_();
|
|
369
|
+
const operator = this.advance().type === tokens_1.TokenType.PLUSPLUS ? "++" : "--";
|
|
370
|
+
expr = { type: "UpdateExpression", operator, argument: expr, prefix: false, pos };
|
|
371
|
+
}
|
|
372
|
+
return expr;
|
|
373
|
+
}
|
|
374
|
+
call() {
|
|
375
|
+
let expr = this.primary();
|
|
376
|
+
while (true) {
|
|
377
|
+
if (this.check(tokens_1.TokenType.LPAREN)) {
|
|
378
|
+
const pos = this.pos_();
|
|
379
|
+
this.advance();
|
|
380
|
+
const args = [];
|
|
381
|
+
while (!this.check(tokens_1.TokenType.RPAREN)) {
|
|
382
|
+
args.push(this.expression());
|
|
383
|
+
if (!this.check(tokens_1.TokenType.RPAREN)) {
|
|
384
|
+
this.expect(tokens_1.TokenType.COMMA, "twa93na ',' bin lhojaj", "DCE4", masofa);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
this.expect(tokens_1.TokenType.RPAREN, "twa93na ')' mora lhojaj", "DCE5");
|
|
388
|
+
expr = { type: "CallExpression", callee: expr, args, pos };
|
|
389
|
+
}
|
|
390
|
+
else if (this.check(tokens_1.TokenType.DOT)) {
|
|
391
|
+
const pos = this.pos_();
|
|
392
|
+
this.advance();
|
|
393
|
+
const property = this.expect(tokens_1.TokenType.IDENTF, "twa93na smya dyal lkhasiya mora '.'", "DCE7").value;
|
|
394
|
+
expr = {
|
|
395
|
+
type: "MemberExpression",
|
|
396
|
+
object: expr,
|
|
397
|
+
property: { type: "Identifier", name: property, pos },
|
|
398
|
+
computed: false,
|
|
399
|
+
pos,
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
else if (this.check(tokens_1.TokenType.LBRACT)) {
|
|
403
|
+
const pos = this.pos_();
|
|
404
|
+
this.advance();
|
|
405
|
+
const property = this.expression();
|
|
406
|
+
this.expect(tokens_1.TokenType.RBRACT, "twa93na ']' mora lfahras", "DCE3", "mosfofa[ra9m]");
|
|
407
|
+
expr = { type: "MemberExpression", object: expr, property, computed: true, pos };
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return expr;
|
|
414
|
+
}
|
|
415
|
+
primary() {
|
|
416
|
+
const token = this.peek();
|
|
417
|
+
const pos = this.pos_();
|
|
418
|
+
if (this.match(tokens_1.TokenType.NUMBER)) {
|
|
419
|
+
return { type: "NumericLiteral", value: Number(token.value), pos };
|
|
420
|
+
}
|
|
421
|
+
if (this.match(tokens_1.TokenType.STRING)) {
|
|
422
|
+
return { type: "StringLiteral", value: token.value, pos };
|
|
423
|
+
}
|
|
424
|
+
if (this.match(tokens_1.TokenType.TRUE)) {
|
|
425
|
+
return { type: "BooleanLiteral", value: true, pos };
|
|
426
|
+
}
|
|
427
|
+
if (this.match(tokens_1.TokenType.FALSE)) {
|
|
428
|
+
return { type: "BooleanLiteral", value: false, pos };
|
|
429
|
+
}
|
|
430
|
+
if (this.match(tokens_1.TokenType.NULL)) {
|
|
431
|
+
return { type: "NullLiteral", pos };
|
|
432
|
+
}
|
|
433
|
+
if (this.match(tokens_1.TokenType.IDENTF)) {
|
|
434
|
+
return { type: "Identifier", name: token.value, pos };
|
|
435
|
+
}
|
|
436
|
+
if (this.match(tokens_1.TokenType.LPAREN)) {
|
|
437
|
+
const expr = this.expression();
|
|
438
|
+
this.expect(tokens_1.TokenType.RPAREN, "twa93na ')' mora tta3bir", "DCE5");
|
|
439
|
+
return expr;
|
|
440
|
+
}
|
|
441
|
+
if (this.match(tokens_1.TokenType.LBRACT)) {
|
|
442
|
+
const elements = [];
|
|
443
|
+
while (!this.check(tokens_1.TokenType.RBRACT)) {
|
|
444
|
+
elements.push(this.expression());
|
|
445
|
+
if (!this.check(tokens_1.TokenType.RBRACT)) {
|
|
446
|
+
this.expect(tokens_1.TokenType.COMMA, "twa93na ',' bin l3anasir dyal lmasfofa", "DCE4", masofa);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
this.expect(tokens_1.TokenType.RBRACT, "twa93na ']' mora l3anasir dyal lmasfofa", "DCE3", masofa);
|
|
450
|
+
return { type: "ArrayExpression", elements, pos };
|
|
451
|
+
}
|
|
452
|
+
if (token.value === "\\n") {
|
|
453
|
+
this.error(`token mmtw93ach: 'star jdid'`, "DCE1");
|
|
454
|
+
}
|
|
455
|
+
this.error(`token mmtw93ach: '${token.value}'`, "DCE1");
|
|
456
|
+
}
|
|
457
|
+
consumeEOS() {
|
|
458
|
+
this.skipNewlines();
|
|
459
|
+
this.expect(tokens_1.TokenType.EOS, "twa93na ';'", "DCE2");
|
|
460
|
+
}
|
|
461
|
+
skipNewlines() {
|
|
462
|
+
while (this.check(tokens_1.TokenType.NEWLINE)) {
|
|
463
|
+
this.advance();
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
peek(offset = 0) {
|
|
467
|
+
return this.tokens[this.pos + offset];
|
|
468
|
+
}
|
|
469
|
+
check(type) {
|
|
470
|
+
return this.peek().type === type;
|
|
471
|
+
}
|
|
472
|
+
checkPrev(type) {
|
|
473
|
+
return this.tokens[this.pos - 1]?.type === type;
|
|
474
|
+
}
|
|
475
|
+
match(type) {
|
|
476
|
+
if (!this.check(type))
|
|
477
|
+
return false;
|
|
478
|
+
this.advance();
|
|
479
|
+
return true;
|
|
480
|
+
}
|
|
481
|
+
advance() {
|
|
482
|
+
const token = this.tokens[this.pos];
|
|
483
|
+
if (!this.isEnd())
|
|
484
|
+
this.pos++;
|
|
485
|
+
return token;
|
|
486
|
+
}
|
|
487
|
+
expect(type, message, ecode, hint) {
|
|
488
|
+
if (this.check(type))
|
|
489
|
+
return this.advance();
|
|
490
|
+
this.error(message, ecode, hint);
|
|
491
|
+
}
|
|
492
|
+
isEnd() {
|
|
493
|
+
return this.peek().type === tokens_1.TokenType.EOF;
|
|
494
|
+
}
|
|
495
|
+
pos_() {
|
|
496
|
+
const token = this.peek();
|
|
497
|
+
return { line: token.line, column: token.column };
|
|
498
|
+
}
|
|
499
|
+
error(message, ecode, hint) {
|
|
500
|
+
const token = this.peek();
|
|
501
|
+
throw new errors_1.DarijaError({
|
|
502
|
+
code: ecode,
|
|
503
|
+
stage: "parser",
|
|
504
|
+
message,
|
|
505
|
+
location: {
|
|
506
|
+
line: token.line,
|
|
507
|
+
column: token.column
|
|
508
|
+
},
|
|
509
|
+
hint: hint ? hint : ''
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
exports.Parser = Parser;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TokenType = void 0;
|
|
4
|
+
var TokenType;
|
|
5
|
+
(function (TokenType) {
|
|
6
|
+
// literals
|
|
7
|
+
TokenType["IDENTF"] = "IDENTF";
|
|
8
|
+
TokenType["NUMBER"] = "NUMBER";
|
|
9
|
+
TokenType["STRING"] = "STRING";
|
|
10
|
+
TokenType["TRUE"] = "TRUE";
|
|
11
|
+
TokenType["FALSE"] = "FALSE";
|
|
12
|
+
TokenType["NULL"] = "NULL";
|
|
13
|
+
// declarations
|
|
14
|
+
TokenType["DIR"] = "DIR";
|
|
15
|
+
TokenType["KHLI"] = "KHLI";
|
|
16
|
+
// functions
|
|
17
|
+
TokenType["FN"] = "FN";
|
|
18
|
+
TokenType["RAJ3"] = "RAJ3";
|
|
19
|
+
// control flow
|
|
20
|
+
TokenType["ILA"] = "ILA";
|
|
21
|
+
TokenType["AWLA"] = "AWLA";
|
|
22
|
+
TokenType["WLA"] = "WLA";
|
|
23
|
+
TokenType["MAHD"] = "MAHD";
|
|
24
|
+
TokenType["DWR"] = "DWR";
|
|
25
|
+
TokenType["QTA3"] = "QTA3";
|
|
26
|
+
TokenType["KAML"] = "KAML";
|
|
27
|
+
// classes
|
|
28
|
+
TokenType["CLASS"] = "CLASS";
|
|
29
|
+
TokenType["DIRFLBLASA"] = "DIRFLBLASA";
|
|
30
|
+
TokenType["WRAATMN"] = "WRAATMN";
|
|
31
|
+
// built-in I/O
|
|
32
|
+
TokenType["KTEB"] = "KTEB";
|
|
33
|
+
// punctuation
|
|
34
|
+
TokenType["LPAREN"] = "LPAREN";
|
|
35
|
+
TokenType["RPAREN"] = "RPAREN";
|
|
36
|
+
TokenType["LBRACE"] = "LBRACE";
|
|
37
|
+
TokenType["RBRACE"] = "RBRACE";
|
|
38
|
+
TokenType["LBRACT"] = "LBRACT";
|
|
39
|
+
TokenType["RBRACT"] = "RBRACT";
|
|
40
|
+
TokenType["DOT"] = "DOT";
|
|
41
|
+
TokenType["COMMA"] = "COMMA";
|
|
42
|
+
TokenType["QUESTION"] = "QUESTION";
|
|
43
|
+
TokenType["EOS"] = "EOS";
|
|
44
|
+
// operators
|
|
45
|
+
TokenType["PLUS"] = "PLUS";
|
|
46
|
+
TokenType["PLUSPLUS"] = "PLUSPLUS";
|
|
47
|
+
TokenType["MINUS"] = "MINUS";
|
|
48
|
+
TokenType["MINUSMINUS"] = "MINUSMINUS";
|
|
49
|
+
TokenType["STAR"] = "STAR";
|
|
50
|
+
TokenType["POWER"] = "POWER";
|
|
51
|
+
TokenType["SLASH"] = "SLASH";
|
|
52
|
+
TokenType["PERCENT"] = "PERCENT";
|
|
53
|
+
TokenType["EQUAL"] = "EQUAL";
|
|
54
|
+
TokenType["EQEQ"] = "EQEQ";
|
|
55
|
+
TokenType["NOT"] = "NOT";
|
|
56
|
+
TokenType["NOTEQ"] = "NOTEQ";
|
|
57
|
+
TokenType["LT"] = "LT";
|
|
58
|
+
TokenType["LTEQ"] = "LTEQ";
|
|
59
|
+
TokenType["GT"] = "GT";
|
|
60
|
+
TokenType["GTEQ"] = "GTEQ";
|
|
61
|
+
TokenType["AND"] = "AND";
|
|
62
|
+
TokenType["OR"] = "OR";
|
|
63
|
+
TokenType["COLON"] = "COLON";
|
|
64
|
+
TokenType["COLONEQUAL"] = "COLONEQUAL";
|
|
65
|
+
// structural
|
|
66
|
+
TokenType["NEWLINE"] = "NEWLINE";
|
|
67
|
+
TokenType["EOF"] = "EOF";
|
|
68
|
+
})(TokenType || (exports.TokenType = TokenType = {}));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.showType = showType;
|
|
4
|
+
exports.isType = isType;
|
|
5
|
+
function showType(type) {
|
|
6
|
+
return type.d ? type.base + "[]".repeat(type.d) : type.base;
|
|
7
|
+
}
|
|
8
|
+
function isType(type, base, d = 0) {
|
|
9
|
+
return type.base === base && type.d === d;
|
|
10
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "darijacode",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "A new programming languages based on Moroccan words to let people on morocco learn programming fast without need to english or learn advanced concepts",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"DarijaCode",
|
|
7
|
+
"programming",
|
|
8
|
+
"language",
|
|
9
|
+
"morocco"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://github.com/krnl0xsns1nk/DarijaCode#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/krnl0xsns1nk/DarijaCode/issues"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/krnl0xsns1nk/DarijaCode.git"
|
|
18
|
+
},
|
|
19
|
+
"license": "DCL",
|
|
20
|
+
"author": "krnl0xsns1nk",
|
|
21
|
+
"type": "commonJs",
|
|
22
|
+
"main": "compiler/index.js",
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=16.0.0"
|
|
25
|
+
},
|
|
26
|
+
"bin": {
|
|
27
|
+
"drj": "dist/cli.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"README.md",
|
|
32
|
+
"LICENSE"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"prepublishOnly": "npm run setup",
|
|
36
|
+
"build": "tsc && tsc-alias && chmod +x dist/cli.js",
|
|
37
|
+
"start": "node dist/compiler/index.js",
|
|
38
|
+
"dev": "ts-node -r tsconfig-paths/register src/compiler/index.ts",
|
|
39
|
+
"now": "scripts/run.sh",
|
|
40
|
+
"setup": "npm run build && npm link",
|
|
41
|
+
"test": "ts-node -r tsconfig-paths/register scripts/test.ts all",
|
|
42
|
+
"test:update": "ts-node -r tsconfig-paths/register scripts/test.ts all --update",
|
|
43
|
+
"test:lexer": "ts-node scripts/test.ts lexer",
|
|
44
|
+
"test:parser": "ts-node scripts/test.ts parser",
|
|
45
|
+
"test:checker": "ts-node scripts/test.ts checker",
|
|
46
|
+
"test:compiler": "ts-node scripts/test.ts compiler",
|
|
47
|
+
"test:runtime": "ts-node scripts/test.ts runtime",
|
|
48
|
+
"test:errors": "ts-node scripts/test.ts errors"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/node": "^26.1.0",
|
|
52
|
+
"ts-node": "^10.9.2",
|
|
53
|
+
"tsc-alias": "^1.9.0",
|
|
54
|
+
"tsconfig-paths": "^4.2.0",
|
|
55
|
+
"typescript": "^6.0.3",
|
|
56
|
+
"typescript-language-server": "^5.3.0"
|
|
57
|
+
}
|
|
58
|
+
}
|