@devalade/algolang 1.0.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.
Files changed (3) hide show
  1. package/dist/cli.js +4553 -0
  2. package/dist/index.js +3275 -0
  3. package/package.json +47 -0
package/dist/index.js ADDED
@@ -0,0 +1,3275 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+
4
+ // src/lexer/lexer.ts
5
+ class Lexer {
6
+ source;
7
+ position = 0;
8
+ line = 1;
9
+ column = 1;
10
+ keywords;
11
+ constructor(source) {
12
+ this.source = source;
13
+ this.keywords = new Map([
14
+ ["PROGRAMME", "PROGRAMME" /* PROGRAM */],
15
+ ["DEBUT", "DEBUT" /* BEGIN */],
16
+ ["FIN", "FIN" /* END */],
17
+ ["VAR", "VAR" /* VAR */],
18
+ ["ENTIER", "ENTIER" /* INTEGER */],
19
+ ["REEL", "REEL" /* REAL */],
20
+ ["BOOLEEN", "BOOLEEN" /* BOOLEAN */],
21
+ ["CHAINE", "CHAINE" /* STRING */],
22
+ ["SI", "SI" /* IF */],
23
+ ["ALORS", "ALORS" /* THEN */],
24
+ ["SINON", "SINON" /* ELSE */],
25
+ ["FINSI", "FINIF" /* ENDIF */],
26
+ ["TANTQUE", "TANTQUE" /* WHILE */],
27
+ ["FAIRE", "FAIRE" /* DO */],
28
+ ["POUR", "POUR" /* FOR */],
29
+ ["ALLANT", "ALLANT" /* ALLANT */],
30
+ ["DE", "DE" /* DE */],
31
+ ["A", "A" /* TO */],
32
+ ["REPETER", "REPETER" /* REPEAT */],
33
+ ["JUSQUA", "JUSQUA" /* UNTIL */],
34
+ ["LIRE", "LIRE" /* READ */],
35
+ ["ECRIRE", "ECRIRE" /* WRITE */],
36
+ ["VRAI", "VRAI" /* TRUE */],
37
+ ["FAUX", "FAUX" /* FALSE */],
38
+ ["ET", "ET" /* AND */],
39
+ ["OU", "OU" /* OR */],
40
+ ["NON", "NON" /* NOT */],
41
+ ["FINPOUR", "FINPOUR" /* ENDFOR */],
42
+ ["FINTANTQUE", "FINTANTQUE" /* ENDWHILE */]
43
+ ]);
44
+ }
45
+ tokenize() {
46
+ const tokens = [];
47
+ while (!this.isAtEnd()) {
48
+ const token = this.scanToken();
49
+ if (token.type !== "COMMENT" /* COMMENT */) {
50
+ tokens.push(token);
51
+ }
52
+ }
53
+ tokens.push({
54
+ type: "EOF" /* EOF */,
55
+ value: "",
56
+ line: this.line,
57
+ column: this.column,
58
+ position: this.position
59
+ });
60
+ return tokens;
61
+ }
62
+ scanToken() {
63
+ this.skipWhitespace();
64
+ if (this.isAtEnd()) {
65
+ return this.createToken("EOF" /* EOF */, "");
66
+ }
67
+ const char = this.currentChar();
68
+ if (char === "/" && this.peek() === "/") {
69
+ return this.scanLineComment();
70
+ }
71
+ if (char === "/" && this.peek() === "*") {
72
+ return this.scanBlockComment();
73
+ }
74
+ if (char === '"') {
75
+ return this.scanString();
76
+ }
77
+ if (this.isDigit(char)) {
78
+ return this.scanNumber();
79
+ }
80
+ if (this.isAlpha(char)) {
81
+ return this.scanIdentifier();
82
+ }
83
+ if (char === ":" && this.peek() === "=") {
84
+ const token = this.createToken("ASSIGN" /* ASSIGN */, ":=");
85
+ this.advance();
86
+ this.advance();
87
+ return token;
88
+ }
89
+ if (char === "<" && this.peek() === "=") {
90
+ const token = this.createToken("LESS_EQUAL" /* LESS_EQUAL */, "<=");
91
+ this.advance();
92
+ this.advance();
93
+ return token;
94
+ }
95
+ if (char === ">" && this.peek() === "=") {
96
+ const token = this.createToken("GREATER_EQUAL" /* GREATER_EQUAL */, ">=");
97
+ this.advance();
98
+ this.advance();
99
+ return token;
100
+ }
101
+ if (char === "<" && this.peek() === ">") {
102
+ const token = this.createToken("NOT_EQUAL" /* NOT_EQUAL */, "<>");
103
+ this.advance();
104
+ this.advance();
105
+ return token;
106
+ }
107
+ switch (char) {
108
+ case "+":
109
+ return this.createToken("PLUS" /* PLUS */, this.advance());
110
+ case "-":
111
+ return this.createToken("MINUS" /* MINUS */, this.advance());
112
+ case "*":
113
+ return this.createToken("MULTIPLY" /* MULTIPLY */, this.advance());
114
+ case "/":
115
+ return this.createToken("DIVIDE" /* DIVIDE */, this.advance());
116
+ case "=":
117
+ return this.createToken("EQUAL" /* EQUAL */, this.advance());
118
+ case "<":
119
+ return this.createToken("LESS_THAN" /* LESS_THAN */, this.advance());
120
+ case ">":
121
+ return this.createToken("GREATER_THAN" /* GREATER_THAN */, this.advance());
122
+ case ";":
123
+ return this.createToken("SEMICOLON" /* SEMICOLON */, this.advance());
124
+ case ":":
125
+ return this.createToken("COLON" /* COLON */, this.advance());
126
+ case ",":
127
+ return this.createToken("COMMA" /* COMMA */, this.advance());
128
+ case ".":
129
+ return this.createToken("DOT" /* DOT */, this.advance());
130
+ case "(":
131
+ return this.createToken("LEFT_PAREN" /* LEFT_PAREN */, this.advance());
132
+ case ")":
133
+ return this.createToken("RIGHT_PAREN" /* RIGHT_PAREN */, this.advance());
134
+ default:
135
+ throw new Error(`Caractère non reconnu '${char}' à la ligne ${this.line}, colonne ${this.column}`);
136
+ }
137
+ }
138
+ scanIdentifier() {
139
+ const start = this.position;
140
+ const startColumn = this.column;
141
+ while (!this.isAtEnd() && this.isAlphaNumeric(this.currentChar())) {
142
+ this.advance();
143
+ }
144
+ const value = this.source.substring(start, this.position);
145
+ const type = this.keywords.get(value.toUpperCase()) || "IDENTIFIER" /* IDENTIFIER */;
146
+ return {
147
+ type,
148
+ value,
149
+ line: this.line,
150
+ column: startColumn,
151
+ position: start
152
+ };
153
+ }
154
+ scanNumber() {
155
+ const start = this.position;
156
+ const startColumn = this.column;
157
+ let hasDecimal = false;
158
+ while (!this.isAtEnd() && (this.isDigit(this.currentChar()) || this.currentChar() === ".")) {
159
+ if (this.currentChar() === ".") {
160
+ if (hasDecimal) {
161
+ throw new Error(`Nombre invalide: trop de points décimaux à la ligne ${this.line}, colonne ${this.column}`);
162
+ }
163
+ hasDecimal = true;
164
+ }
165
+ this.advance();
166
+ }
167
+ const value = this.source.substring(start, this.position);
168
+ return {
169
+ type: "NUMBER" /* NUMBER */,
170
+ value,
171
+ line: this.line,
172
+ column: startColumn,
173
+ position: start
174
+ };
175
+ }
176
+ scanString() {
177
+ const start = this.position;
178
+ const startColumn = this.column;
179
+ this.advance();
180
+ let value = "";
181
+ while (!this.isAtEnd() && this.currentChar() !== '"') {
182
+ if (this.currentChar() === "\\") {
183
+ this.advance();
184
+ if (this.isAtEnd()) {
185
+ throw new Error(`Chaîne de caractères non terminée à la ligne ${this.line}, colonne ${this.column}`);
186
+ }
187
+ const escaped = this.currentChar();
188
+ switch (escaped) {
189
+ case "n":
190
+ value += `
191
+ `;
192
+ break;
193
+ case "t":
194
+ value += "\t";
195
+ break;
196
+ case "r":
197
+ value += "\r";
198
+ break;
199
+ case "\\":
200
+ value += "\\";
201
+ break;
202
+ case '"':
203
+ value += '"';
204
+ break;
205
+ default:
206
+ value += escaped;
207
+ break;
208
+ }
209
+ this.advance();
210
+ } else {
211
+ value += this.currentChar();
212
+ this.advance();
213
+ }
214
+ }
215
+ if (this.isAtEnd()) {
216
+ throw new Error(`Chaîne de caractères non terminée à la ligne ${this.line}, colonne ${this.column}`);
217
+ }
218
+ this.advance();
219
+ return {
220
+ type: "STRING_LITERAL" /* STRING_LITERAL */,
221
+ value,
222
+ line: this.line,
223
+ column: startColumn,
224
+ position: start
225
+ };
226
+ }
227
+ scanLineComment() {
228
+ const start = this.position;
229
+ const startColumn = this.column;
230
+ while (!this.isAtEnd() && this.currentChar() !== `
231
+ `) {
232
+ this.advance();
233
+ }
234
+ const value = this.source.substring(start, this.position);
235
+ return {
236
+ type: "COMMENT" /* COMMENT */,
237
+ value,
238
+ line: this.line,
239
+ column: startColumn,
240
+ position: start
241
+ };
242
+ }
243
+ scanBlockComment() {
244
+ const start = this.position;
245
+ const startColumn = this.column;
246
+ this.advance();
247
+ while (!this.isAtEnd() && !(this.currentChar() === "*" && this.peek() === "/")) {
248
+ if (this.currentChar() === `
249
+ `) {
250
+ this.line++;
251
+ this.column = 1;
252
+ } else {
253
+ this.column++;
254
+ }
255
+ this.advance();
256
+ }
257
+ if (this.isAtEnd()) {
258
+ throw new Error(`Commentaire bloc non terminé commençant à la ligne ${this.line}, colonne ${this.column}`);
259
+ }
260
+ this.advance();
261
+ this.advance();
262
+ const value = this.source.substring(start, this.position);
263
+ return {
264
+ type: "COMMENT" /* COMMENT */,
265
+ value,
266
+ line: this.line,
267
+ column: startColumn,
268
+ position: start
269
+ };
270
+ }
271
+ skipWhitespace() {
272
+ while (!this.isAtEnd() && this.isWhitespace(this.currentChar())) {
273
+ if (this.currentChar() === `
274
+ `) {
275
+ this.line++;
276
+ this.column = 1;
277
+ } else {
278
+ this.column++;
279
+ }
280
+ this.advance();
281
+ }
282
+ }
283
+ createToken(type, value) {
284
+ return {
285
+ type,
286
+ value,
287
+ line: this.line,
288
+ column: this.column,
289
+ position: this.position
290
+ };
291
+ }
292
+ advance() {
293
+ const char = this.source[this.position];
294
+ this.position++;
295
+ return char !== undefined ? char : "\x00";
296
+ }
297
+ currentChar() {
298
+ const char = this.source[this.position];
299
+ return char !== undefined ? char : "\x00";
300
+ }
301
+ peek() {
302
+ if (this.position + 1 >= this.source.length) {
303
+ return "\x00";
304
+ }
305
+ const char = this.source[this.position + 1];
306
+ return char !== undefined ? char : "\x00";
307
+ }
308
+ isAtEnd() {
309
+ return this.position >= this.source.length;
310
+ }
311
+ isDigit(char) {
312
+ return char >= "0" && char <= "9";
313
+ }
314
+ isAlpha(char) {
315
+ return char >= "a" && char <= "z" || char >= "A" && char <= "Z" || char >= "À" && char <= "ÿ" || char === "_" || char === "'";
316
+ }
317
+ isAlphaNumeric(char) {
318
+ return this.isAlpha(char) || this.isDigit(char);
319
+ }
320
+ isWhitespace(char) {
321
+ return char === " " || char === "\t" || char === `
322
+ ` || char === "\r";
323
+ }
324
+ }
325
+ // src/parser/parser.ts
326
+ class Parser {
327
+ tokens;
328
+ current = 0;
329
+ errors = [];
330
+ symbolTable;
331
+ reservedKeywords = new Set([
332
+ "programme",
333
+ "debut",
334
+ "fin",
335
+ "var",
336
+ "entier",
337
+ "reel",
338
+ "booleen",
339
+ "chaine",
340
+ "si",
341
+ "alors",
342
+ "sinon",
343
+ "finsi",
344
+ "tantque",
345
+ "faire",
346
+ "fintantque",
347
+ "pour",
348
+ "a",
349
+ "finpour",
350
+ "repeter",
351
+ "jusqua",
352
+ "lire",
353
+ "ecrire",
354
+ "vrai",
355
+ "faux",
356
+ "et",
357
+ "ou",
358
+ "non",
359
+ "fonction",
360
+ "procedure",
361
+ "retourner"
362
+ ]);
363
+ constructor(tokens) {
364
+ this.tokens = tokens;
365
+ this.symbolTable = {
366
+ symbols: new Map,
367
+ children: [],
368
+ scopeName: "global"
369
+ };
370
+ }
371
+ isReservedKeyword(identifier) {
372
+ return this.reservedKeywords.has(identifier.toLowerCase());
373
+ }
374
+ isKeywordToken(tokenType) {
375
+ return [
376
+ "PROGRAMME" /* PROGRAM */,
377
+ "DEBUT" /* BEGIN */,
378
+ "FIN" /* END */,
379
+ "VAR" /* VAR */,
380
+ "ENTIER" /* INTEGER */,
381
+ "REEL" /* REAL */,
382
+ "BOOLEEN" /* BOOLEAN */,
383
+ "CHAINE" /* STRING */,
384
+ "SI" /* IF */,
385
+ "ALORS" /* THEN */,
386
+ "SINON" /* ELSE */,
387
+ "TANTQUE" /* WHILE */,
388
+ "FAIRE" /* DO */,
389
+ "POUR" /* FOR */,
390
+ "ALLANT" /* ALLANT */,
391
+ "DE" /* DE */,
392
+ "A" /* TO */,
393
+ "REPETER" /* REPEAT */,
394
+ "JUSQUA" /* UNTIL */,
395
+ "LIRE" /* READ */,
396
+ "ECRIRE" /* WRITE */,
397
+ "VRAI" /* TRUE */,
398
+ "FAUX" /* FALSE */,
399
+ "ET" /* AND */,
400
+ "OU" /* OR */,
401
+ "NON" /* NOT */,
402
+ "FINPOUR" /* ENDFOR */,
403
+ "FINIF" /* ENDIF */,
404
+ "FINTANTQUE" /* ENDWHILE */
405
+ ].includes(tokenType);
406
+ }
407
+ createReservedKeywordError(identifier, token) {
408
+ this.errors.push({
409
+ type: "ERROR",
410
+ message: `Le nom '${identifier}' est un mot-clé réservé et ne peut pas être utilisé comme nom de variable`,
411
+ line: token.line,
412
+ column: token.column,
413
+ position: token.position,
414
+ code: "RESERVED_KEYWORD",
415
+ explanation: "Les mots-clés réservés sont utilisés par le langage AlgoLang pour définir la structure du programme et ne peuvent pas être utilisés comme noms de variables.",
416
+ suggestion: `Choisissez un autre nom plus descriptif, par exemple: '${identifier}Valeur', '${identifier}Temp', 'ma${identifier.charAt(0).toUpperCase() + identifier.slice(1)}'`
417
+ });
418
+ }
419
+ parse() {
420
+ try {
421
+ const program = this.parseProgram();
422
+ return {
423
+ ast: program,
424
+ errors: this.errors,
425
+ symbolTable: this.symbolTable
426
+ };
427
+ } catch (error) {
428
+ return {
429
+ ast: { type: "PROGRAM" /* PROGRAM */, children: [] },
430
+ errors: [
431
+ ...this.errors,
432
+ {
433
+ type: "ERROR",
434
+ message: error instanceof Error ? error.message : "Erreur de parsing inconnue",
435
+ line: 1,
436
+ column: 1,
437
+ position: 0,
438
+ code: "PARSE_ERROR"
439
+ }
440
+ ],
441
+ symbolTable: this.symbolTable
442
+ };
443
+ }
444
+ }
445
+ parseProgram() {
446
+ const programToken = this.expect("PROGRAMME" /* PROGRAM */, 'Le programme doit commencer par le mot-clé "programme"');
447
+ const identifier = this.expect("IDENTIFIER" /* IDENTIFIER */, "Le programme doit avoir un nom");
448
+ this.expect("SEMICOLON" /* SEMICOLON */, "Le nom du programme doit être suivi d'un point-virgule");
449
+ const block = this.parseBlock();
450
+ return {
451
+ type: "PROGRAM" /* PROGRAM */,
452
+ value: identifier.value,
453
+ children: [block],
454
+ token: programToken
455
+ };
456
+ }
457
+ parseBlock() {
458
+ const declarations = this.parseDeclarations();
459
+ const compoundStatement = this.parseCompoundStatement();
460
+ return {
461
+ type: "BLOCK" /* BLOCK */,
462
+ children: [declarations, compoundStatement]
463
+ };
464
+ }
465
+ parseDeclarations() {
466
+ const declarations = [];
467
+ while (this.check("VAR" /* VAR */)) {
468
+ this.advance();
469
+ while (!this.check("DEBUT" /* BEGIN */) && !this.isAtEnd()) {
470
+ const declaration = this.parseVariableDeclaration();
471
+ declarations.push(declaration);
472
+ if (!this.check("SEMICOLON" /* SEMICOLON */)) {
473
+ break;
474
+ }
475
+ this.advance();
476
+ }
477
+ }
478
+ return {
479
+ type: "BLOCK" /* BLOCK */,
480
+ children: declarations
481
+ };
482
+ }
483
+ parseVariableDeclaration() {
484
+ const identifiers = [];
485
+ do {
486
+ let identifier;
487
+ if (this.check("IDENTIFIER" /* IDENTIFIER */)) {
488
+ identifier = this.advance();
489
+ } else {
490
+ const currentToken = this.peek();
491
+ if (this.isKeywordToken(currentToken.type)) {
492
+ identifier = this.advance();
493
+ this.createReservedKeywordError(identifier.value, identifier);
494
+ } else {
495
+ this.expect("IDENTIFIER" /* IDENTIFIER */, "Identificateur attendu dans la déclaration de variable");
496
+ break;
497
+ }
498
+ }
499
+ if (this.isReservedKeyword(identifier.value)) {
500
+ this.createReservedKeywordError(identifier.value, identifier);
501
+ }
502
+ identifiers.push(identifier.value);
503
+ if (this.check("COMMA" /* COMMA */)) {
504
+ this.advance();
505
+ } else {
506
+ break;
507
+ }
508
+ } while (true);
509
+ this.expect("COLON" /* COLON */, "Deux-points attendus après les identificateurs");
510
+ const typeToken = this.expect(["ENTIER" /* INTEGER */, "REEL" /* REAL */, "BOOLEEN" /* BOOLEAN */, "CHAINE" /* STRING */], "Type de variable attendu");
511
+ const type = this.tokenTypeToDataType(typeToken.type);
512
+ for (const identifier of identifiers) {
513
+ if (this.symbolTable.symbols.has(identifier)) {
514
+ this.errors.push({
515
+ type: "ERROR",
516
+ message: `La variable '${identifier}' est déjà déclarée`,
517
+ line: typeToken.line,
518
+ column: typeToken.column,
519
+ position: typeToken.position,
520
+ code: "DUPLICATE_VARIABLE",
521
+ explanation: "Chaque variable doit avoir un nom unique dans son scope",
522
+ suggestion: `Choisissez un autre nom pour la variable '${identifier}'`
523
+ });
524
+ } else {
525
+ const symbolInfo = {
526
+ name: identifier,
527
+ type,
528
+ scope: this.symbolTable.scopeName,
529
+ line: typeToken.line,
530
+ column: typeToken.column
531
+ };
532
+ this.symbolTable.symbols.set(identifier, symbolInfo);
533
+ }
534
+ }
535
+ return {
536
+ type: "VAR_DECLARATION" /* VAR_DECLARATION */,
537
+ value: type,
538
+ children: identifiers.map((name) => ({
539
+ type: "VARIABLE" /* VARIABLE */,
540
+ value: name
541
+ })),
542
+ token: typeToken
543
+ };
544
+ }
545
+ parseCompoundStatement() {
546
+ this.expect("DEBUT" /* BEGIN */, `Le bloc d'instructions doit commencer par "debut"`);
547
+ const statements = [];
548
+ while (!this.check("FIN" /* END */) && !this.isAtEnd()) {
549
+ const statement = this.parseStatement();
550
+ statements.push(statement);
551
+ if (this.check("SEMICOLON" /* SEMICOLON */)) {
552
+ this.advance();
553
+ } else if (!this.check("FIN" /* END */) && !this.check("FINIF" /* ENDIF */) && !this.check("FINTANTQUE" /* ENDWHILE */)) {
554
+ this.errors.push({
555
+ type: "ERROR",
556
+ message: "Point-virgule attendu après l'instruction",
557
+ line: this.peek().line,
558
+ column: this.peek().column,
559
+ position: this.peek().position,
560
+ code: "MISSING_SEMICOLON"
561
+ });
562
+ break;
563
+ }
564
+ }
565
+ this.expect("FIN" /* END */, `Le bloc d'instructions doit se terminer par "fin"`);
566
+ return {
567
+ type: "COMPOUND_STATEMENT" /* COMPOUND_STATEMENT */,
568
+ children: statements
569
+ };
570
+ }
571
+ parseStatement() {
572
+ if (this.check("DEBUT" /* BEGIN */)) {
573
+ return this.parseCompoundStatement();
574
+ }
575
+ if (this.isKeywordToken(this.peek().type) && this.peekAhead(1)?.type === "ASSIGN" /* ASSIGN */) {
576
+ return this.parseAssignment();
577
+ }
578
+ if (this.check("SI" /* IF */)) {
579
+ return this.parseIfStatement();
580
+ }
581
+ if (this.check("TANTQUE" /* WHILE */)) {
582
+ return this.parseWhileStatement();
583
+ }
584
+ if (this.check("POUR" /* FOR */)) {
585
+ return this.parseForStatement();
586
+ }
587
+ if (this.check("REPETER" /* REPEAT */)) {
588
+ return this.parseRepeatStatement();
589
+ }
590
+ if (this.check("LIRE" /* READ */)) {
591
+ return this.parseReadStatement();
592
+ }
593
+ if (this.check("ECRIRE" /* WRITE */)) {
594
+ return this.parseWriteStatement();
595
+ }
596
+ return this.parseAssignment();
597
+ }
598
+ parseIfStatement(isElseIf = false) {
599
+ const ifToken = this.advance();
600
+ const condition = this.parseExpression();
601
+ this.expect("ALORS" /* THEN */, '"alors" attendu après la condition du si');
602
+ const thenStatements = [];
603
+ while (!this.check("SINON" /* ELSE */) && !this.check("FINIF" /* ENDIF */) && !this.check("FIN" /* END */) && !this.isAtEnd()) {
604
+ const statement = this.parseStatement();
605
+ thenStatements.push(statement);
606
+ if (this.check("SEMICOLON" /* SEMICOLON */)) {
607
+ this.advance();
608
+ }
609
+ }
610
+ const thenStatement = {
611
+ type: "COMPOUND_STATEMENT" /* COMPOUND_STATEMENT */,
612
+ children: thenStatements
613
+ };
614
+ let elseStatement;
615
+ if (this.check("SEMICOLON" /* SEMICOLON */) && this.peekAhead(1)?.type === "SINON" /* ELSE */) {
616
+ this.advance();
617
+ }
618
+ if (this.check("SINON" /* ELSE */)) {
619
+ this.advance();
620
+ if (this.check("SI" /* IF */)) {
621
+ elseStatement = this.parseIfStatement(true);
622
+ } else {
623
+ const elseStatements = [];
624
+ while (!this.check("FINIF" /* ENDIF */) && !this.check("FIN" /* END */) && !this.isAtEnd()) {
625
+ const statement = this.parseStatement();
626
+ elseStatements.push(statement);
627
+ if (this.check("SEMICOLON" /* SEMICOLON */)) {
628
+ this.advance();
629
+ }
630
+ }
631
+ elseStatement = {
632
+ type: "COMPOUND_STATEMENT" /* COMPOUND_STATEMENT */,
633
+ children: elseStatements
634
+ };
635
+ }
636
+ }
637
+ if (!isElseIf) {
638
+ if (this.check("SEMICOLON" /* SEMICOLON */) && this.peekAhead(1)?.type === "FINIF" /* ENDIF */) {
639
+ this.advance();
640
+ }
641
+ this.expect("FINIF" /* ENDIF */, '"finsi" attendu à la fin du bloc si');
642
+ }
643
+ return {
644
+ type: "IF_STATEMENT" /* IF_STATEMENT */,
645
+ children: [
646
+ condition,
647
+ thenStatement,
648
+ ...elseStatement ? [elseStatement] : []
649
+ ],
650
+ token: ifToken
651
+ };
652
+ }
653
+ parseWhileStatement() {
654
+ const whileToken = this.advance();
655
+ const condition = this.parseExpression();
656
+ this.expect("FAIRE" /* DO */, '"faire" attendu après la condition du tantque');
657
+ const bodyStatements = [];
658
+ while (!this.check("FINTANTQUE" /* ENDWHILE */) && !this.check("FIN" /* END */) && !this.isAtEnd()) {
659
+ const statement = this.parseStatement();
660
+ bodyStatements.push(statement);
661
+ if (this.check("SEMICOLON" /* SEMICOLON */)) {
662
+ this.advance();
663
+ }
664
+ }
665
+ this.expect("FINTANTQUE" /* ENDWHILE */, '"fintantque" attendu à la fin de la boucle tantque');
666
+ return {
667
+ type: "WHILE_STATEMENT" /* WHILE_STATEMENT */,
668
+ children: [
669
+ condition,
670
+ { type: "COMPOUND_STATEMENT" /* COMPOUND_STATEMENT */, children: bodyStatements }
671
+ ],
672
+ token: whileToken
673
+ };
674
+ }
675
+ parseForStatement() {
676
+ const forToken = this.advance();
677
+ const variable = this.expect("IDENTIFIER" /* IDENTIFIER */, 'Identificateur attendu après "pour"');
678
+ let startValue;
679
+ if (this.check("ALLANT" /* ALLANT */)) {
680
+ this.advance();
681
+ this.expect("DE" /* DE */, '"de" attendu après "allant" dans la boucle pour');
682
+ startValue = this.parseExpression();
683
+ } else if (this.check("ASSIGN" /* ASSIGN */)) {
684
+ this.advance();
685
+ startValue = this.parseExpression();
686
+ } else {
687
+ throw new Error('"allant de" ou ":=" attendu après la variable dans la boucle pour');
688
+ }
689
+ this.expect("A" /* TO */, '"a" attendu dans la boucle pour');
690
+ const endValue = this.parseExpression();
691
+ this.expect("FAIRE" /* DO */, '"faire" attendu dans la boucle pour');
692
+ const bodyStatements = [];
693
+ while (!this.check("FINPOUR" /* ENDFOR */) && !this.check("FIN" /* END */) && !this.isAtEnd()) {
694
+ const statement = this.parseStatement();
695
+ bodyStatements.push(statement);
696
+ if (this.check("SEMICOLON" /* SEMICOLON */)) {
697
+ this.advance();
698
+ }
699
+ }
700
+ this.expect("FINPOUR" /* ENDFOR */, '"finpour" attendu à la fin de la boucle pour');
701
+ return {
702
+ type: "FOR_STATEMENT" /* FOR_STATEMENT */,
703
+ children: [
704
+ { type: "VARIABLE" /* VARIABLE */, value: variable.value, token: variable },
705
+ startValue,
706
+ endValue,
707
+ { type: "COMPOUND_STATEMENT" /* COMPOUND_STATEMENT */, children: bodyStatements }
708
+ ],
709
+ token: forToken
710
+ };
711
+ }
712
+ parseReadStatement() {
713
+ const readToken = this.advance();
714
+ this.expect("LEFT_PAREN" /* LEFT_PAREN */, 'Parenthèse ouvrante attendue après "lire"');
715
+ let variable;
716
+ if (this.check("IDENTIFIER" /* IDENTIFIER */)) {
717
+ variable = this.advance();
718
+ } else {
719
+ const currentToken = this.peek();
720
+ if (this.isKeywordToken(currentToken.type)) {
721
+ variable = this.advance();
722
+ this.createReservedKeywordError(variable.value, variable);
723
+ } else {
724
+ this.expect("IDENTIFIER" /* IDENTIFIER */, 'Variable attendue dans "lire"');
725
+ throw new Error('Variable attendue dans "lire"');
726
+ }
727
+ }
728
+ this.expect("RIGHT_PAREN" /* RIGHT_PAREN */, 'Parenthèse fermante attendue dans "lire"');
729
+ return {
730
+ type: "READ_STATEMENT" /* READ_STATEMENT */,
731
+ children: [
732
+ { type: "VARIABLE" /* VARIABLE */, value: variable.value, token: variable }
733
+ ],
734
+ token: readToken
735
+ };
736
+ }
737
+ parseWriteStatement() {
738
+ const writeToken = this.advance();
739
+ this.expect("LEFT_PAREN" /* LEFT_PAREN */, 'Parenthèse ouvrante attendue après "ecrire"');
740
+ const expressions = [];
741
+ expressions.push(this.parseExpression());
742
+ while (this.check("COMMA" /* COMMA */)) {
743
+ this.advance();
744
+ expressions.push(this.parseExpression());
745
+ }
746
+ this.expect("RIGHT_PAREN" /* RIGHT_PAREN */, 'Parenthèse fermante attendue dans "ecrire"');
747
+ return {
748
+ type: "WRITE_STATEMENT" /* WRITE_STATEMENT */,
749
+ children: expressions,
750
+ token: writeToken
751
+ };
752
+ }
753
+ parseAssignment() {
754
+ let variable;
755
+ if (this.check("IDENTIFIER" /* IDENTIFIER */)) {
756
+ variable = this.advance();
757
+ } else {
758
+ const currentToken = this.peek();
759
+ if (this.isKeywordToken(currentToken.type)) {
760
+ variable = this.advance();
761
+ this.createReservedKeywordError(variable.value, variable);
762
+ } else {
763
+ this.expect("IDENTIFIER" /* IDENTIFIER */, "Variable attendue dans l'affectation");
764
+ throw new Error("Variable attendue dans l'affectation");
765
+ }
766
+ }
767
+ if (this.isReservedKeyword(variable.value)) {
768
+ this.createReservedKeywordError(variable.value, variable);
769
+ }
770
+ this.expect("ASSIGN" /* ASSIGN */, `":=" attendu dans l'affectation`);
771
+ const expression = this.parseExpression();
772
+ return {
773
+ type: "ASSIGNMENT" /* ASSIGNMENT */,
774
+ children: [
775
+ { type: "VARIABLE" /* VARIABLE */, value: variable.value, token: variable },
776
+ expression
777
+ ],
778
+ token: variable
779
+ };
780
+ }
781
+ parseExpression() {
782
+ return this.parseOrExpression();
783
+ }
784
+ parseOrExpression() {
785
+ let left = this.parseAndExpression();
786
+ while (this.check("OU" /* OR */)) {
787
+ const operator = this.advance();
788
+ const right = this.parseAndExpression();
789
+ left = {
790
+ type: "BINARY_OP" /* BINARY_OP */,
791
+ value: operator.value,
792
+ children: [left, right],
793
+ token: operator
794
+ };
795
+ }
796
+ return left;
797
+ }
798
+ parseAndExpression() {
799
+ let left = this.parseEqualityExpression();
800
+ while (this.check("ET" /* AND */)) {
801
+ const operator = this.advance();
802
+ const right = this.parseEqualityExpression();
803
+ left = {
804
+ type: "BINARY_OP" /* BINARY_OP */,
805
+ value: operator.value,
806
+ children: [left, right],
807
+ token: operator
808
+ };
809
+ }
810
+ return left;
811
+ }
812
+ parseEqualityExpression() {
813
+ let left = this.parseRelationalExpression();
814
+ while (this.check(["EQUAL" /* EQUAL */, "NOT_EQUAL" /* NOT_EQUAL */])) {
815
+ const operator = this.advance();
816
+ const right = this.parseRelationalExpression();
817
+ left = {
818
+ type: "BINARY_OP" /* BINARY_OP */,
819
+ value: operator.value,
820
+ children: [left, right],
821
+ token: operator
822
+ };
823
+ }
824
+ return left;
825
+ }
826
+ parseRelationalExpression() {
827
+ let left = this.parseAdditiveExpression();
828
+ while (this.check([
829
+ "LESS_THAN" /* LESS_THAN */,
830
+ "LESS_EQUAL" /* LESS_EQUAL */,
831
+ "GREATER_THAN" /* GREATER_THAN */,
832
+ "GREATER_EQUAL" /* GREATER_EQUAL */
833
+ ])) {
834
+ const operator = this.advance();
835
+ const right = this.parseAdditiveExpression();
836
+ left = {
837
+ type: "BINARY_OP" /* BINARY_OP */,
838
+ value: operator.value,
839
+ children: [left, right],
840
+ token: operator
841
+ };
842
+ }
843
+ return left;
844
+ }
845
+ parseAdditiveExpression() {
846
+ let left = this.parseMultiplicativeExpression();
847
+ while (this.check(["PLUS" /* PLUS */, "MINUS" /* MINUS */])) {
848
+ const operator = this.advance();
849
+ const right = this.parseMultiplicativeExpression();
850
+ left = {
851
+ type: "BINARY_OP" /* BINARY_OP */,
852
+ value: operator.value,
853
+ children: [left, right],
854
+ token: operator
855
+ };
856
+ }
857
+ return left;
858
+ }
859
+ parseMultiplicativeExpression() {
860
+ let left = this.parseUnaryExpression();
861
+ while (this.check(["MULTIPLY" /* MULTIPLY */, "DIVIDE" /* DIVIDE */])) {
862
+ const operator = this.advance();
863
+ const right = this.parseUnaryExpression();
864
+ left = {
865
+ type: "BINARY_OP" /* BINARY_OP */,
866
+ value: operator.value,
867
+ children: [left, right],
868
+ token: operator
869
+ };
870
+ }
871
+ return left;
872
+ }
873
+ parseUnaryExpression() {
874
+ if (this.check("NON" /* NOT */)) {
875
+ const nextToken = this.peekAhead();
876
+ if (nextToken && [
877
+ "RIGHT_PAREN" /* RIGHT_PAREN */,
878
+ "SEMICOLON" /* SEMICOLON */,
879
+ "COMMA" /* COMMA */,
880
+ "EOF" /* EOF */
881
+ ].includes(nextToken.type)) {
882
+ return this.parsePrimary();
883
+ }
884
+ }
885
+ if (this.check(["NON" /* NOT */, "MINUS" /* MINUS */])) {
886
+ const operator = this.advance();
887
+ const operand = this.parseUnaryExpression();
888
+ return {
889
+ type: "UNARY_OP" /* UNARY_OP */,
890
+ value: operator.value,
891
+ children: [operand],
892
+ token: operator
893
+ };
894
+ }
895
+ return this.parsePrimary();
896
+ }
897
+ parsePrimary() {
898
+ if (this.check("NUMBER" /* NUMBER */)) {
899
+ const token2 = this.advance();
900
+ return {
901
+ type: "LITERAL" /* LITERAL */,
902
+ value: parseFloat(token2.value),
903
+ token: token2
904
+ };
905
+ }
906
+ if (this.check(["VRAI" /* TRUE */, "FAUX" /* FALSE */])) {
907
+ const token2 = this.advance();
908
+ return {
909
+ type: "LITERAL" /* LITERAL */,
910
+ value: token2.value === "vrai",
911
+ token: token2
912
+ };
913
+ }
914
+ if (this.check("STRING_LITERAL" /* STRING_LITERAL */)) {
915
+ const token2 = this.advance();
916
+ return {
917
+ type: "LITERAL" /* LITERAL */,
918
+ value: token2.value,
919
+ token: token2
920
+ };
921
+ }
922
+ if (this.check("IDENTIFIER" /* IDENTIFIER */)) {
923
+ const token2 = this.advance();
924
+ if (this.isReservedKeyword(token2.value)) {
925
+ this.createReservedKeywordError(token2.value, token2);
926
+ }
927
+ return {
928
+ type: "VARIABLE" /* VARIABLE */,
929
+ value: token2.value,
930
+ token: token2
931
+ };
932
+ }
933
+ const currentToken = this.peek();
934
+ if (this.isKeywordToken(currentToken.type)) {
935
+ const token2 = this.advance();
936
+ this.createReservedKeywordError(token2.value, token2);
937
+ return {
938
+ type: "VARIABLE" /* VARIABLE */,
939
+ value: token2.value,
940
+ token: token2
941
+ };
942
+ }
943
+ if (this.check("LEFT_PAREN" /* LEFT_PAREN */)) {
944
+ this.advance();
945
+ const expression = this.parseExpression();
946
+ this.expect("RIGHT_PAREN" /* RIGHT_PAREN */, "Parenthèse fermante attendue");
947
+ return expression;
948
+ }
949
+ const token = this.peek();
950
+ this.errors.push({
951
+ type: "ERROR",
952
+ message: `Expression inattendue: ${token.value}`,
953
+ line: token.line,
954
+ column: token.column,
955
+ position: token.position,
956
+ code: "UNEXPECTED_TOKEN"
957
+ });
958
+ this.advance();
959
+ return {
960
+ type: "LITERAL" /* LITERAL */,
961
+ value: 0
962
+ };
963
+ }
964
+ parseRepeatStatement() {
965
+ const repeatToken = this.advance();
966
+ const statements = [];
967
+ while (!this.check("JUSQUA" /* UNTIL */) && !this.isAtEnd()) {
968
+ const statement = this.parseStatement();
969
+ statements.push(statement);
970
+ if (this.check("SEMICOLON" /* SEMICOLON */)) {
971
+ this.advance();
972
+ }
973
+ }
974
+ this.expect("JUSQUA" /* UNTIL */, '"jusqua" attendu à la fin de la boucle repeter');
975
+ const condition = this.parseExpression();
976
+ return {
977
+ type: "REPEAT_STATEMENT" /* REPEAT_STATEMENT */,
978
+ children: [...statements, condition],
979
+ token: repeatToken
980
+ };
981
+ }
982
+ check(type) {
983
+ if (this.isAtEnd())
984
+ return false;
985
+ if (Array.isArray(type)) {
986
+ return type.includes(this.peek().type);
987
+ }
988
+ return this.peek().type === type;
989
+ }
990
+ advance() {
991
+ if (!this.isAtEnd())
992
+ this.current++;
993
+ return this.previous();
994
+ }
995
+ isAtEnd() {
996
+ return this.peek().type === "EOF";
997
+ }
998
+ peek() {
999
+ return this.tokens[this.current] ?? {
1000
+ type: "EOF" /* EOF */,
1001
+ value: "",
1002
+ line: 0,
1003
+ column: 0,
1004
+ position: 0
1005
+ };
1006
+ }
1007
+ peekAhead(offset = 1) {
1008
+ return this.tokens[this.current + offset];
1009
+ }
1010
+ previous() {
1011
+ return this.tokens[this.current - 1] ?? {
1012
+ type: "EOF" /* EOF */,
1013
+ value: "",
1014
+ line: 0,
1015
+ column: 0,
1016
+ position: 0
1017
+ };
1018
+ }
1019
+ expect(type, message) {
1020
+ if (this.check(type)) {
1021
+ return this.advance();
1022
+ }
1023
+ const token = this.peek();
1024
+ this.errors.push({
1025
+ type: "ERROR",
1026
+ message,
1027
+ line: token.line,
1028
+ column: token.column,
1029
+ position: token.position,
1030
+ code: "EXPECTED_TOKEN",
1031
+ explanation: `Attendu: ${Array.isArray(type) ? type.join(" ou ") : type}, Trouvé: ${token.type}`,
1032
+ suggestion: "Vérifiez la syntaxe de votre programme"
1033
+ });
1034
+ throw new Error(message);
1035
+ }
1036
+ tokenTypeToDataType(tokenType) {
1037
+ switch (tokenType) {
1038
+ case "ENTIER" /* INTEGER */:
1039
+ return "ENTIER" /* INTEGER */;
1040
+ case "REEL" /* REAL */:
1041
+ return "REEL" /* REAL */;
1042
+ case "BOOLEEN" /* BOOLEAN */:
1043
+ return "BOOLEEN" /* BOOLEAN */;
1044
+ case "CHAINE" /* STRING */:
1045
+ return "CHAINE" /* STRING */;
1046
+ default:
1047
+ return "VIDE" /* VOID */;
1048
+ }
1049
+ }
1050
+ }
1051
+ // src/codegen/codegen.ts
1052
+ class CodeGenerator {
1053
+ symbolTable;
1054
+ errors = [];
1055
+ indentLevel = 0;
1056
+ constructor(symbolTable, _options) {
1057
+ this.symbolTable = symbolTable;
1058
+ }
1059
+ generate(ast) {
1060
+ try {
1061
+ const output = this.generateJavaScript(ast);
1062
+ return {
1063
+ success: this.errors.length === 0,
1064
+ output,
1065
+ errors: this.errors,
1066
+ warnings: [],
1067
+ symbolTable: this.symbolTable,
1068
+ ast
1069
+ };
1070
+ } catch (error) {
1071
+ return {
1072
+ success: false,
1073
+ output: "",
1074
+ errors: [
1075
+ ...this.errors,
1076
+ {
1077
+ type: "ERROR",
1078
+ message: error instanceof Error ? error.message : "Erreur inconnue lors de la génération de code",
1079
+ line: 0,
1080
+ column: 0,
1081
+ position: 0,
1082
+ code: "GENERATION_ERROR"
1083
+ }
1084
+ ],
1085
+ warnings: []
1086
+ };
1087
+ }
1088
+ }
1089
+ generateJavaScript(ast) {
1090
+ const lines = [];
1091
+ lines.push("// Code généré par AlgoLang");
1092
+ lines.push('import * as readline from "readline";');
1093
+ lines.push("");
1094
+ lines.push("const rl = readline.createInterface({");
1095
+ lines.push(" input: process.stdin,");
1096
+ lines.push(" output: process.stdout");
1097
+ lines.push("});");
1098
+ lines.push("");
1099
+ const programCode = this.generateNode(ast);
1100
+ lines.push(programCode);
1101
+ lines.push("");
1102
+ lines.push("// Fonctions utilitaires pour les entrées/sorties");
1103
+ lines.push("function lire(prompt) {");
1104
+ lines.push(" return new Promise((resolve) => {");
1105
+ lines.push(" rl.question(prompt, (answer) => {");
1106
+ lines.push(" resolve(answer.trim());");
1107
+ lines.push(" });");
1108
+ lines.push(" });");
1109
+ lines.push("}");
1110
+ lines.push("");
1111
+ lines.push("function ecrire(...args) {");
1112
+ lines.push(" console.log(...args);");
1113
+ lines.push("}");
1114
+ lines.push("");
1115
+ lines.push("// Point d'entrée principal");
1116
+ lines.push("main().then(() => {");
1117
+ lines.push(" rl.close();");
1118
+ lines.push("});");
1119
+ return lines.join(`
1120
+ `);
1121
+ }
1122
+ generateNode(node) {
1123
+ switch (node.type) {
1124
+ case "PROGRAM":
1125
+ return this.generateProgram(node);
1126
+ case "BLOCK":
1127
+ return this.generateBlock(node);
1128
+ case "VAR_DECLARATION":
1129
+ return this.generateVariableDeclaration(node);
1130
+ case "COMPOUND_STATEMENT":
1131
+ return this.generateCompoundStatement(node);
1132
+ case "ASSIGNMENT":
1133
+ return this.generateAssignment(node);
1134
+ case "IF_STATEMENT":
1135
+ return this.generateIfStatement(node);
1136
+ case "WHILE_STATEMENT":
1137
+ return this.generateWhileStatement(node);
1138
+ case "FOR_STATEMENT":
1139
+ return this.generateForStatement(node);
1140
+ case "REPEAT_STATEMENT":
1141
+ return this.generateRepeatStatement(node);
1142
+ case "READ_STATEMENT":
1143
+ return this.generateReadStatement(node);
1144
+ case "WRITE_STATEMENT":
1145
+ return this.generateWriteStatement(node);
1146
+ case "BINARY_OP":
1147
+ return this.generateBinaryOp(node);
1148
+ case "UNARY_OP":
1149
+ return this.generateUnaryOp(node);
1150
+ case "LITERAL":
1151
+ return this.generateLiteral(node);
1152
+ case "VARIABLE":
1153
+ return this.generateVariable(node);
1154
+ default:
1155
+ this.errors.push({
1156
+ type: "ERROR",
1157
+ message: `Type de nœud non supporté: ${node.type}`,
1158
+ line: 0,
1159
+ column: 0,
1160
+ position: 0,
1161
+ code: "UNSUPPORTED_NODE_TYPE"
1162
+ });
1163
+ return "";
1164
+ }
1165
+ }
1166
+ generateProgram(node) {
1167
+ const lines = [];
1168
+ lines.push(`// Programme: ${node.value}`);
1169
+ lines.push("async function main() {");
1170
+ this.indentLevel++;
1171
+ if (node.children && node.children.length > 0) {
1172
+ for (const child of node.children) {
1173
+ const childCode = this.generateNode(child);
1174
+ if (childCode) {
1175
+ lines.push(this.indent(childCode));
1176
+ }
1177
+ }
1178
+ }
1179
+ this.indentLevel--;
1180
+ lines.push("}");
1181
+ return lines.join(`
1182
+ `);
1183
+ }
1184
+ generateBlock(node) {
1185
+ const lines = [];
1186
+ if (node.children) {
1187
+ for (const child of node.children) {
1188
+ const childCode = this.generateNode(child);
1189
+ if (childCode) {
1190
+ lines.push(this.indent(childCode));
1191
+ }
1192
+ }
1193
+ }
1194
+ return lines.join(`
1195
+ `);
1196
+ }
1197
+ generateVariableDeclaration(node) {
1198
+ const lines = [];
1199
+ const varType = this.mapAlgoLangTypeToJS(node.value);
1200
+ if (node.children) {
1201
+ const variableNames = node.children.map((child) => child.value).join(", ");
1202
+ lines.push(`let ${variableNames}; // ${varType}`);
1203
+ }
1204
+ return lines.join(`
1205
+ `);
1206
+ }
1207
+ generateCompoundStatement(node) {
1208
+ const lines = [];
1209
+ if (node.children) {
1210
+ for (const child of node.children) {
1211
+ const childCode = this.generateNode(child);
1212
+ if (childCode) {
1213
+ lines.push(this.indent(childCode));
1214
+ }
1215
+ }
1216
+ }
1217
+ return lines.join(`
1218
+ `);
1219
+ }
1220
+ generateAssignment(node) {
1221
+ if (!node.children || node.children.length < 2) {
1222
+ return "";
1223
+ }
1224
+ const variable = node.children[0];
1225
+ const expression = node.children[1];
1226
+ if (!variable || !expression) {
1227
+ return "";
1228
+ }
1229
+ const variableName = variable.value;
1230
+ const expressionCode = this.generateNode(expression);
1231
+ return `${variableName} = ${expressionCode};`;
1232
+ }
1233
+ generateIfStatement(node) {
1234
+ if (!node.children || node.children.length < 2) {
1235
+ return "";
1236
+ }
1237
+ const condition = node.children[0];
1238
+ const thenStatement = node.children[1];
1239
+ const elseStatement = node.children[2];
1240
+ if (!condition || !thenStatement) {
1241
+ return "";
1242
+ }
1243
+ const conditionCode = this.generateNode(condition);
1244
+ const thenCode = this.generateNode(thenStatement);
1245
+ let code = `if (${conditionCode}) {
1246
+ `;
1247
+ this.indentLevel++;
1248
+ code += this.indent(thenCode) + `
1249
+ `;
1250
+ this.indentLevel--;
1251
+ code += "}";
1252
+ if (elseStatement) {
1253
+ const elseCode = this.generateNode(elseStatement);
1254
+ code += ` else {
1255
+ `;
1256
+ this.indentLevel++;
1257
+ code += this.indent(elseCode) + `
1258
+ `;
1259
+ this.indentLevel--;
1260
+ code += "}";
1261
+ }
1262
+ return code;
1263
+ }
1264
+ generateWhileStatement(node) {
1265
+ if (!node.children || node.children.length < 2) {
1266
+ return "";
1267
+ }
1268
+ const condition = node.children[0];
1269
+ const body = node.children[1];
1270
+ if (!condition || !body) {
1271
+ return "";
1272
+ }
1273
+ const conditionCode = this.generateNode(condition);
1274
+ const bodyCode = this.generateNode(body);
1275
+ let code = `while (${conditionCode}) {
1276
+ `;
1277
+ this.indentLevel++;
1278
+ code += this.indent(bodyCode) + `
1279
+ `;
1280
+ this.indentLevel--;
1281
+ code += "}";
1282
+ return code;
1283
+ }
1284
+ generateForStatement(node) {
1285
+ if (!node.children || node.children.length < 4) {
1286
+ return "";
1287
+ }
1288
+ const variable = node.children[0];
1289
+ const startValue = node.children[1];
1290
+ const endValue = node.children[2];
1291
+ const body = node.children[3];
1292
+ if (!variable || !startValue || !endValue || !body) {
1293
+ return "";
1294
+ }
1295
+ const variableName = variable.value;
1296
+ const startCode = this.generateNode(startValue);
1297
+ const endCode = this.generateNode(endValue);
1298
+ const bodyCode = this.generateNode(body);
1299
+ let code = `for (let ${variableName} = ${startCode}; ${variableName} <= ${endCode}; ${variableName}++) {
1300
+ `;
1301
+ this.indentLevel++;
1302
+ code += this.indent(bodyCode) + `
1303
+ `;
1304
+ this.indentLevel--;
1305
+ code += "}";
1306
+ return code;
1307
+ }
1308
+ generateRepeatStatement(node) {
1309
+ if (!node.children || node.children.length < 2) {
1310
+ return "";
1311
+ }
1312
+ const conditionIndex = node.children.length - 1;
1313
+ const condition = node.children[conditionIndex];
1314
+ const bodyStatements = node.children.slice(0, conditionIndex);
1315
+ if (!condition || bodyStatements.length === 0) {
1316
+ return "";
1317
+ }
1318
+ const conditionCode = this.generateNode(condition);
1319
+ let code = `do {
1320
+ `;
1321
+ this.indentLevel++;
1322
+ for (const statement of bodyStatements) {
1323
+ const statementCode = this.generateNode(statement);
1324
+ if (statementCode) {
1325
+ code += this.indent(statementCode) + `
1326
+ `;
1327
+ }
1328
+ }
1329
+ this.indentLevel--;
1330
+ code += "} while (!(" + conditionCode + "));";
1331
+ return code;
1332
+ }
1333
+ generateReadStatement(node) {
1334
+ if (!node.children || node.children.length === 0) {
1335
+ return "";
1336
+ }
1337
+ const variable = node.children[0];
1338
+ if (!variable) {
1339
+ return "";
1340
+ }
1341
+ const variableName = variable.value;
1342
+ const symbolInfo = this.symbolTable.symbols.get(variableName);
1343
+ let conversion = "";
1344
+ if (symbolInfo) {
1345
+ switch (symbolInfo.type) {
1346
+ case "ENTIER":
1347
+ case "REEL":
1348
+ conversion = "parseInt(";
1349
+ break;
1350
+ case "BOOLEEN":
1351
+ conversion = "(";
1352
+ break;
1353
+ default:
1354
+ conversion = "";
1355
+ }
1356
+ }
1357
+ if (conversion) {
1358
+ return `${variableName} = ${conversion}await lire(""));`;
1359
+ } else {
1360
+ return `${variableName} = await lire("");`;
1361
+ }
1362
+ }
1363
+ generateWriteStatement(node) {
1364
+ if (!node.children || node.children.length === 0) {
1365
+ return "";
1366
+ }
1367
+ const expressionCodes = [];
1368
+ for (const child of node.children) {
1369
+ if (child) {
1370
+ const expressionCode = this.generateNode(child);
1371
+ expressionCodes.push(expressionCode);
1372
+ }
1373
+ }
1374
+ if (expressionCodes.length === 1) {
1375
+ return `ecrire(${expressionCodes[0]});`;
1376
+ }
1377
+ const concatenated = expressionCodes.join(", ");
1378
+ return `ecrire(${concatenated});`;
1379
+ }
1380
+ generateBinaryOp(node) {
1381
+ if (!node.children || node.children.length < 2) {
1382
+ return "";
1383
+ }
1384
+ const left = node.children[0];
1385
+ const right = node.children[1];
1386
+ const operator = node.value;
1387
+ if (!left || !right) {
1388
+ return "";
1389
+ }
1390
+ const leftCode = this.generateNode(left);
1391
+ const rightCode = this.generateNode(right);
1392
+ const jsOperator = this.mapOperator(operator);
1393
+ return `(${leftCode} ${jsOperator} ${rightCode})`;
1394
+ }
1395
+ generateUnaryOp(node) {
1396
+ if (!node.children || node.children.length === 0) {
1397
+ return "";
1398
+ }
1399
+ const operand = node.children[0];
1400
+ const operator = node.value;
1401
+ if (!operand) {
1402
+ return "";
1403
+ }
1404
+ const operandCode = this.generateNode(operand);
1405
+ if (operator === "non") {
1406
+ return `!(${operandCode})`;
1407
+ } else if (operator === "-") {
1408
+ return `-${operandCode}`;
1409
+ }
1410
+ return operandCode;
1411
+ }
1412
+ generateLiteral(node) {
1413
+ if (node.value === undefined || node.value === null) {
1414
+ return "null";
1415
+ }
1416
+ if (typeof node.value === "boolean") {
1417
+ return node.value ? "true" : "false";
1418
+ }
1419
+ if (typeof node.value === "number") {
1420
+ return node.value.toString();
1421
+ }
1422
+ if (typeof node.value === "string") {
1423
+ return `"${node.value}"`;
1424
+ }
1425
+ return node.value?.toString() ?? "null";
1426
+ }
1427
+ generateVariable(node) {
1428
+ return node.value;
1429
+ }
1430
+ mapAlgoLangTypeToJS(algoLangType) {
1431
+ switch (algoLangType) {
1432
+ case "ENTIER":
1433
+ return "number";
1434
+ case "REEL":
1435
+ return "number";
1436
+ case "BOOLEEN":
1437
+ return "boolean";
1438
+ case "CHAINE":
1439
+ return "string";
1440
+ default:
1441
+ return "any";
1442
+ }
1443
+ }
1444
+ mapOperator(operator) {
1445
+ switch (operator) {
1446
+ case ":=":
1447
+ return "=";
1448
+ case "=":
1449
+ return "===";
1450
+ case "<>":
1451
+ return "!==";
1452
+ case "<":
1453
+ return "<";
1454
+ case "<=":
1455
+ return "<=";
1456
+ case ">":
1457
+ return ">";
1458
+ case ">=":
1459
+ return ">=";
1460
+ case "et":
1461
+ return "&&";
1462
+ case "ou":
1463
+ return "||";
1464
+ case "non":
1465
+ return "!";
1466
+ default:
1467
+ return operator;
1468
+ }
1469
+ }
1470
+ indent(code) {
1471
+ return " ".repeat(this.indentLevel) + code;
1472
+ }
1473
+ }
1474
+ // src/lexer/lexer.ts
1475
+ class Lexer2 {
1476
+ source;
1477
+ position = 0;
1478
+ line = 1;
1479
+ column = 1;
1480
+ keywords;
1481
+ constructor(source) {
1482
+ this.source = source;
1483
+ this.keywords = new Map([
1484
+ ["PROGRAMME", "PROGRAMME" /* PROGRAM */],
1485
+ ["DEBUT", "DEBUT" /* BEGIN */],
1486
+ ["FIN", "FIN" /* END */],
1487
+ ["VAR", "VAR" /* VAR */],
1488
+ ["ENTIER", "ENTIER" /* INTEGER */],
1489
+ ["REEL", "REEL" /* REAL */],
1490
+ ["BOOLEEN", "BOOLEEN" /* BOOLEAN */],
1491
+ ["CHAINE", "CHAINE" /* STRING */],
1492
+ ["SI", "SI" /* IF */],
1493
+ ["ALORS", "ALORS" /* THEN */],
1494
+ ["SINON", "SINON" /* ELSE */],
1495
+ ["FINSI", "FINIF" /* ENDIF */],
1496
+ ["TANTQUE", "TANTQUE" /* WHILE */],
1497
+ ["FAIRE", "FAIRE" /* DO */],
1498
+ ["POUR", "POUR" /* FOR */],
1499
+ ["ALLANT", "ALLANT" /* ALLANT */],
1500
+ ["DE", "DE" /* DE */],
1501
+ ["A", "A" /* TO */],
1502
+ ["REPETER", "REPETER" /* REPEAT */],
1503
+ ["JUSQUA", "JUSQUA" /* UNTIL */],
1504
+ ["LIRE", "LIRE" /* READ */],
1505
+ ["ECRIRE", "ECRIRE" /* WRITE */],
1506
+ ["VRAI", "VRAI" /* TRUE */],
1507
+ ["FAUX", "FAUX" /* FALSE */],
1508
+ ["ET", "ET" /* AND */],
1509
+ ["OU", "OU" /* OR */],
1510
+ ["NON", "NON" /* NOT */],
1511
+ ["FINPOUR", "FINPOUR" /* ENDFOR */],
1512
+ ["FINTANTQUE", "FINTANTQUE" /* ENDWHILE */]
1513
+ ]);
1514
+ }
1515
+ tokenize() {
1516
+ const tokens = [];
1517
+ while (!this.isAtEnd()) {
1518
+ const token = this.scanToken();
1519
+ if (token.type !== "COMMENT" /* COMMENT */) {
1520
+ tokens.push(token);
1521
+ }
1522
+ }
1523
+ tokens.push({
1524
+ type: "EOF" /* EOF */,
1525
+ value: "",
1526
+ line: this.line,
1527
+ column: this.column,
1528
+ position: this.position
1529
+ });
1530
+ return tokens;
1531
+ }
1532
+ scanToken() {
1533
+ this.skipWhitespace();
1534
+ if (this.isAtEnd()) {
1535
+ return this.createToken("EOF" /* EOF */, "");
1536
+ }
1537
+ const char = this.currentChar();
1538
+ if (char === "/" && this.peek() === "/") {
1539
+ return this.scanLineComment();
1540
+ }
1541
+ if (char === "/" && this.peek() === "*") {
1542
+ return this.scanBlockComment();
1543
+ }
1544
+ if (char === '"') {
1545
+ return this.scanString();
1546
+ }
1547
+ if (this.isDigit(char)) {
1548
+ return this.scanNumber();
1549
+ }
1550
+ if (this.isAlpha(char)) {
1551
+ return this.scanIdentifier();
1552
+ }
1553
+ if (char === ":" && this.peek() === "=") {
1554
+ const token = this.createToken("ASSIGN" /* ASSIGN */, ":=");
1555
+ this.advance();
1556
+ this.advance();
1557
+ return token;
1558
+ }
1559
+ if (char === "<" && this.peek() === "=") {
1560
+ const token = this.createToken("LESS_EQUAL" /* LESS_EQUAL */, "<=");
1561
+ this.advance();
1562
+ this.advance();
1563
+ return token;
1564
+ }
1565
+ if (char === ">" && this.peek() === "=") {
1566
+ const token = this.createToken("GREATER_EQUAL" /* GREATER_EQUAL */, ">=");
1567
+ this.advance();
1568
+ this.advance();
1569
+ return token;
1570
+ }
1571
+ if (char === "<" && this.peek() === ">") {
1572
+ const token = this.createToken("NOT_EQUAL" /* NOT_EQUAL */, "<>");
1573
+ this.advance();
1574
+ this.advance();
1575
+ return token;
1576
+ }
1577
+ switch (char) {
1578
+ case "+":
1579
+ return this.createToken("PLUS" /* PLUS */, this.advance());
1580
+ case "-":
1581
+ return this.createToken("MINUS" /* MINUS */, this.advance());
1582
+ case "*":
1583
+ return this.createToken("MULTIPLY" /* MULTIPLY */, this.advance());
1584
+ case "/":
1585
+ return this.createToken("DIVIDE" /* DIVIDE */, this.advance());
1586
+ case "=":
1587
+ return this.createToken("EQUAL" /* EQUAL */, this.advance());
1588
+ case "<":
1589
+ return this.createToken("LESS_THAN" /* LESS_THAN */, this.advance());
1590
+ case ">":
1591
+ return this.createToken("GREATER_THAN" /* GREATER_THAN */, this.advance());
1592
+ case ";":
1593
+ return this.createToken("SEMICOLON" /* SEMICOLON */, this.advance());
1594
+ case ":":
1595
+ return this.createToken("COLON" /* COLON */, this.advance());
1596
+ case ",":
1597
+ return this.createToken("COMMA" /* COMMA */, this.advance());
1598
+ case ".":
1599
+ return this.createToken("DOT" /* DOT */, this.advance());
1600
+ case "(":
1601
+ return this.createToken("LEFT_PAREN" /* LEFT_PAREN */, this.advance());
1602
+ case ")":
1603
+ return this.createToken("RIGHT_PAREN" /* RIGHT_PAREN */, this.advance());
1604
+ default:
1605
+ throw new Error(`Caractère non reconnu '${char}' à la ligne ${this.line}, colonne ${this.column}`);
1606
+ }
1607
+ }
1608
+ scanIdentifier() {
1609
+ const start = this.position;
1610
+ const startColumn = this.column;
1611
+ while (!this.isAtEnd() && this.isAlphaNumeric(this.currentChar())) {
1612
+ this.advance();
1613
+ }
1614
+ const value = this.source.substring(start, this.position);
1615
+ const type = this.keywords.get(value.toUpperCase()) || "IDENTIFIER" /* IDENTIFIER */;
1616
+ return {
1617
+ type,
1618
+ value,
1619
+ line: this.line,
1620
+ column: startColumn,
1621
+ position: start
1622
+ };
1623
+ }
1624
+ scanNumber() {
1625
+ const start = this.position;
1626
+ const startColumn = this.column;
1627
+ let hasDecimal = false;
1628
+ while (!this.isAtEnd() && (this.isDigit(this.currentChar()) || this.currentChar() === ".")) {
1629
+ if (this.currentChar() === ".") {
1630
+ if (hasDecimal) {
1631
+ throw new Error(`Nombre invalide: trop de points décimaux à la ligne ${this.line}, colonne ${this.column}`);
1632
+ }
1633
+ hasDecimal = true;
1634
+ }
1635
+ this.advance();
1636
+ }
1637
+ const value = this.source.substring(start, this.position);
1638
+ return {
1639
+ type: "NUMBER" /* NUMBER */,
1640
+ value,
1641
+ line: this.line,
1642
+ column: startColumn,
1643
+ position: start
1644
+ };
1645
+ }
1646
+ scanString() {
1647
+ const start = this.position;
1648
+ const startColumn = this.column;
1649
+ this.advance();
1650
+ let value = "";
1651
+ while (!this.isAtEnd() && this.currentChar() !== '"') {
1652
+ if (this.currentChar() === "\\") {
1653
+ this.advance();
1654
+ if (this.isAtEnd()) {
1655
+ throw new Error(`Chaîne de caractères non terminée à la ligne ${this.line}, colonne ${this.column}`);
1656
+ }
1657
+ const escaped = this.currentChar();
1658
+ switch (escaped) {
1659
+ case "n":
1660
+ value += `
1661
+ `;
1662
+ break;
1663
+ case "t":
1664
+ value += "\t";
1665
+ break;
1666
+ case "r":
1667
+ value += "\r";
1668
+ break;
1669
+ case "\\":
1670
+ value += "\\";
1671
+ break;
1672
+ case '"':
1673
+ value += '"';
1674
+ break;
1675
+ default:
1676
+ value += escaped;
1677
+ break;
1678
+ }
1679
+ this.advance();
1680
+ } else {
1681
+ value += this.currentChar();
1682
+ this.advance();
1683
+ }
1684
+ }
1685
+ if (this.isAtEnd()) {
1686
+ throw new Error(`Chaîne de caractères non terminée à la ligne ${this.line}, colonne ${this.column}`);
1687
+ }
1688
+ this.advance();
1689
+ return {
1690
+ type: "STRING_LITERAL" /* STRING_LITERAL */,
1691
+ value,
1692
+ line: this.line,
1693
+ column: startColumn,
1694
+ position: start
1695
+ };
1696
+ }
1697
+ scanLineComment() {
1698
+ const start = this.position;
1699
+ const startColumn = this.column;
1700
+ while (!this.isAtEnd() && this.currentChar() !== `
1701
+ `) {
1702
+ this.advance();
1703
+ }
1704
+ const value = this.source.substring(start, this.position);
1705
+ return {
1706
+ type: "COMMENT" /* COMMENT */,
1707
+ value,
1708
+ line: this.line,
1709
+ column: startColumn,
1710
+ position: start
1711
+ };
1712
+ }
1713
+ scanBlockComment() {
1714
+ const start = this.position;
1715
+ const startColumn = this.column;
1716
+ this.advance();
1717
+ while (!this.isAtEnd() && !(this.currentChar() === "*" && this.peek() === "/")) {
1718
+ if (this.currentChar() === `
1719
+ `) {
1720
+ this.line++;
1721
+ this.column = 1;
1722
+ } else {
1723
+ this.column++;
1724
+ }
1725
+ this.advance();
1726
+ }
1727
+ if (this.isAtEnd()) {
1728
+ throw new Error(`Commentaire bloc non terminé commençant à la ligne ${this.line}, colonne ${this.column}`);
1729
+ }
1730
+ this.advance();
1731
+ this.advance();
1732
+ const value = this.source.substring(start, this.position);
1733
+ return {
1734
+ type: "COMMENT" /* COMMENT */,
1735
+ value,
1736
+ line: this.line,
1737
+ column: startColumn,
1738
+ position: start
1739
+ };
1740
+ }
1741
+ skipWhitespace() {
1742
+ while (!this.isAtEnd() && this.isWhitespace(this.currentChar())) {
1743
+ if (this.currentChar() === `
1744
+ `) {
1745
+ this.line++;
1746
+ this.column = 1;
1747
+ } else {
1748
+ this.column++;
1749
+ }
1750
+ this.advance();
1751
+ }
1752
+ }
1753
+ createToken(type, value) {
1754
+ return {
1755
+ type,
1756
+ value,
1757
+ line: this.line,
1758
+ column: this.column,
1759
+ position: this.position
1760
+ };
1761
+ }
1762
+ advance() {
1763
+ const char = this.source[this.position];
1764
+ this.position++;
1765
+ return char !== undefined ? char : "\x00";
1766
+ }
1767
+ currentChar() {
1768
+ const char = this.source[this.position];
1769
+ return char !== undefined ? char : "\x00";
1770
+ }
1771
+ peek() {
1772
+ if (this.position + 1 >= this.source.length) {
1773
+ return "\x00";
1774
+ }
1775
+ const char = this.source[this.position + 1];
1776
+ return char !== undefined ? char : "\x00";
1777
+ }
1778
+ isAtEnd() {
1779
+ return this.position >= this.source.length;
1780
+ }
1781
+ isDigit(char) {
1782
+ return char >= "0" && char <= "9";
1783
+ }
1784
+ isAlpha(char) {
1785
+ return char >= "a" && char <= "z" || char >= "A" && char <= "Z" || char >= "À" && char <= "ÿ" || char === "_" || char === "'";
1786
+ }
1787
+ isAlphaNumeric(char) {
1788
+ return this.isAlpha(char) || this.isDigit(char);
1789
+ }
1790
+ isWhitespace(char) {
1791
+ return char === " " || char === "\t" || char === `
1792
+ ` || char === "\r";
1793
+ }
1794
+ }
1795
+
1796
+ // src/parser/parser.ts
1797
+ class Parser2 {
1798
+ tokens;
1799
+ current = 0;
1800
+ errors = [];
1801
+ symbolTable;
1802
+ reservedKeywords = new Set([
1803
+ "programme",
1804
+ "debut",
1805
+ "fin",
1806
+ "var",
1807
+ "entier",
1808
+ "reel",
1809
+ "booleen",
1810
+ "chaine",
1811
+ "si",
1812
+ "alors",
1813
+ "sinon",
1814
+ "finsi",
1815
+ "tantque",
1816
+ "faire",
1817
+ "fintantque",
1818
+ "pour",
1819
+ "a",
1820
+ "finpour",
1821
+ "repeter",
1822
+ "jusqua",
1823
+ "lire",
1824
+ "ecrire",
1825
+ "vrai",
1826
+ "faux",
1827
+ "et",
1828
+ "ou",
1829
+ "non",
1830
+ "fonction",
1831
+ "procedure",
1832
+ "retourner"
1833
+ ]);
1834
+ constructor(tokens) {
1835
+ this.tokens = tokens;
1836
+ this.symbolTable = {
1837
+ symbols: new Map,
1838
+ children: [],
1839
+ scopeName: "global"
1840
+ };
1841
+ }
1842
+ isReservedKeyword(identifier) {
1843
+ return this.reservedKeywords.has(identifier.toLowerCase());
1844
+ }
1845
+ isKeywordToken(tokenType) {
1846
+ return [
1847
+ "PROGRAMME" /* PROGRAM */,
1848
+ "DEBUT" /* BEGIN */,
1849
+ "FIN" /* END */,
1850
+ "VAR" /* VAR */,
1851
+ "ENTIER" /* INTEGER */,
1852
+ "REEL" /* REAL */,
1853
+ "BOOLEEN" /* BOOLEAN */,
1854
+ "CHAINE" /* STRING */,
1855
+ "SI" /* IF */,
1856
+ "ALORS" /* THEN */,
1857
+ "SINON" /* ELSE */,
1858
+ "TANTQUE" /* WHILE */,
1859
+ "FAIRE" /* DO */,
1860
+ "POUR" /* FOR */,
1861
+ "ALLANT" /* ALLANT */,
1862
+ "DE" /* DE */,
1863
+ "A" /* TO */,
1864
+ "REPETER" /* REPEAT */,
1865
+ "JUSQUA" /* UNTIL */,
1866
+ "LIRE" /* READ */,
1867
+ "ECRIRE" /* WRITE */,
1868
+ "VRAI" /* TRUE */,
1869
+ "FAUX" /* FALSE */,
1870
+ "ET" /* AND */,
1871
+ "OU" /* OR */,
1872
+ "NON" /* NOT */,
1873
+ "FINPOUR" /* ENDFOR */,
1874
+ "FINIF" /* ENDIF */,
1875
+ "FINTANTQUE" /* ENDWHILE */
1876
+ ].includes(tokenType);
1877
+ }
1878
+ createReservedKeywordError(identifier, token) {
1879
+ this.errors.push({
1880
+ type: "ERROR",
1881
+ message: `Le nom '${identifier}' est un mot-clé réservé et ne peut pas être utilisé comme nom de variable`,
1882
+ line: token.line,
1883
+ column: token.column,
1884
+ position: token.position,
1885
+ code: "RESERVED_KEYWORD",
1886
+ explanation: "Les mots-clés réservés sont utilisés par le langage AlgoLang pour définir la structure du programme et ne peuvent pas être utilisés comme noms de variables.",
1887
+ suggestion: `Choisissez un autre nom plus descriptif, par exemple: '${identifier}Valeur', '${identifier}Temp', 'ma${identifier.charAt(0).toUpperCase() + identifier.slice(1)}'`
1888
+ });
1889
+ }
1890
+ parse() {
1891
+ try {
1892
+ const program = this.parseProgram();
1893
+ return {
1894
+ ast: program,
1895
+ errors: this.errors,
1896
+ symbolTable: this.symbolTable
1897
+ };
1898
+ } catch (error) {
1899
+ return {
1900
+ ast: { type: "PROGRAM" /* PROGRAM */, children: [] },
1901
+ errors: [
1902
+ ...this.errors,
1903
+ {
1904
+ type: "ERROR",
1905
+ message: error instanceof Error ? error.message : "Erreur de parsing inconnue",
1906
+ line: 1,
1907
+ column: 1,
1908
+ position: 0,
1909
+ code: "PARSE_ERROR"
1910
+ }
1911
+ ],
1912
+ symbolTable: this.symbolTable
1913
+ };
1914
+ }
1915
+ }
1916
+ parseProgram() {
1917
+ const programToken = this.expect("PROGRAMME" /* PROGRAM */, 'Le programme doit commencer par le mot-clé "programme"');
1918
+ const identifier = this.expect("IDENTIFIER" /* IDENTIFIER */, "Le programme doit avoir un nom");
1919
+ this.expect("SEMICOLON" /* SEMICOLON */, "Le nom du programme doit être suivi d'un point-virgule");
1920
+ const block = this.parseBlock();
1921
+ return {
1922
+ type: "PROGRAM" /* PROGRAM */,
1923
+ value: identifier.value,
1924
+ children: [block],
1925
+ token: programToken
1926
+ };
1927
+ }
1928
+ parseBlock() {
1929
+ const declarations = this.parseDeclarations();
1930
+ const compoundStatement = this.parseCompoundStatement();
1931
+ return {
1932
+ type: "BLOCK" /* BLOCK */,
1933
+ children: [declarations, compoundStatement]
1934
+ };
1935
+ }
1936
+ parseDeclarations() {
1937
+ const declarations = [];
1938
+ while (this.check("VAR" /* VAR */)) {
1939
+ this.advance();
1940
+ while (!this.check("DEBUT" /* BEGIN */) && !this.isAtEnd()) {
1941
+ const declaration = this.parseVariableDeclaration();
1942
+ declarations.push(declaration);
1943
+ if (!this.check("SEMICOLON" /* SEMICOLON */)) {
1944
+ break;
1945
+ }
1946
+ this.advance();
1947
+ }
1948
+ }
1949
+ return {
1950
+ type: "BLOCK" /* BLOCK */,
1951
+ children: declarations
1952
+ };
1953
+ }
1954
+ parseVariableDeclaration() {
1955
+ const identifiers = [];
1956
+ do {
1957
+ let identifier;
1958
+ if (this.check("IDENTIFIER" /* IDENTIFIER */)) {
1959
+ identifier = this.advance();
1960
+ } else {
1961
+ const currentToken = this.peek();
1962
+ if (this.isKeywordToken(currentToken.type)) {
1963
+ identifier = this.advance();
1964
+ this.createReservedKeywordError(identifier.value, identifier);
1965
+ } else {
1966
+ this.expect("IDENTIFIER" /* IDENTIFIER */, "Identificateur attendu dans la déclaration de variable");
1967
+ break;
1968
+ }
1969
+ }
1970
+ if (this.isReservedKeyword(identifier.value)) {
1971
+ this.createReservedKeywordError(identifier.value, identifier);
1972
+ }
1973
+ identifiers.push(identifier.value);
1974
+ if (this.check("COMMA" /* COMMA */)) {
1975
+ this.advance();
1976
+ } else {
1977
+ break;
1978
+ }
1979
+ } while (true);
1980
+ this.expect("COLON" /* COLON */, "Deux-points attendus après les identificateurs");
1981
+ const typeToken = this.expect(["ENTIER" /* INTEGER */, "REEL" /* REAL */, "BOOLEEN" /* BOOLEAN */, "CHAINE" /* STRING */], "Type de variable attendu");
1982
+ const type = this.tokenTypeToDataType(typeToken.type);
1983
+ for (const identifier of identifiers) {
1984
+ if (this.symbolTable.symbols.has(identifier)) {
1985
+ this.errors.push({
1986
+ type: "ERROR",
1987
+ message: `La variable '${identifier}' est déjà déclarée`,
1988
+ line: typeToken.line,
1989
+ column: typeToken.column,
1990
+ position: typeToken.position,
1991
+ code: "DUPLICATE_VARIABLE",
1992
+ explanation: "Chaque variable doit avoir un nom unique dans son scope",
1993
+ suggestion: `Choisissez un autre nom pour la variable '${identifier}'`
1994
+ });
1995
+ } else {
1996
+ const symbolInfo = {
1997
+ name: identifier,
1998
+ type,
1999
+ scope: this.symbolTable.scopeName,
2000
+ line: typeToken.line,
2001
+ column: typeToken.column
2002
+ };
2003
+ this.symbolTable.symbols.set(identifier, symbolInfo);
2004
+ }
2005
+ }
2006
+ return {
2007
+ type: "VAR_DECLARATION" /* VAR_DECLARATION */,
2008
+ value: type,
2009
+ children: identifiers.map((name) => ({
2010
+ type: "VARIABLE" /* VARIABLE */,
2011
+ value: name
2012
+ })),
2013
+ token: typeToken
2014
+ };
2015
+ }
2016
+ parseCompoundStatement() {
2017
+ this.expect("DEBUT" /* BEGIN */, `Le bloc d'instructions doit commencer par "debut"`);
2018
+ const statements = [];
2019
+ while (!this.check("FIN" /* END */) && !this.isAtEnd()) {
2020
+ const statement = this.parseStatement();
2021
+ statements.push(statement);
2022
+ if (this.check("SEMICOLON" /* SEMICOLON */)) {
2023
+ this.advance();
2024
+ } else if (!this.check("FIN" /* END */) && !this.check("FINIF" /* ENDIF */) && !this.check("FINTANTQUE" /* ENDWHILE */)) {
2025
+ this.errors.push({
2026
+ type: "ERROR",
2027
+ message: "Point-virgule attendu après l'instruction",
2028
+ line: this.peek().line,
2029
+ column: this.peek().column,
2030
+ position: this.peek().position,
2031
+ code: "MISSING_SEMICOLON"
2032
+ });
2033
+ break;
2034
+ }
2035
+ }
2036
+ this.expect("FIN" /* END */, `Le bloc d'instructions doit se terminer par "fin"`);
2037
+ return {
2038
+ type: "COMPOUND_STATEMENT" /* COMPOUND_STATEMENT */,
2039
+ children: statements
2040
+ };
2041
+ }
2042
+ parseStatement() {
2043
+ if (this.check("DEBUT" /* BEGIN */)) {
2044
+ return this.parseCompoundStatement();
2045
+ }
2046
+ if (this.isKeywordToken(this.peek().type) && this.peekAhead(1)?.type === "ASSIGN" /* ASSIGN */) {
2047
+ return this.parseAssignment();
2048
+ }
2049
+ if (this.check("SI" /* IF */)) {
2050
+ return this.parseIfStatement();
2051
+ }
2052
+ if (this.check("TANTQUE" /* WHILE */)) {
2053
+ return this.parseWhileStatement();
2054
+ }
2055
+ if (this.check("POUR" /* FOR */)) {
2056
+ return this.parseForStatement();
2057
+ }
2058
+ if (this.check("REPETER" /* REPEAT */)) {
2059
+ return this.parseRepeatStatement();
2060
+ }
2061
+ if (this.check("LIRE" /* READ */)) {
2062
+ return this.parseReadStatement();
2063
+ }
2064
+ if (this.check("ECRIRE" /* WRITE */)) {
2065
+ return this.parseWriteStatement();
2066
+ }
2067
+ return this.parseAssignment();
2068
+ }
2069
+ parseIfStatement(isElseIf = false) {
2070
+ const ifToken = this.advance();
2071
+ const condition = this.parseExpression();
2072
+ this.expect("ALORS" /* THEN */, '"alors" attendu après la condition du si');
2073
+ const thenStatements = [];
2074
+ while (!this.check("SINON" /* ELSE */) && !this.check("FINIF" /* ENDIF */) && !this.check("FIN" /* END */) && !this.isAtEnd()) {
2075
+ const statement = this.parseStatement();
2076
+ thenStatements.push(statement);
2077
+ if (this.check("SEMICOLON" /* SEMICOLON */)) {
2078
+ this.advance();
2079
+ }
2080
+ }
2081
+ const thenStatement = {
2082
+ type: "COMPOUND_STATEMENT" /* COMPOUND_STATEMENT */,
2083
+ children: thenStatements
2084
+ };
2085
+ let elseStatement;
2086
+ if (this.check("SEMICOLON" /* SEMICOLON */) && this.peekAhead(1)?.type === "SINON" /* ELSE */) {
2087
+ this.advance();
2088
+ }
2089
+ if (this.check("SINON" /* ELSE */)) {
2090
+ this.advance();
2091
+ if (this.check("SI" /* IF */)) {
2092
+ elseStatement = this.parseIfStatement(true);
2093
+ } else {
2094
+ const elseStatements = [];
2095
+ while (!this.check("FINIF" /* ENDIF */) && !this.check("FIN" /* END */) && !this.isAtEnd()) {
2096
+ const statement = this.parseStatement();
2097
+ elseStatements.push(statement);
2098
+ if (this.check("SEMICOLON" /* SEMICOLON */)) {
2099
+ this.advance();
2100
+ }
2101
+ }
2102
+ elseStatement = {
2103
+ type: "COMPOUND_STATEMENT" /* COMPOUND_STATEMENT */,
2104
+ children: elseStatements
2105
+ };
2106
+ }
2107
+ }
2108
+ if (!isElseIf) {
2109
+ if (this.check("SEMICOLON" /* SEMICOLON */) && this.peekAhead(1)?.type === "FINIF" /* ENDIF */) {
2110
+ this.advance();
2111
+ }
2112
+ this.expect("FINIF" /* ENDIF */, '"finsi" attendu à la fin du bloc si');
2113
+ }
2114
+ return {
2115
+ type: "IF_STATEMENT" /* IF_STATEMENT */,
2116
+ children: [
2117
+ condition,
2118
+ thenStatement,
2119
+ ...elseStatement ? [elseStatement] : []
2120
+ ],
2121
+ token: ifToken
2122
+ };
2123
+ }
2124
+ parseWhileStatement() {
2125
+ const whileToken = this.advance();
2126
+ const condition = this.parseExpression();
2127
+ this.expect("FAIRE" /* DO */, '"faire" attendu après la condition du tantque');
2128
+ const bodyStatements = [];
2129
+ while (!this.check("FINTANTQUE" /* ENDWHILE */) && !this.check("FIN" /* END */) && !this.isAtEnd()) {
2130
+ const statement = this.parseStatement();
2131
+ bodyStatements.push(statement);
2132
+ if (this.check("SEMICOLON" /* SEMICOLON */)) {
2133
+ this.advance();
2134
+ }
2135
+ }
2136
+ this.expect("FINTANTQUE" /* ENDWHILE */, '"fintantque" attendu à la fin de la boucle tantque');
2137
+ return {
2138
+ type: "WHILE_STATEMENT" /* WHILE_STATEMENT */,
2139
+ children: [
2140
+ condition,
2141
+ { type: "COMPOUND_STATEMENT" /* COMPOUND_STATEMENT */, children: bodyStatements }
2142
+ ],
2143
+ token: whileToken
2144
+ };
2145
+ }
2146
+ parseForStatement() {
2147
+ const forToken = this.advance();
2148
+ const variable = this.expect("IDENTIFIER" /* IDENTIFIER */, 'Identificateur attendu après "pour"');
2149
+ let startValue;
2150
+ if (this.check("ALLANT" /* ALLANT */)) {
2151
+ this.advance();
2152
+ this.expect("DE" /* DE */, '"de" attendu après "allant" dans la boucle pour');
2153
+ startValue = this.parseExpression();
2154
+ } else if (this.check("ASSIGN" /* ASSIGN */)) {
2155
+ this.advance();
2156
+ startValue = this.parseExpression();
2157
+ } else {
2158
+ throw new Error('"allant de" ou ":=" attendu après la variable dans la boucle pour');
2159
+ }
2160
+ this.expect("A" /* TO */, '"a" attendu dans la boucle pour');
2161
+ const endValue = this.parseExpression();
2162
+ this.expect("FAIRE" /* DO */, '"faire" attendu dans la boucle pour');
2163
+ const bodyStatements = [];
2164
+ while (!this.check("FINPOUR" /* ENDFOR */) && !this.check("FIN" /* END */) && !this.isAtEnd()) {
2165
+ const statement = this.parseStatement();
2166
+ bodyStatements.push(statement);
2167
+ if (this.check("SEMICOLON" /* SEMICOLON */)) {
2168
+ this.advance();
2169
+ }
2170
+ }
2171
+ this.expect("FINPOUR" /* ENDFOR */, '"finpour" attendu à la fin de la boucle pour');
2172
+ return {
2173
+ type: "FOR_STATEMENT" /* FOR_STATEMENT */,
2174
+ children: [
2175
+ { type: "VARIABLE" /* VARIABLE */, value: variable.value, token: variable },
2176
+ startValue,
2177
+ endValue,
2178
+ { type: "COMPOUND_STATEMENT" /* COMPOUND_STATEMENT */, children: bodyStatements }
2179
+ ],
2180
+ token: forToken
2181
+ };
2182
+ }
2183
+ parseReadStatement() {
2184
+ const readToken = this.advance();
2185
+ this.expect("LEFT_PAREN" /* LEFT_PAREN */, 'Parenthèse ouvrante attendue après "lire"');
2186
+ let variable;
2187
+ if (this.check("IDENTIFIER" /* IDENTIFIER */)) {
2188
+ variable = this.advance();
2189
+ } else {
2190
+ const currentToken = this.peek();
2191
+ if (this.isKeywordToken(currentToken.type)) {
2192
+ variable = this.advance();
2193
+ this.createReservedKeywordError(variable.value, variable);
2194
+ } else {
2195
+ this.expect("IDENTIFIER" /* IDENTIFIER */, 'Variable attendue dans "lire"');
2196
+ throw new Error('Variable attendue dans "lire"');
2197
+ }
2198
+ }
2199
+ this.expect("RIGHT_PAREN" /* RIGHT_PAREN */, 'Parenthèse fermante attendue dans "lire"');
2200
+ return {
2201
+ type: "READ_STATEMENT" /* READ_STATEMENT */,
2202
+ children: [
2203
+ { type: "VARIABLE" /* VARIABLE */, value: variable.value, token: variable }
2204
+ ],
2205
+ token: readToken
2206
+ };
2207
+ }
2208
+ parseWriteStatement() {
2209
+ const writeToken = this.advance();
2210
+ this.expect("LEFT_PAREN" /* LEFT_PAREN */, 'Parenthèse ouvrante attendue après "ecrire"');
2211
+ const expressions = [];
2212
+ expressions.push(this.parseExpression());
2213
+ while (this.check("COMMA" /* COMMA */)) {
2214
+ this.advance();
2215
+ expressions.push(this.parseExpression());
2216
+ }
2217
+ this.expect("RIGHT_PAREN" /* RIGHT_PAREN */, 'Parenthèse fermante attendue dans "ecrire"');
2218
+ return {
2219
+ type: "WRITE_STATEMENT" /* WRITE_STATEMENT */,
2220
+ children: expressions,
2221
+ token: writeToken
2222
+ };
2223
+ }
2224
+ parseAssignment() {
2225
+ let variable;
2226
+ if (this.check("IDENTIFIER" /* IDENTIFIER */)) {
2227
+ variable = this.advance();
2228
+ } else {
2229
+ const currentToken = this.peek();
2230
+ if (this.isKeywordToken(currentToken.type)) {
2231
+ variable = this.advance();
2232
+ this.createReservedKeywordError(variable.value, variable);
2233
+ } else {
2234
+ this.expect("IDENTIFIER" /* IDENTIFIER */, "Variable attendue dans l'affectation");
2235
+ throw new Error("Variable attendue dans l'affectation");
2236
+ }
2237
+ }
2238
+ if (this.isReservedKeyword(variable.value)) {
2239
+ this.createReservedKeywordError(variable.value, variable);
2240
+ }
2241
+ this.expect("ASSIGN" /* ASSIGN */, `":=" attendu dans l'affectation`);
2242
+ const expression = this.parseExpression();
2243
+ return {
2244
+ type: "ASSIGNMENT" /* ASSIGNMENT */,
2245
+ children: [
2246
+ { type: "VARIABLE" /* VARIABLE */, value: variable.value, token: variable },
2247
+ expression
2248
+ ],
2249
+ token: variable
2250
+ };
2251
+ }
2252
+ parseExpression() {
2253
+ return this.parseOrExpression();
2254
+ }
2255
+ parseOrExpression() {
2256
+ let left = this.parseAndExpression();
2257
+ while (this.check("OU" /* OR */)) {
2258
+ const operator = this.advance();
2259
+ const right = this.parseAndExpression();
2260
+ left = {
2261
+ type: "BINARY_OP" /* BINARY_OP */,
2262
+ value: operator.value,
2263
+ children: [left, right],
2264
+ token: operator
2265
+ };
2266
+ }
2267
+ return left;
2268
+ }
2269
+ parseAndExpression() {
2270
+ let left = this.parseEqualityExpression();
2271
+ while (this.check("ET" /* AND */)) {
2272
+ const operator = this.advance();
2273
+ const right = this.parseEqualityExpression();
2274
+ left = {
2275
+ type: "BINARY_OP" /* BINARY_OP */,
2276
+ value: operator.value,
2277
+ children: [left, right],
2278
+ token: operator
2279
+ };
2280
+ }
2281
+ return left;
2282
+ }
2283
+ parseEqualityExpression() {
2284
+ let left = this.parseRelationalExpression();
2285
+ while (this.check(["EQUAL" /* EQUAL */, "NOT_EQUAL" /* NOT_EQUAL */])) {
2286
+ const operator = this.advance();
2287
+ const right = this.parseRelationalExpression();
2288
+ left = {
2289
+ type: "BINARY_OP" /* BINARY_OP */,
2290
+ value: operator.value,
2291
+ children: [left, right],
2292
+ token: operator
2293
+ };
2294
+ }
2295
+ return left;
2296
+ }
2297
+ parseRelationalExpression() {
2298
+ let left = this.parseAdditiveExpression();
2299
+ while (this.check([
2300
+ "LESS_THAN" /* LESS_THAN */,
2301
+ "LESS_EQUAL" /* LESS_EQUAL */,
2302
+ "GREATER_THAN" /* GREATER_THAN */,
2303
+ "GREATER_EQUAL" /* GREATER_EQUAL */
2304
+ ])) {
2305
+ const operator = this.advance();
2306
+ const right = this.parseAdditiveExpression();
2307
+ left = {
2308
+ type: "BINARY_OP" /* BINARY_OP */,
2309
+ value: operator.value,
2310
+ children: [left, right],
2311
+ token: operator
2312
+ };
2313
+ }
2314
+ return left;
2315
+ }
2316
+ parseAdditiveExpression() {
2317
+ let left = this.parseMultiplicativeExpression();
2318
+ while (this.check(["PLUS" /* PLUS */, "MINUS" /* MINUS */])) {
2319
+ const operator = this.advance();
2320
+ const right = this.parseMultiplicativeExpression();
2321
+ left = {
2322
+ type: "BINARY_OP" /* BINARY_OP */,
2323
+ value: operator.value,
2324
+ children: [left, right],
2325
+ token: operator
2326
+ };
2327
+ }
2328
+ return left;
2329
+ }
2330
+ parseMultiplicativeExpression() {
2331
+ let left = this.parseUnaryExpression();
2332
+ while (this.check(["MULTIPLY" /* MULTIPLY */, "DIVIDE" /* DIVIDE */])) {
2333
+ const operator = this.advance();
2334
+ const right = this.parseUnaryExpression();
2335
+ left = {
2336
+ type: "BINARY_OP" /* BINARY_OP */,
2337
+ value: operator.value,
2338
+ children: [left, right],
2339
+ token: operator
2340
+ };
2341
+ }
2342
+ return left;
2343
+ }
2344
+ parseUnaryExpression() {
2345
+ if (this.check("NON" /* NOT */)) {
2346
+ const nextToken = this.peekAhead();
2347
+ if (nextToken && [
2348
+ "RIGHT_PAREN" /* RIGHT_PAREN */,
2349
+ "SEMICOLON" /* SEMICOLON */,
2350
+ "COMMA" /* COMMA */,
2351
+ "EOF" /* EOF */
2352
+ ].includes(nextToken.type)) {
2353
+ return this.parsePrimary();
2354
+ }
2355
+ }
2356
+ if (this.check(["NON" /* NOT */, "MINUS" /* MINUS */])) {
2357
+ const operator = this.advance();
2358
+ const operand = this.parseUnaryExpression();
2359
+ return {
2360
+ type: "UNARY_OP" /* UNARY_OP */,
2361
+ value: operator.value,
2362
+ children: [operand],
2363
+ token: operator
2364
+ };
2365
+ }
2366
+ return this.parsePrimary();
2367
+ }
2368
+ parsePrimary() {
2369
+ if (this.check("NUMBER" /* NUMBER */)) {
2370
+ const token2 = this.advance();
2371
+ return {
2372
+ type: "LITERAL" /* LITERAL */,
2373
+ value: parseFloat(token2.value),
2374
+ token: token2
2375
+ };
2376
+ }
2377
+ if (this.check(["VRAI" /* TRUE */, "FAUX" /* FALSE */])) {
2378
+ const token2 = this.advance();
2379
+ return {
2380
+ type: "LITERAL" /* LITERAL */,
2381
+ value: token2.value === "vrai",
2382
+ token: token2
2383
+ };
2384
+ }
2385
+ if (this.check("STRING_LITERAL" /* STRING_LITERAL */)) {
2386
+ const token2 = this.advance();
2387
+ return {
2388
+ type: "LITERAL" /* LITERAL */,
2389
+ value: token2.value,
2390
+ token: token2
2391
+ };
2392
+ }
2393
+ if (this.check("IDENTIFIER" /* IDENTIFIER */)) {
2394
+ const token2 = this.advance();
2395
+ if (this.isReservedKeyword(token2.value)) {
2396
+ this.createReservedKeywordError(token2.value, token2);
2397
+ }
2398
+ return {
2399
+ type: "VARIABLE" /* VARIABLE */,
2400
+ value: token2.value,
2401
+ token: token2
2402
+ };
2403
+ }
2404
+ const currentToken = this.peek();
2405
+ if (this.isKeywordToken(currentToken.type)) {
2406
+ const token2 = this.advance();
2407
+ this.createReservedKeywordError(token2.value, token2);
2408
+ return {
2409
+ type: "VARIABLE" /* VARIABLE */,
2410
+ value: token2.value,
2411
+ token: token2
2412
+ };
2413
+ }
2414
+ if (this.check("LEFT_PAREN" /* LEFT_PAREN */)) {
2415
+ this.advance();
2416
+ const expression = this.parseExpression();
2417
+ this.expect("RIGHT_PAREN" /* RIGHT_PAREN */, "Parenthèse fermante attendue");
2418
+ return expression;
2419
+ }
2420
+ const token = this.peek();
2421
+ this.errors.push({
2422
+ type: "ERROR",
2423
+ message: `Expression inattendue: ${token.value}`,
2424
+ line: token.line,
2425
+ column: token.column,
2426
+ position: token.position,
2427
+ code: "UNEXPECTED_TOKEN"
2428
+ });
2429
+ this.advance();
2430
+ return {
2431
+ type: "LITERAL" /* LITERAL */,
2432
+ value: 0
2433
+ };
2434
+ }
2435
+ parseRepeatStatement() {
2436
+ const repeatToken = this.advance();
2437
+ const statements = [];
2438
+ while (!this.check("JUSQUA" /* UNTIL */) && !this.isAtEnd()) {
2439
+ const statement = this.parseStatement();
2440
+ statements.push(statement);
2441
+ if (this.check("SEMICOLON" /* SEMICOLON */)) {
2442
+ this.advance();
2443
+ }
2444
+ }
2445
+ this.expect("JUSQUA" /* UNTIL */, '"jusqua" attendu à la fin de la boucle repeter');
2446
+ const condition = this.parseExpression();
2447
+ return {
2448
+ type: "REPEAT_STATEMENT" /* REPEAT_STATEMENT */,
2449
+ children: [...statements, condition],
2450
+ token: repeatToken
2451
+ };
2452
+ }
2453
+ check(type) {
2454
+ if (this.isAtEnd())
2455
+ return false;
2456
+ if (Array.isArray(type)) {
2457
+ return type.includes(this.peek().type);
2458
+ }
2459
+ return this.peek().type === type;
2460
+ }
2461
+ advance() {
2462
+ if (!this.isAtEnd())
2463
+ this.current++;
2464
+ return this.previous();
2465
+ }
2466
+ isAtEnd() {
2467
+ return this.peek().type === "EOF";
2468
+ }
2469
+ peek() {
2470
+ return this.tokens[this.current] ?? {
2471
+ type: "EOF" /* EOF */,
2472
+ value: "",
2473
+ line: 0,
2474
+ column: 0,
2475
+ position: 0
2476
+ };
2477
+ }
2478
+ peekAhead(offset = 1) {
2479
+ return this.tokens[this.current + offset];
2480
+ }
2481
+ previous() {
2482
+ return this.tokens[this.current - 1] ?? {
2483
+ type: "EOF" /* EOF */,
2484
+ value: "",
2485
+ line: 0,
2486
+ column: 0,
2487
+ position: 0
2488
+ };
2489
+ }
2490
+ expect(type, message) {
2491
+ if (this.check(type)) {
2492
+ return this.advance();
2493
+ }
2494
+ const token = this.peek();
2495
+ this.errors.push({
2496
+ type: "ERROR",
2497
+ message,
2498
+ line: token.line,
2499
+ column: token.column,
2500
+ position: token.position,
2501
+ code: "EXPECTED_TOKEN",
2502
+ explanation: `Attendu: ${Array.isArray(type) ? type.join(" ou ") : type}, Trouvé: ${token.type}`,
2503
+ suggestion: "Vérifiez la syntaxe de votre programme"
2504
+ });
2505
+ throw new Error(message);
2506
+ }
2507
+ tokenTypeToDataType(tokenType) {
2508
+ switch (tokenType) {
2509
+ case "ENTIER" /* INTEGER */:
2510
+ return "ENTIER" /* INTEGER */;
2511
+ case "REEL" /* REAL */:
2512
+ return "REEL" /* REAL */;
2513
+ case "BOOLEEN" /* BOOLEAN */:
2514
+ return "BOOLEEN" /* BOOLEAN */;
2515
+ case "CHAINE" /* STRING */:
2516
+ return "CHAINE" /* STRING */;
2517
+ default:
2518
+ return "VIDE" /* VOID */;
2519
+ }
2520
+ }
2521
+ }
2522
+
2523
+ // src/codegen/codegen.ts
2524
+ class CodeGenerator2 {
2525
+ symbolTable;
2526
+ errors = [];
2527
+ indentLevel = 0;
2528
+ constructor(symbolTable, _options) {
2529
+ this.symbolTable = symbolTable;
2530
+ }
2531
+ generate(ast) {
2532
+ try {
2533
+ const output = this.generateJavaScript(ast);
2534
+ return {
2535
+ success: this.errors.length === 0,
2536
+ output,
2537
+ errors: this.errors,
2538
+ warnings: [],
2539
+ symbolTable: this.symbolTable,
2540
+ ast
2541
+ };
2542
+ } catch (error) {
2543
+ return {
2544
+ success: false,
2545
+ output: "",
2546
+ errors: [
2547
+ ...this.errors,
2548
+ {
2549
+ type: "ERROR",
2550
+ message: error instanceof Error ? error.message : "Erreur inconnue lors de la génération de code",
2551
+ line: 0,
2552
+ column: 0,
2553
+ position: 0,
2554
+ code: "GENERATION_ERROR"
2555
+ }
2556
+ ],
2557
+ warnings: []
2558
+ };
2559
+ }
2560
+ }
2561
+ generateJavaScript(ast) {
2562
+ const lines = [];
2563
+ lines.push("// Code généré par AlgoLang");
2564
+ lines.push('import * as readline from "readline";');
2565
+ lines.push("");
2566
+ lines.push("const rl = readline.createInterface({");
2567
+ lines.push(" input: process.stdin,");
2568
+ lines.push(" output: process.stdout");
2569
+ lines.push("});");
2570
+ lines.push("");
2571
+ const programCode = this.generateNode(ast);
2572
+ lines.push(programCode);
2573
+ lines.push("");
2574
+ lines.push("// Fonctions utilitaires pour les entrées/sorties");
2575
+ lines.push("function lire(prompt) {");
2576
+ lines.push(" return new Promise((resolve) => {");
2577
+ lines.push(" rl.question(prompt, (answer) => {");
2578
+ lines.push(" resolve(answer.trim());");
2579
+ lines.push(" });");
2580
+ lines.push(" });");
2581
+ lines.push("}");
2582
+ lines.push("");
2583
+ lines.push("function ecrire(...args) {");
2584
+ lines.push(" console.log(...args);");
2585
+ lines.push("}");
2586
+ lines.push("");
2587
+ lines.push("// Point d'entrée principal");
2588
+ lines.push("main().then(() => {");
2589
+ lines.push(" rl.close();");
2590
+ lines.push("});");
2591
+ return lines.join(`
2592
+ `);
2593
+ }
2594
+ generateNode(node) {
2595
+ switch (node.type) {
2596
+ case "PROGRAM":
2597
+ return this.generateProgram(node);
2598
+ case "BLOCK":
2599
+ return this.generateBlock(node);
2600
+ case "VAR_DECLARATION":
2601
+ return this.generateVariableDeclaration(node);
2602
+ case "COMPOUND_STATEMENT":
2603
+ return this.generateCompoundStatement(node);
2604
+ case "ASSIGNMENT":
2605
+ return this.generateAssignment(node);
2606
+ case "IF_STATEMENT":
2607
+ return this.generateIfStatement(node);
2608
+ case "WHILE_STATEMENT":
2609
+ return this.generateWhileStatement(node);
2610
+ case "FOR_STATEMENT":
2611
+ return this.generateForStatement(node);
2612
+ case "REPEAT_STATEMENT":
2613
+ return this.generateRepeatStatement(node);
2614
+ case "READ_STATEMENT":
2615
+ return this.generateReadStatement(node);
2616
+ case "WRITE_STATEMENT":
2617
+ return this.generateWriteStatement(node);
2618
+ case "BINARY_OP":
2619
+ return this.generateBinaryOp(node);
2620
+ case "UNARY_OP":
2621
+ return this.generateUnaryOp(node);
2622
+ case "LITERAL":
2623
+ return this.generateLiteral(node);
2624
+ case "VARIABLE":
2625
+ return this.generateVariable(node);
2626
+ default:
2627
+ this.errors.push({
2628
+ type: "ERROR",
2629
+ message: `Type de nœud non supporté: ${node.type}`,
2630
+ line: 0,
2631
+ column: 0,
2632
+ position: 0,
2633
+ code: "UNSUPPORTED_NODE_TYPE"
2634
+ });
2635
+ return "";
2636
+ }
2637
+ }
2638
+ generateProgram(node) {
2639
+ const lines = [];
2640
+ lines.push(`// Programme: ${node.value}`);
2641
+ lines.push("async function main() {");
2642
+ this.indentLevel++;
2643
+ if (node.children && node.children.length > 0) {
2644
+ for (const child of node.children) {
2645
+ const childCode = this.generateNode(child);
2646
+ if (childCode) {
2647
+ lines.push(this.indent(childCode));
2648
+ }
2649
+ }
2650
+ }
2651
+ this.indentLevel--;
2652
+ lines.push("}");
2653
+ return lines.join(`
2654
+ `);
2655
+ }
2656
+ generateBlock(node) {
2657
+ const lines = [];
2658
+ if (node.children) {
2659
+ for (const child of node.children) {
2660
+ const childCode = this.generateNode(child);
2661
+ if (childCode) {
2662
+ lines.push(this.indent(childCode));
2663
+ }
2664
+ }
2665
+ }
2666
+ return lines.join(`
2667
+ `);
2668
+ }
2669
+ generateVariableDeclaration(node) {
2670
+ const lines = [];
2671
+ const varType = this.mapAlgoLangTypeToJS(node.value);
2672
+ if (node.children) {
2673
+ const variableNames = node.children.map((child) => child.value).join(", ");
2674
+ lines.push(`let ${variableNames}; // ${varType}`);
2675
+ }
2676
+ return lines.join(`
2677
+ `);
2678
+ }
2679
+ generateCompoundStatement(node) {
2680
+ const lines = [];
2681
+ if (node.children) {
2682
+ for (const child of node.children) {
2683
+ const childCode = this.generateNode(child);
2684
+ if (childCode) {
2685
+ lines.push(this.indent(childCode));
2686
+ }
2687
+ }
2688
+ }
2689
+ return lines.join(`
2690
+ `);
2691
+ }
2692
+ generateAssignment(node) {
2693
+ if (!node.children || node.children.length < 2) {
2694
+ return "";
2695
+ }
2696
+ const variable = node.children[0];
2697
+ const expression = node.children[1];
2698
+ if (!variable || !expression) {
2699
+ return "";
2700
+ }
2701
+ const variableName = variable.value;
2702
+ const expressionCode = this.generateNode(expression);
2703
+ return `${variableName} = ${expressionCode};`;
2704
+ }
2705
+ generateIfStatement(node) {
2706
+ if (!node.children || node.children.length < 2) {
2707
+ return "";
2708
+ }
2709
+ const condition = node.children[0];
2710
+ const thenStatement = node.children[1];
2711
+ const elseStatement = node.children[2];
2712
+ if (!condition || !thenStatement) {
2713
+ return "";
2714
+ }
2715
+ const conditionCode = this.generateNode(condition);
2716
+ const thenCode = this.generateNode(thenStatement);
2717
+ let code = `if (${conditionCode}) {
2718
+ `;
2719
+ this.indentLevel++;
2720
+ code += this.indent(thenCode) + `
2721
+ `;
2722
+ this.indentLevel--;
2723
+ code += "}";
2724
+ if (elseStatement) {
2725
+ const elseCode = this.generateNode(elseStatement);
2726
+ code += ` else {
2727
+ `;
2728
+ this.indentLevel++;
2729
+ code += this.indent(elseCode) + `
2730
+ `;
2731
+ this.indentLevel--;
2732
+ code += "}";
2733
+ }
2734
+ return code;
2735
+ }
2736
+ generateWhileStatement(node) {
2737
+ if (!node.children || node.children.length < 2) {
2738
+ return "";
2739
+ }
2740
+ const condition = node.children[0];
2741
+ const body = node.children[1];
2742
+ if (!condition || !body) {
2743
+ return "";
2744
+ }
2745
+ const conditionCode = this.generateNode(condition);
2746
+ const bodyCode = this.generateNode(body);
2747
+ let code = `while (${conditionCode}) {
2748
+ `;
2749
+ this.indentLevel++;
2750
+ code += this.indent(bodyCode) + `
2751
+ `;
2752
+ this.indentLevel--;
2753
+ code += "}";
2754
+ return code;
2755
+ }
2756
+ generateForStatement(node) {
2757
+ if (!node.children || node.children.length < 4) {
2758
+ return "";
2759
+ }
2760
+ const variable = node.children[0];
2761
+ const startValue = node.children[1];
2762
+ const endValue = node.children[2];
2763
+ const body = node.children[3];
2764
+ if (!variable || !startValue || !endValue || !body) {
2765
+ return "";
2766
+ }
2767
+ const variableName = variable.value;
2768
+ const startCode = this.generateNode(startValue);
2769
+ const endCode = this.generateNode(endValue);
2770
+ const bodyCode = this.generateNode(body);
2771
+ let code = `for (let ${variableName} = ${startCode}; ${variableName} <= ${endCode}; ${variableName}++) {
2772
+ `;
2773
+ this.indentLevel++;
2774
+ code += this.indent(bodyCode) + `
2775
+ `;
2776
+ this.indentLevel--;
2777
+ code += "}";
2778
+ return code;
2779
+ }
2780
+ generateRepeatStatement(node) {
2781
+ if (!node.children || node.children.length < 2) {
2782
+ return "";
2783
+ }
2784
+ const conditionIndex = node.children.length - 1;
2785
+ const condition = node.children[conditionIndex];
2786
+ const bodyStatements = node.children.slice(0, conditionIndex);
2787
+ if (!condition || bodyStatements.length === 0) {
2788
+ return "";
2789
+ }
2790
+ const conditionCode = this.generateNode(condition);
2791
+ let code = `do {
2792
+ `;
2793
+ this.indentLevel++;
2794
+ for (const statement of bodyStatements) {
2795
+ const statementCode = this.generateNode(statement);
2796
+ if (statementCode) {
2797
+ code += this.indent(statementCode) + `
2798
+ `;
2799
+ }
2800
+ }
2801
+ this.indentLevel--;
2802
+ code += "} while (!(" + conditionCode + "));";
2803
+ return code;
2804
+ }
2805
+ generateReadStatement(node) {
2806
+ if (!node.children || node.children.length === 0) {
2807
+ return "";
2808
+ }
2809
+ const variable = node.children[0];
2810
+ if (!variable) {
2811
+ return "";
2812
+ }
2813
+ const variableName = variable.value;
2814
+ const symbolInfo = this.symbolTable.symbols.get(variableName);
2815
+ let conversion = "";
2816
+ if (symbolInfo) {
2817
+ switch (symbolInfo.type) {
2818
+ case "ENTIER":
2819
+ case "REEL":
2820
+ conversion = "parseInt(";
2821
+ break;
2822
+ case "BOOLEEN":
2823
+ conversion = "(";
2824
+ break;
2825
+ default:
2826
+ conversion = "";
2827
+ }
2828
+ }
2829
+ if (conversion) {
2830
+ return `${variableName} = ${conversion}await lire(""));`;
2831
+ } else {
2832
+ return `${variableName} = await lire("");`;
2833
+ }
2834
+ }
2835
+ generateWriteStatement(node) {
2836
+ if (!node.children || node.children.length === 0) {
2837
+ return "";
2838
+ }
2839
+ const expressionCodes = [];
2840
+ for (const child of node.children) {
2841
+ if (child) {
2842
+ const expressionCode = this.generateNode(child);
2843
+ expressionCodes.push(expressionCode);
2844
+ }
2845
+ }
2846
+ if (expressionCodes.length === 1) {
2847
+ return `ecrire(${expressionCodes[0]});`;
2848
+ }
2849
+ const concatenated = expressionCodes.join(", ");
2850
+ return `ecrire(${concatenated});`;
2851
+ }
2852
+ generateBinaryOp(node) {
2853
+ if (!node.children || node.children.length < 2) {
2854
+ return "";
2855
+ }
2856
+ const left = node.children[0];
2857
+ const right = node.children[1];
2858
+ const operator = node.value;
2859
+ if (!left || !right) {
2860
+ return "";
2861
+ }
2862
+ const leftCode = this.generateNode(left);
2863
+ const rightCode = this.generateNode(right);
2864
+ const jsOperator = this.mapOperator(operator);
2865
+ return `(${leftCode} ${jsOperator} ${rightCode})`;
2866
+ }
2867
+ generateUnaryOp(node) {
2868
+ if (!node.children || node.children.length === 0) {
2869
+ return "";
2870
+ }
2871
+ const operand = node.children[0];
2872
+ const operator = node.value;
2873
+ if (!operand) {
2874
+ return "";
2875
+ }
2876
+ const operandCode = this.generateNode(operand);
2877
+ if (operator === "non") {
2878
+ return `!(${operandCode})`;
2879
+ } else if (operator === "-") {
2880
+ return `-${operandCode}`;
2881
+ }
2882
+ return operandCode;
2883
+ }
2884
+ generateLiteral(node) {
2885
+ if (node.value === undefined || node.value === null) {
2886
+ return "null";
2887
+ }
2888
+ if (typeof node.value === "boolean") {
2889
+ return node.value ? "true" : "false";
2890
+ }
2891
+ if (typeof node.value === "number") {
2892
+ return node.value.toString();
2893
+ }
2894
+ if (typeof node.value === "string") {
2895
+ return `"${node.value}"`;
2896
+ }
2897
+ return node.value?.toString() ?? "null";
2898
+ }
2899
+ generateVariable(node) {
2900
+ return node.value;
2901
+ }
2902
+ mapAlgoLangTypeToJS(algoLangType) {
2903
+ switch (algoLangType) {
2904
+ case "ENTIER":
2905
+ return "number";
2906
+ case "REEL":
2907
+ return "number";
2908
+ case "BOOLEEN":
2909
+ return "boolean";
2910
+ case "CHAINE":
2911
+ return "string";
2912
+ default:
2913
+ return "any";
2914
+ }
2915
+ }
2916
+ mapOperator(operator) {
2917
+ switch (operator) {
2918
+ case ":=":
2919
+ return "=";
2920
+ case "=":
2921
+ return "===";
2922
+ case "<>":
2923
+ return "!==";
2924
+ case "<":
2925
+ return "<";
2926
+ case "<=":
2927
+ return "<=";
2928
+ case ">":
2929
+ return ">";
2930
+ case ">=":
2931
+ return ">=";
2932
+ case "et":
2933
+ return "&&";
2934
+ case "ou":
2935
+ return "||";
2936
+ case "non":
2937
+ return "!";
2938
+ default:
2939
+ return operator;
2940
+ }
2941
+ }
2942
+ indent(code) {
2943
+ return " ".repeat(this.indentLevel) + code;
2944
+ }
2945
+ }
2946
+
2947
+ // src/compiler.ts
2948
+ class AlgoLangCompiler {
2949
+ options;
2950
+ constructor(options = {}) {
2951
+ this.options = {
2952
+ target: "javascript",
2953
+ optimizationLevel: 1,
2954
+ debugMode: false,
2955
+ pedagogicalMode: true,
2956
+ ...options
2957
+ };
2958
+ }
2959
+ compile(sourceCode, filePath = "<input>") {
2960
+ const startTime = performance.now();
2961
+ try {
2962
+ const context = {
2963
+ sourceCode,
2964
+ filePath,
2965
+ symbolTable: {
2966
+ symbols: new Map,
2967
+ children: [],
2968
+ scopeName: "global"
2969
+ },
2970
+ currentScope: {
2971
+ symbols: new Map,
2972
+ children: [],
2973
+ scopeName: "global"
2974
+ },
2975
+ errors: [],
2976
+ warnings: []
2977
+ };
2978
+ const lexer = new Lexer2(sourceCode);
2979
+ let tokens;
2980
+ try {
2981
+ tokens = lexer.tokenize();
2982
+ if (this.options.debugMode) {
2983
+ console.log("Tokens générés:", tokens.length);
2984
+ }
2985
+ } catch (error) {
2986
+ return this.createErrorOutput(error instanceof Error ? error.message : "Erreur lors de l'analyse lexicale", context, Date.now() - startTime);
2987
+ }
2988
+ const parser = new Parser2(tokens);
2989
+ let parseResult;
2990
+ try {
2991
+ parseResult = parser.parse();
2992
+ context.symbolTable = parseResult.symbolTable;
2993
+ context.errors.push(...parseResult.errors);
2994
+ if (this.options.debugMode) {
2995
+ console.log("AST généré avec", parseResult.errors.length, "erreurs");
2996
+ }
2997
+ } catch (error) {
2998
+ return this.createErrorOutput(error instanceof Error ? error.message : "Erreur lors de l'analyse syntaxique", context, Date.now() - startTime);
2999
+ }
3000
+ const codeGenerator = new CodeGenerator2(context.symbolTable, this.options);
3001
+ let compiledOutput;
3002
+ try {
3003
+ compiledOutput = codeGenerator.generate(parseResult.ast);
3004
+ context.errors.push(...compiledOutput.errors);
3005
+ context.warnings.push(...compiledOutput.warnings);
3006
+ if (this.options.debugMode) {
3007
+ console.log("Code généré avec succès");
3008
+ }
3009
+ } catch (error) {
3010
+ return this.createErrorOutput(error instanceof Error ? error.message : "Erreur lors de la génération de code", context, Date.now() - startTime);
3011
+ }
3012
+ const finalOutput = this.postProcess(compiledOutput, context);
3013
+ return {
3014
+ ...finalOutput,
3015
+ output: finalOutput.output,
3016
+ errors: context.errors,
3017
+ warnings: context.warnings,
3018
+ symbolTable: context.symbolTable,
3019
+ ast: parseResult.ast,
3020
+ success: context.errors.length === 0,
3021
+ executionTime: performance.now() - startTime
3022
+ };
3023
+ } catch (error) {
3024
+ return this.createErrorOutput(error instanceof Error ? error.message : "Erreur inconnue lors de la compilation", {
3025
+ sourceCode,
3026
+ filePath,
3027
+ symbolTable: {
3028
+ symbols: new Map,
3029
+ children: [],
3030
+ scopeName: "global"
3031
+ },
3032
+ currentScope: {
3033
+ symbols: new Map,
3034
+ children: [],
3035
+ scopeName: "global"
3036
+ },
3037
+ errors: [],
3038
+ warnings: []
3039
+ }, Date.now() - startTime);
3040
+ }
3041
+ }
3042
+ postProcess(output, context) {
3043
+ let processedOutput = output.output;
3044
+ if (this.options.optimizationLevel >= 1) {
3045
+ processedOutput = this.applyBasicOptimizations(processedOutput);
3046
+ }
3047
+ if (this.options.optimizationLevel >= 2) {
3048
+ processedOutput = this.applyAdvancedOptimizations(processedOutput);
3049
+ }
3050
+ if (this.options.optimizationLevel >= 3) {
3051
+ processedOutput = this.applyAggressiveOptimizations(processedOutput);
3052
+ }
3053
+ if (this.options.pedagogicalMode) {
3054
+ processedOutput = this.addPedagogicalComments(processedOutput, context);
3055
+ }
3056
+ return {
3057
+ ...output,
3058
+ output: processedOutput
3059
+ };
3060
+ }
3061
+ applyBasicOptimizations(code) {
3062
+ return code.replace(/\n\s*\n\s*\n/g, `
3063
+
3064
+ `);
3065
+ }
3066
+ applyAdvancedOptimizations(code) {
3067
+ return code;
3068
+ }
3069
+ applyAggressiveOptimizations(code) {
3070
+ return code;
3071
+ }
3072
+ addPedagogicalComments(code, context) {
3073
+ const lines = code.split(`
3074
+ `);
3075
+ const commentedLines = [];
3076
+ commentedLines.push("// ===============================================");
3077
+ commentedLines.push("// Code généré par AlgoLang - Compilateur Éducatif");
3078
+ commentedLines.push("// Fichier source: " + context.filePath);
3079
+ commentedLines.push("// Variables déclarées: " + context.symbolTable.symbols.size);
3080
+ commentedLines.push("// Erreurs de compilation: " + context.errors.length);
3081
+ commentedLines.push("// Avertissements: " + context.warnings.length);
3082
+ commentedLines.push("// ===============================================");
3083
+ commentedLines.push("");
3084
+ for (const line of lines) {
3085
+ commentedLines.push(line);
3086
+ if (line.includes("function main()")) {
3087
+ commentedLines.push("// Point d'entrée principal");
3088
+ } else if (line.includes("let ")) {
3089
+ commentedLines.push("// Déclaration de variable");
3090
+ } else if (line.includes("if (")) {
3091
+ commentedLines.push("// Structure conditionnelle : exécute le code si la condition est vraie");
3092
+ } else if (line.includes("while (")) {
3093
+ commentedLines.push("// Boucle conditionnelle : répète tant que la condition est vraie");
3094
+ } else if (line.includes("for (")) {
3095
+ commentedLines.push("// Boucle itérative : répète pour un nombre défini d'itérations");
3096
+ }
3097
+ }
3098
+ return commentedLines.join(`
3099
+ `);
3100
+ }
3101
+ createErrorOutput(message, context, executionTime) {
3102
+ return {
3103
+ success: false,
3104
+ output: "",
3105
+ errors: [
3106
+ ...context.errors,
3107
+ {
3108
+ type: "ERROR",
3109
+ message,
3110
+ line: 0,
3111
+ column: 0,
3112
+ position: 0,
3113
+ code: "COMPILATION_ERROR"
3114
+ }
3115
+ ],
3116
+ warnings: context.warnings,
3117
+ executionTime
3118
+ };
3119
+ }
3120
+ validateSyntax(sourceCode) {
3121
+ try {
3122
+ const lexer = new Lexer2(sourceCode);
3123
+ const tokens = lexer.tokenize();
3124
+ const parser = new Parser2(tokens);
3125
+ const result = parser.parse();
3126
+ return {
3127
+ valid: result.errors.length === 0,
3128
+ errors: result.errors
3129
+ };
3130
+ } catch (error) {
3131
+ return {
3132
+ valid: false,
3133
+ errors: [
3134
+ {
3135
+ type: "ERROR",
3136
+ message: error instanceof Error ? error.message : "Erreur de syntaxe inconnue",
3137
+ line: 0,
3138
+ column: 0,
3139
+ position: 0,
3140
+ code: "SYNTAX_ERROR"
3141
+ }
3142
+ ]
3143
+ };
3144
+ }
3145
+ }
3146
+ getSymbolTable(sourceCode) {
3147
+ try {
3148
+ const lexer = new Lexer2(sourceCode);
3149
+ const tokens = lexer.tokenize();
3150
+ const parser = new Parser2(tokens);
3151
+ const result = parser.parse();
3152
+ return result.symbolTable;
3153
+ } catch (error) {
3154
+ return {
3155
+ symbols: new Map,
3156
+ children: [],
3157
+ scopeName: "global"
3158
+ };
3159
+ }
3160
+ }
3161
+ formatError(error) {
3162
+ let formatted = `❌ Erreur [${error.code}]: ${error.message}`;
3163
+ if (error.line > 0) {
3164
+ formatted += ` (ligne ${error.line}`;
3165
+ if (error.column > 0) {
3166
+ formatted += `, colonne ${error.column}`;
3167
+ }
3168
+ formatted += ")";
3169
+ }
3170
+ if (this.options.pedagogicalMode && error.explanation) {
3171
+ formatted += `
3172
+
3173
+ \uD83D\uDCA1 Explication: ${error.explanation}`;
3174
+ }
3175
+ if (this.options.pedagogicalMode && error.suggestion) {
3176
+ formatted += `
3177
+
3178
+ \uD83D\uDD27 Suggestion: ${error.suggestion}`;
3179
+ }
3180
+ return formatted;
3181
+ }
3182
+ }
3183
+ // src/types/index.ts
3184
+ var TokenType2;
3185
+ ((TokenType3) => {
3186
+ TokenType3["PROGRAM"] = "PROGRAMME";
3187
+ TokenType3["BEGIN"] = "DEBUT";
3188
+ TokenType3["END"] = "FIN";
3189
+ TokenType3["VAR"] = "VAR";
3190
+ TokenType3["INTEGER"] = "ENTIER";
3191
+ TokenType3["REAL"] = "REEL";
3192
+ TokenType3["BOOLEAN"] = "BOOLEEN";
3193
+ TokenType3["STRING"] = "CHAINE";
3194
+ TokenType3["IF"] = "SI";
3195
+ TokenType3["THEN"] = "ALORS";
3196
+ TokenType3["ELSE"] = "SINON";
3197
+ TokenType3["WHILE"] = "TANTQUE";
3198
+ TokenType3["DO"] = "FAIRE";
3199
+ TokenType3["FOR"] = "POUR";
3200
+ TokenType3["ALLANT"] = "ALLANT";
3201
+ TokenType3["DE"] = "DE";
3202
+ TokenType3["TO"] = "A";
3203
+ TokenType3["REPEAT"] = "REPETER";
3204
+ TokenType3["UNTIL"] = "JUSQUA";
3205
+ TokenType3["READ"] = "LIRE";
3206
+ TokenType3["WRITE"] = "ECRIRE";
3207
+ TokenType3["TRUE"] = "VRAI";
3208
+ TokenType3["FALSE"] = "FAUX";
3209
+ TokenType3["AND"] = "ET";
3210
+ TokenType3["OR"] = "OU";
3211
+ TokenType3["NOT"] = "NON";
3212
+ TokenType3["ENDFOR"] = "FINPOUR";
3213
+ TokenType3["ENDIF"] = "FINIF";
3214
+ TokenType3["ENDWHILE"] = "FINTANTQUE";
3215
+ TokenType3["PLUS"] = "PLUS";
3216
+ TokenType3["MINUS"] = "MINUS";
3217
+ TokenType3["MULTIPLY"] = "MULTIPLY";
3218
+ TokenType3["DIVIDE"] = "DIVIDE";
3219
+ TokenType3["ASSIGN"] = "ASSIGN";
3220
+ TokenType3["EQUAL"] = "EQUAL";
3221
+ TokenType3["NOT_EQUAL"] = "NOT_EQUAL";
3222
+ TokenType3["LESS_THAN"] = "LESS_THAN";
3223
+ TokenType3["LESS_EQUAL"] = "LESS_EQUAL";
3224
+ TokenType3["GREATER_THAN"] = "GREATER_THAN";
3225
+ TokenType3["GREATER_EQUAL"] = "GREATER_EQUAL";
3226
+ TokenType3["SEMICOLON"] = "SEMICOLON";
3227
+ TokenType3["COLON"] = "COLON";
3228
+ TokenType3["COMMA"] = "COMMA";
3229
+ TokenType3["DOT"] = "DOT";
3230
+ TokenType3["LEFT_PAREN"] = "LEFT_PAREN";
3231
+ TokenType3["RIGHT_PAREN"] = "RIGHT_PAREN";
3232
+ TokenType3["NUMBER"] = "NUMBER";
3233
+ TokenType3["IDENTIFIER"] = "IDENTIFIER";
3234
+ TokenType3["STRING_LITERAL"] = "STRING_LITERAL";
3235
+ TokenType3["EOF"] = "EOF";
3236
+ TokenType3["NEWLINE"] = "NEWLINE";
3237
+ TokenType3["COMMENT"] = "COMMENT";
3238
+ })(TokenType2 ||= {});
3239
+ var NodeType2;
3240
+ ((NodeType3) => {
3241
+ NodeType3["PROGRAM"] = "PROGRAM";
3242
+ NodeType3["VAR_DECLARATION"] = "VAR_DECLARATION";
3243
+ NodeType3["TYPE_SPECIFIER"] = "TYPE_SPECIFIER";
3244
+ NodeType3["ASSIGNMENT"] = "ASSIGNMENT";
3245
+ NodeType3["IF_STATEMENT"] = "IF_STATEMENT";
3246
+ NodeType3["WHILE_STATEMENT"] = "WHILE_STATEMENT";
3247
+ NodeType3["FOR_STATEMENT"] = "FOR_STATEMENT";
3248
+ NodeType3["REPEAT_STATEMENT"] = "REPEAT_STATEMENT";
3249
+ NodeType3["READ_STATEMENT"] = "READ_STATEMENT";
3250
+ NodeType3["WRITE_STATEMENT"] = "WRITE_STATEMENT";
3251
+ NodeType3["COMPOUND_STATEMENT"] = "COMPOUND_STATEMENT";
3252
+ NodeType3["BINARY_OP"] = "BINARY_OP";
3253
+ NodeType3["UNARY_OP"] = "UNARY_OP";
3254
+ NodeType3["LITERAL"] = "LITERAL";
3255
+ NodeType3["VARIABLE"] = "VARIABLE";
3256
+ NodeType3["BLOCK"] = "BLOCK";
3257
+ NodeType3["PARAMETER_LIST"] = "PARAMETER_LIST";
3258
+ })(NodeType2 ||= {});
3259
+ var DataType2;
3260
+ ((DataType3) => {
3261
+ DataType3["INTEGER"] = "ENTIER";
3262
+ DataType3["REAL"] = "REEL";
3263
+ DataType3["BOOLEAN"] = "BOOLEEN";
3264
+ DataType3["STRING"] = "CHAINE";
3265
+ DataType3["VOID"] = "VIDE";
3266
+ })(DataType2 ||= {});
3267
+ export {
3268
+ TokenType2 as TokenType,
3269
+ Parser,
3270
+ NodeType2 as NodeType,
3271
+ Lexer,
3272
+ DataType2 as DataType,
3273
+ CodeGenerator,
3274
+ AlgoLangCompiler
3275
+ };