@devalade/algolang 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +41 -26
- package/dist/index.js +83 -52
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2893,6 +2893,7 @@ var KEYWORDS = {
|
|
|
2893
2893
|
documentation: "**reel_en_entier(x)** : Convertit un réel en entier (troncature)."
|
|
2894
2894
|
}
|
|
2895
2895
|
};
|
|
2896
|
+
var BUILTIN_NAMES = new Set(Object.entries(KEYWORDS).filter(([, e]) => e.tokenType === null).map(([label]) => label));
|
|
2896
2897
|
|
|
2897
2898
|
// src/lexer/lexer.ts
|
|
2898
2899
|
class Lexer {
|
|
@@ -3221,22 +3222,12 @@ class SemanticAnalyzer {
|
|
|
3221
3222
|
const algoType = node.value;
|
|
3222
3223
|
const line = node.token?.line ?? 0;
|
|
3223
3224
|
const column = node.token?.column ?? 0;
|
|
3225
|
+
const position = node.token?.position ?? 0;
|
|
3224
3226
|
for (const child of node.children ?? []) {
|
|
3225
3227
|
if (child.type !== "VARIABLE" /* VARIABLE */)
|
|
3226
3228
|
continue;
|
|
3227
3229
|
const name = child.value;
|
|
3228
|
-
if (this.
|
|
3229
|
-
this.errors.push({
|
|
3230
|
-
type: "ERROR",
|
|
3231
|
-
message: `La variable '${name}' est déjà déclarée`,
|
|
3232
|
-
line,
|
|
3233
|
-
column,
|
|
3234
|
-
position: node.token?.position ?? 0,
|
|
3235
|
-
code: "DUPLICATE_VARIABLE",
|
|
3236
|
-
explanation: "Chaque variable doit avoir un nom unique dans son scope",
|
|
3237
|
-
suggestion: `Choisissez un autre nom pour la variable '${name}'`
|
|
3238
|
-
});
|
|
3239
|
-
} else {
|
|
3230
|
+
if (this.validateName(name, line, column, position)) {
|
|
3240
3231
|
this.defineSymbol(name, algoType, line, column);
|
|
3241
3232
|
}
|
|
3242
3233
|
}
|
|
@@ -3248,26 +3239,45 @@ class SemanticAnalyzer {
|
|
|
3248
3239
|
const typeLabel = `TABLEAU[${size}] DE ${elemType}`;
|
|
3249
3240
|
const line = node.token?.line ?? 0;
|
|
3250
3241
|
const column = node.token?.column ?? 0;
|
|
3242
|
+
const position = node.token?.position ?? 0;
|
|
3251
3243
|
for (const child of (node.children ?? []).slice(1)) {
|
|
3252
3244
|
if (child.type !== "VARIABLE" /* VARIABLE */)
|
|
3253
3245
|
continue;
|
|
3254
3246
|
const name = child.value;
|
|
3255
|
-
if (this.
|
|
3256
|
-
this.errors.push({
|
|
3257
|
-
type: "ERROR",
|
|
3258
|
-
message: `La variable '${name}' est déjà déclarée`,
|
|
3259
|
-
line,
|
|
3260
|
-
column,
|
|
3261
|
-
position: node.token?.position ?? 0,
|
|
3262
|
-
code: "DUPLICATE_VARIABLE",
|
|
3263
|
-
explanation: "Chaque variable doit avoir un nom unique dans son scope",
|
|
3264
|
-
suggestion: `Choisissez un autre nom pour la variable '${name}'`
|
|
3265
|
-
});
|
|
3266
|
-
} else {
|
|
3247
|
+
if (this.validateName(name, line, column, position)) {
|
|
3267
3248
|
this.defineSymbol(name, typeLabel, line, column);
|
|
3268
3249
|
}
|
|
3269
3250
|
}
|
|
3270
3251
|
}
|
|
3252
|
+
validateName(name, line, column, position) {
|
|
3253
|
+
if (BUILTIN_NAMES.has(name)) {
|
|
3254
|
+
this.errors.push({
|
|
3255
|
+
type: "ERROR",
|
|
3256
|
+
message: `Le nom '${name}' est une fonction intégrée et ne peut pas être utilisé comme nom de variable`,
|
|
3257
|
+
line,
|
|
3258
|
+
column,
|
|
3259
|
+
position,
|
|
3260
|
+
code: "BUILTIN_SHADOWING",
|
|
3261
|
+
explanation: `'${name}' est une fonction intégrée d'AlgoLang`,
|
|
3262
|
+
suggestion: `Choisissez un autre nom, par exemple '${name}Valeur' ou 'mon${name.charAt(0).toUpperCase()}${name.slice(1)}'`
|
|
3263
|
+
});
|
|
3264
|
+
return false;
|
|
3265
|
+
}
|
|
3266
|
+
if (this.symbolTable.symbols.has(name)) {
|
|
3267
|
+
this.errors.push({
|
|
3268
|
+
type: "ERROR",
|
|
3269
|
+
message: `La variable '${name}' est déjà déclarée`,
|
|
3270
|
+
line,
|
|
3271
|
+
column,
|
|
3272
|
+
position,
|
|
3273
|
+
code: "DUPLICATE_VARIABLE",
|
|
3274
|
+
explanation: "Chaque variable doit avoir un nom unique dans son scope",
|
|
3275
|
+
suggestion: `Choisissez un autre nom pour la variable '${name}'`
|
|
3276
|
+
});
|
|
3277
|
+
return false;
|
|
3278
|
+
}
|
|
3279
|
+
return true;
|
|
3280
|
+
}
|
|
3271
3281
|
defineSymbol(name, type, line, column) {
|
|
3272
3282
|
const info = {
|
|
3273
3283
|
name,
|
|
@@ -4228,7 +4238,12 @@ class CodeGenerator {
|
|
|
4228
4238
|
lines.push(`// Programme: ${node.value}`);
|
|
4229
4239
|
if (block?.children) {
|
|
4230
4240
|
for (const child of block.children) {
|
|
4231
|
-
if (child.type === "
|
|
4241
|
+
if (child.type === "BLOCK") {
|
|
4242
|
+
for (const decl of child.children ?? []) {
|
|
4243
|
+
lines.push(this.generateNode(decl));
|
|
4244
|
+
}
|
|
4245
|
+
lines.push("");
|
|
4246
|
+
} else if (child.type === "FUNCTION_DECLARATION" || child.type === "PROCEDURE_DECLARATION") {
|
|
4232
4247
|
lines.push(this.generateNode(child));
|
|
4233
4248
|
lines.push("");
|
|
4234
4249
|
}
|
|
@@ -4238,7 +4253,7 @@ class CodeGenerator {
|
|
|
4238
4253
|
this.indentLevel++;
|
|
4239
4254
|
if (block?.children) {
|
|
4240
4255
|
for (const child of block.children) {
|
|
4241
|
-
if (child.type !== "FUNCTION_DECLARATION" && child.type !== "PROCEDURE_DECLARATION") {
|
|
4256
|
+
if (child.type !== "BLOCK" && child.type !== "FUNCTION_DECLARATION" && child.type !== "PROCEDURE_DECLARATION") {
|
|
4242
4257
|
const childCode = this.generateNode(child);
|
|
4243
4258
|
if (childCode) {
|
|
4244
4259
|
lines.push(this.indent(childCode));
|
package/dist/index.js
CHANGED
|
@@ -262,6 +262,7 @@ var KEYWORDS = {
|
|
|
262
262
|
documentation: "**reel_en_entier(x)** : Convertit un réel en entier (troncature)."
|
|
263
263
|
}
|
|
264
264
|
};
|
|
265
|
+
var BUILTIN_NAMES = new Set(Object.entries(KEYWORDS).filter(([, e]) => e.tokenType === null).map(([label]) => label));
|
|
265
266
|
|
|
266
267
|
// src/lexer/lexer.ts
|
|
267
268
|
class Lexer {
|
|
@@ -589,22 +590,12 @@ class SemanticAnalyzer {
|
|
|
589
590
|
const algoType = node.value;
|
|
590
591
|
const line = node.token?.line ?? 0;
|
|
591
592
|
const column = node.token?.column ?? 0;
|
|
593
|
+
const position = node.token?.position ?? 0;
|
|
592
594
|
for (const child of node.children ?? []) {
|
|
593
595
|
if (child.type !== "VARIABLE" /* VARIABLE */)
|
|
594
596
|
continue;
|
|
595
597
|
const name = child.value;
|
|
596
|
-
if (this.
|
|
597
|
-
this.errors.push({
|
|
598
|
-
type: "ERROR",
|
|
599
|
-
message: `La variable '${name}' est déjà déclarée`,
|
|
600
|
-
line,
|
|
601
|
-
column,
|
|
602
|
-
position: node.token?.position ?? 0,
|
|
603
|
-
code: "DUPLICATE_VARIABLE",
|
|
604
|
-
explanation: "Chaque variable doit avoir un nom unique dans son scope",
|
|
605
|
-
suggestion: `Choisissez un autre nom pour la variable '${name}'`
|
|
606
|
-
});
|
|
607
|
-
} else {
|
|
598
|
+
if (this.validateName(name, line, column, position)) {
|
|
608
599
|
this.defineSymbol(name, algoType, line, column);
|
|
609
600
|
}
|
|
610
601
|
}
|
|
@@ -616,26 +607,45 @@ class SemanticAnalyzer {
|
|
|
616
607
|
const typeLabel = `TABLEAU[${size}] DE ${elemType}`;
|
|
617
608
|
const line = node.token?.line ?? 0;
|
|
618
609
|
const column = node.token?.column ?? 0;
|
|
610
|
+
const position = node.token?.position ?? 0;
|
|
619
611
|
for (const child of (node.children ?? []).slice(1)) {
|
|
620
612
|
if (child.type !== "VARIABLE" /* VARIABLE */)
|
|
621
613
|
continue;
|
|
622
614
|
const name = child.value;
|
|
623
|
-
if (this.
|
|
624
|
-
this.errors.push({
|
|
625
|
-
type: "ERROR",
|
|
626
|
-
message: `La variable '${name}' est déjà déclarée`,
|
|
627
|
-
line,
|
|
628
|
-
column,
|
|
629
|
-
position: node.token?.position ?? 0,
|
|
630
|
-
code: "DUPLICATE_VARIABLE",
|
|
631
|
-
explanation: "Chaque variable doit avoir un nom unique dans son scope",
|
|
632
|
-
suggestion: `Choisissez un autre nom pour la variable '${name}'`
|
|
633
|
-
});
|
|
634
|
-
} else {
|
|
615
|
+
if (this.validateName(name, line, column, position)) {
|
|
635
616
|
this.defineSymbol(name, typeLabel, line, column);
|
|
636
617
|
}
|
|
637
618
|
}
|
|
638
619
|
}
|
|
620
|
+
validateName(name, line, column, position) {
|
|
621
|
+
if (BUILTIN_NAMES.has(name)) {
|
|
622
|
+
this.errors.push({
|
|
623
|
+
type: "ERROR",
|
|
624
|
+
message: `Le nom '${name}' est une fonction intégrée et ne peut pas être utilisé comme nom de variable`,
|
|
625
|
+
line,
|
|
626
|
+
column,
|
|
627
|
+
position,
|
|
628
|
+
code: "BUILTIN_SHADOWING",
|
|
629
|
+
explanation: `'${name}' est une fonction intégrée d'AlgoLang`,
|
|
630
|
+
suggestion: `Choisissez un autre nom, par exemple '${name}Valeur' ou 'mon${name.charAt(0).toUpperCase()}${name.slice(1)}'`
|
|
631
|
+
});
|
|
632
|
+
return false;
|
|
633
|
+
}
|
|
634
|
+
if (this.symbolTable.symbols.has(name)) {
|
|
635
|
+
this.errors.push({
|
|
636
|
+
type: "ERROR",
|
|
637
|
+
message: `La variable '${name}' est déjà déclarée`,
|
|
638
|
+
line,
|
|
639
|
+
column,
|
|
640
|
+
position,
|
|
641
|
+
code: "DUPLICATE_VARIABLE",
|
|
642
|
+
explanation: "Chaque variable doit avoir un nom unique dans son scope",
|
|
643
|
+
suggestion: `Choisissez un autre nom pour la variable '${name}'`
|
|
644
|
+
});
|
|
645
|
+
return false;
|
|
646
|
+
}
|
|
647
|
+
return true;
|
|
648
|
+
}
|
|
639
649
|
defineSymbol(name, type, line, column) {
|
|
640
650
|
const info = {
|
|
641
651
|
name,
|
|
@@ -1595,7 +1605,12 @@ class CodeGenerator {
|
|
|
1595
1605
|
lines.push(`// Programme: ${node.value}`);
|
|
1596
1606
|
if (block?.children) {
|
|
1597
1607
|
for (const child of block.children) {
|
|
1598
|
-
if (child.type === "
|
|
1608
|
+
if (child.type === "BLOCK") {
|
|
1609
|
+
for (const decl of child.children ?? []) {
|
|
1610
|
+
lines.push(this.generateNode(decl));
|
|
1611
|
+
}
|
|
1612
|
+
lines.push("");
|
|
1613
|
+
} else if (child.type === "FUNCTION_DECLARATION" || child.type === "PROCEDURE_DECLARATION") {
|
|
1599
1614
|
lines.push(this.generateNode(child));
|
|
1600
1615
|
lines.push("");
|
|
1601
1616
|
}
|
|
@@ -1605,7 +1620,7 @@ class CodeGenerator {
|
|
|
1605
1620
|
this.indentLevel++;
|
|
1606
1621
|
if (block?.children) {
|
|
1607
1622
|
for (const child of block.children) {
|
|
1608
|
-
if (child.type !== "FUNCTION_DECLARATION" && child.type !== "PROCEDURE_DECLARATION") {
|
|
1623
|
+
if (child.type !== "BLOCK" && child.type !== "FUNCTION_DECLARATION" && child.type !== "PROCEDURE_DECLARATION") {
|
|
1609
1624
|
const childCode = this.generateNode(child);
|
|
1610
1625
|
if (childCode) {
|
|
1611
1626
|
lines.push(this.indent(childCode));
|
|
@@ -3235,7 +3250,12 @@ class CodeGenerator2 {
|
|
|
3235
3250
|
lines.push(`// Programme: ${node.value}`);
|
|
3236
3251
|
if (block?.children) {
|
|
3237
3252
|
for (const child of block.children) {
|
|
3238
|
-
if (child.type === "
|
|
3253
|
+
if (child.type === "BLOCK") {
|
|
3254
|
+
for (const decl of child.children ?? []) {
|
|
3255
|
+
lines.push(this.generateNode(decl));
|
|
3256
|
+
}
|
|
3257
|
+
lines.push("");
|
|
3258
|
+
} else if (child.type === "FUNCTION_DECLARATION" || child.type === "PROCEDURE_DECLARATION") {
|
|
3239
3259
|
lines.push(this.generateNode(child));
|
|
3240
3260
|
lines.push("");
|
|
3241
3261
|
}
|
|
@@ -3245,7 +3265,7 @@ class CodeGenerator2 {
|
|
|
3245
3265
|
this.indentLevel++;
|
|
3246
3266
|
if (block?.children) {
|
|
3247
3267
|
for (const child of block.children) {
|
|
3248
|
-
if (child.type !== "FUNCTION_DECLARATION" && child.type !== "PROCEDURE_DECLARATION") {
|
|
3268
|
+
if (child.type !== "BLOCK" && child.type !== "FUNCTION_DECLARATION" && child.type !== "PROCEDURE_DECLARATION") {
|
|
3249
3269
|
const childCode = this.generateNode(child);
|
|
3250
3270
|
if (childCode) {
|
|
3251
3271
|
lines.push(this.indent(childCode));
|
|
@@ -4225,6 +4245,7 @@ var KEYWORDS2 = {
|
|
|
4225
4245
|
documentation: "**reel_en_entier(x)** : Convertit un réel en entier (troncature)."
|
|
4226
4246
|
}
|
|
4227
4247
|
};
|
|
4248
|
+
var BUILTIN_NAMES2 = new Set(Object.entries(KEYWORDS2).filter(([, e]) => e.tokenType === null).map(([label]) => label));
|
|
4228
4249
|
// src/semantic/semantic-analyzer.ts
|
|
4229
4250
|
class SemanticAnalyzer2 {
|
|
4230
4251
|
symbolTable = {
|
|
@@ -4254,22 +4275,12 @@ class SemanticAnalyzer2 {
|
|
|
4254
4275
|
const algoType = node.value;
|
|
4255
4276
|
const line = node.token?.line ?? 0;
|
|
4256
4277
|
const column = node.token?.column ?? 0;
|
|
4278
|
+
const position = node.token?.position ?? 0;
|
|
4257
4279
|
for (const child of node.children ?? []) {
|
|
4258
4280
|
if (child.type !== "VARIABLE" /* VARIABLE */)
|
|
4259
4281
|
continue;
|
|
4260
4282
|
const name = child.value;
|
|
4261
|
-
if (this.
|
|
4262
|
-
this.errors.push({
|
|
4263
|
-
type: "ERROR",
|
|
4264
|
-
message: `La variable '${name}' est déjà déclarée`,
|
|
4265
|
-
line,
|
|
4266
|
-
column,
|
|
4267
|
-
position: node.token?.position ?? 0,
|
|
4268
|
-
code: "DUPLICATE_VARIABLE",
|
|
4269
|
-
explanation: "Chaque variable doit avoir un nom unique dans son scope",
|
|
4270
|
-
suggestion: `Choisissez un autre nom pour la variable '${name}'`
|
|
4271
|
-
});
|
|
4272
|
-
} else {
|
|
4283
|
+
if (this.validateName(name, line, column, position)) {
|
|
4273
4284
|
this.defineSymbol(name, algoType, line, column);
|
|
4274
4285
|
}
|
|
4275
4286
|
}
|
|
@@ -4281,26 +4292,45 @@ class SemanticAnalyzer2 {
|
|
|
4281
4292
|
const typeLabel = `TABLEAU[${size}] DE ${elemType}`;
|
|
4282
4293
|
const line = node.token?.line ?? 0;
|
|
4283
4294
|
const column = node.token?.column ?? 0;
|
|
4295
|
+
const position = node.token?.position ?? 0;
|
|
4284
4296
|
for (const child of (node.children ?? []).slice(1)) {
|
|
4285
4297
|
if (child.type !== "VARIABLE" /* VARIABLE */)
|
|
4286
4298
|
continue;
|
|
4287
4299
|
const name = child.value;
|
|
4288
|
-
if (this.
|
|
4289
|
-
this.errors.push({
|
|
4290
|
-
type: "ERROR",
|
|
4291
|
-
message: `La variable '${name}' est déjà déclarée`,
|
|
4292
|
-
line,
|
|
4293
|
-
column,
|
|
4294
|
-
position: node.token?.position ?? 0,
|
|
4295
|
-
code: "DUPLICATE_VARIABLE",
|
|
4296
|
-
explanation: "Chaque variable doit avoir un nom unique dans son scope",
|
|
4297
|
-
suggestion: `Choisissez un autre nom pour la variable '${name}'`
|
|
4298
|
-
});
|
|
4299
|
-
} else {
|
|
4300
|
+
if (this.validateName(name, line, column, position)) {
|
|
4300
4301
|
this.defineSymbol(name, typeLabel, line, column);
|
|
4301
4302
|
}
|
|
4302
4303
|
}
|
|
4303
4304
|
}
|
|
4305
|
+
validateName(name, line, column, position) {
|
|
4306
|
+
if (BUILTIN_NAMES.has(name)) {
|
|
4307
|
+
this.errors.push({
|
|
4308
|
+
type: "ERROR",
|
|
4309
|
+
message: `Le nom '${name}' est une fonction intégrée et ne peut pas être utilisé comme nom de variable`,
|
|
4310
|
+
line,
|
|
4311
|
+
column,
|
|
4312
|
+
position,
|
|
4313
|
+
code: "BUILTIN_SHADOWING",
|
|
4314
|
+
explanation: `'${name}' est une fonction intégrée d'AlgoLang`,
|
|
4315
|
+
suggestion: `Choisissez un autre nom, par exemple '${name}Valeur' ou 'mon${name.charAt(0).toUpperCase()}${name.slice(1)}'`
|
|
4316
|
+
});
|
|
4317
|
+
return false;
|
|
4318
|
+
}
|
|
4319
|
+
if (this.symbolTable.symbols.has(name)) {
|
|
4320
|
+
this.errors.push({
|
|
4321
|
+
type: "ERROR",
|
|
4322
|
+
message: `La variable '${name}' est déjà déclarée`,
|
|
4323
|
+
line,
|
|
4324
|
+
column,
|
|
4325
|
+
position,
|
|
4326
|
+
code: "DUPLICATE_VARIABLE",
|
|
4327
|
+
explanation: "Chaque variable doit avoir un nom unique dans son scope",
|
|
4328
|
+
suggestion: `Choisissez un autre nom pour la variable '${name}'`
|
|
4329
|
+
});
|
|
4330
|
+
return false;
|
|
4331
|
+
}
|
|
4332
|
+
return true;
|
|
4333
|
+
}
|
|
4304
4334
|
defineSymbol(name, type, line, column) {
|
|
4305
4335
|
const info = {
|
|
4306
4336
|
name,
|
|
@@ -4321,5 +4351,6 @@ export {
|
|
|
4321
4351
|
KEYWORDS2 as KEYWORDS,
|
|
4322
4352
|
DataType2 as DataType,
|
|
4323
4353
|
CodeGenerator,
|
|
4354
|
+
BUILTIN_NAMES2 as BUILTIN_NAMES,
|
|
4324
4355
|
AlgoLangCompiler
|
|
4325
4356
|
};
|