Réponse au prompt “Décris-moi les étapes pour que ce programme accepte le mot-clé REPETE (comme dans prog2.logo)”

ChatGPT

26 mai 2026

Le fichier prog2.logo utilise une construction Logo classique :

L’objectif est donc d’exécuter plusieurs fois un bloc d’instructions délimité par [ et ].


1 Ce qui existe déjà

Le lexer reconnaît déjà :

char const kwRepeat[] = "repete";

et les caractères :

[]

sont déjà transformés en tokens :

TokenSign

Le travail restant concerne donc essentiellement :

  1. le parseur (Program)
  2. une nouvelle instruction Repeat
  3. la gestion de l’exécution de cette instruction

2 Étape 1 : définir le comportement attendu

Pour :

on veut obtenir :

avance 10
droite 90

avance 10
droite 90

avance 10
droite 90

Le bloc entre [ et ] doit être exécuté plusieurs fois.


3 Étape 2 : créer une nouvelle classe Repeat

Comme les autres instructions :

Instruction
│
├── Move
├── Turn
├── SetPenPos
├── FunctionCall
└── Repeat

Par exemple :

class Repeat : public Instruction
{
public:
    Repeat(...);

private:
    virtual void doExecute(Interpreter&) const override;
    virtual void doDisplay(std::ostream&) const override;
};

4 Étape 3 : représenter le corps de la boucle

Le plus simple est que Repeat contienne un sous-programme :

class Repeat : public Instruction
{
    int myCount;

    std::unique_ptr<Program> myBody;
};

Ainsi :

produit :

Repeat
 ├─ count = 6
 └─ Program
      ├─ Move(40)
      └─ Turn(60)

5 Étape 4 : modifier le parseur

Actuellement :

Program::parseKeyword(...)

gère :

avance
recule
droite
gauche
leve
baisse
pour
fin

Il faut ajouter :

else if (token->second == kwRepeat)
{
    myInstructions.push_back(
        std::make_unique<Repeat>(tokens, ++token, mainProgram)
    );
}

6 Étape 5 : analyser la syntaxe REPETE

Dans le constructeur de Repeat :

on doit lire :

6.0.1 le nombre de répétitions

6

puis vérifier :

[

ensuite construire le sous-programme.


Par exemple :

if(token->first != TokenNumber)
    throw ParseError(...);

myCount = std::stoi(token->second);

++token;

Puis :

if(token->second != "[")
    throw ParseError(...);

++token;

7 Étape 6 : parser le contenu du bloc

Le plus gros travail est ici.

Actuellement un Program se termine sur :

fin

mais un bloc REPETE doit se terminer sur :

]

Il faut donc permettre à Program d’être construit avec un délimiteur de fin.

Par exemple :

enum class ProgramEnd
{
    EndKeyword,
    ClosingBracket
};

Puis :

Program(tokens,currentToken,mainProgram,
        ProgramEnd::ClosingBracket);

Ainsi :

sera analysé exactement comme un programme normal.


8 Étape 7 : gérer l’exécution

C’est la partie la plus délicate.

Aujourd’hui la pile d’appels contient :

Main
└─ Fonction

Pour une boucle il faut quelque chose comme :

Main
└─ Repeat
     itération 1
     itération 2
     ...

8.1 Solution simple (recommandée pour un projet étudiant)

Ne pas modifier l’interpréteur.

Au moment du parsing :

on génère directement :

Move(40)
Turn(60)

Move(40)
Turn(60)

Move(40)
Turn(60)

Move(40)
Turn(60)

Move(40)
Turn(60)

Move(40)
Turn(60)

Autrement dit :

8.1.1 on déroule la boucle à la compilation

C’est ce qu’on appelle du loop unrolling.

Avantages :

Pour un projet de deuxième année, c’est probablement la meilleure stratégie.


9 Étape 8 : solution plus élégante

Un vrai interpréteur ferait :

Repeat
{
    int count;
    Program body;
}

et l’exécution pousserait un contexte spécial :

RepeatContext
{
    compteurCourant;
    compteurMax;
}

Mais cela oblige à :

C’est beaucoup plus invasif.


10 Plan de développement conseillé

Ordre des travaux :

10.0.1 Version minimale

  1. Créer Repeat.h/.cpp
  2. Ajouter le cas kwRepeat dans Program::parseKeyword()
  3. Lire :
  1. Dérouler la boucle lors du parsing

Exemple :

devient en mémoire :

Move(10)
Move(10)
Move(10)

Cette version permet déjà d’exécuter correctement votre prog2.logo sans toucher à l’interpréteur.

10.0.2 Version avancée

  1. Introduire un véritable objet Repeat
  2. Ajouter un contexte d’exécution de boucle
  3. Supporter des boucles imbriquées

C’est la solution qu’on attendrait plutôt dans un interpréteur industriel.