@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.
Files changed (3) hide show
  1. package/dist/cli.js +41 -26
  2. package/dist/index.js +83 -52
  3. 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.symbolTable.symbols.has(name)) {
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.symbolTable.symbols.has(name)) {
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 === "FUNCTION_DECLARATION" || child.type === "PROCEDURE_DECLARATION") {
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.symbolTable.symbols.has(name)) {
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.symbolTable.symbols.has(name)) {
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 === "FUNCTION_DECLARATION" || child.type === "PROCEDURE_DECLARATION") {
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 === "FUNCTION_DECLARATION" || child.type === "PROCEDURE_DECLARATION") {
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.symbolTable.symbols.has(name)) {
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.symbolTable.symbols.has(name)) {
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
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devalade/algolang",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "Compilateur AlgoLang — langage de programmation éducatif pour l'algorithmique",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",