Partage
  • Partager sur Facebook
  • Partager sur Twitter

C : Utiliser parsing pour créer un intérpreteur

    26 septembre 2021 à 12:48:47

    Bonjour tout le monde.

    J'ai créé des types liste en C avec toutes les primitives pour les manipuler.

    Il faut maintenant que je créés un mini interpreteur (dans mon main), ce dernier attends des commandes qui peuvent être sous les formes suivantes :

    > L = (a b c d e)  // cela crééer une liste L avec les éléments a,b,c,d,e puis l'affiche

    (a b c d e)

    > L //affiche la liste L

    (a b c d e)

    > cdr(L) //affiche la liste L sans son premier élément

    (b c d e)


    > LL = cons (e L)  // créér une copie de L appellée LL puis rajoute l'élement e en première position

    (e a b c d e)

    De ce que j'ai lu je devrais utiliser sscanf mais j'ai plusieurs problèmes :

    Je ne sais pas comment reconnaitre les différentes commandes (création, affichage, tronquer 1er élement ...).

    De plus je ne sais pas comment utiliser sscanf pour un nombre de variables inconnu (théoriquement ma liste pourrait avoir 99 éléments).

    Pour l'instant j'ai fais un switch pour chaque type de commande, mais même là je n'y parvient pas.

    Savez vous comment je pourrais faire ?

    Merci bien

    • Partager sur Facebook
    • Partager sur Twitter
      26 septembre 2021 à 13:12:18

      Bonjour ! Est-ce que la syntaxe est imposée ? Je la trouve compliquée car elle n'est pas identique selon les commandes. (*)

      Si elle est imposée, est-ce que tu arrives à reconnaître chaque cas ? Par exemple, même si tu n'as pas encore écrit la fonction qui crée une liste, est-ce que tu arrives à entrer dans cette fonction ?

      Ce que je ferais (et que tu as peut-être envisagé), c'est d'associer un numéro à chaque type de commande. Par exemple 0 = quitter le programme, 1 = définir une liste, etc. Bien sûr on pourra utiliser des 'enum' pour clarifier l'écriture.

      L'algorithme serait (à l'intérieure de la boucle principale) :

      1. Lire la commande dans une unique chaîne de caractères.

      2. Analyser cette chaîne pour déterminer le numéro de la commande.

      3. Avec un switch, aller dans la fonction associée à ce numéro (on pourrait peut-être faire plus optimal en utilisant un tableau de fonction, mais je n'ai jamais fait ça...)

      Pour l'instant tu en es à l'étape 2, c'est ça ? Si oui, il faut écrire les fonctions associées au n° de commande en mettant dedans uniquement un 'printf' qui affiche « Je suis dans la fonction machin-truc ».

      La grosse difficulté sera le traitement proprement dit de chaque option, mais c'est pour plus tard. Une difficulté après l'autre.

      ------

      (*) Ce serait moi je choisirais une syntaxe plus rigide : commande nom-de-liste argument (quoi ? qui ? comment ?).

      (Avertissement : j'y connais rien, et surtout pas la théorie ! Mais j'ai déjà fait un truc de ce genre récemment pour lire un fichier de configuration : ce fichier devait obéir à une certaine syntaxe que j'ai voulu au plus simple parce que gérer le fichier de configuration n'était pas ce qui m'intéressait le plus...)

      L'argument dépend de la commande : aucun, ou liste, ou nom de liste, ou élément.

      Exemples :

      >> define List (a b c d) // l'argument de 'define' est une liste
      >> print List            // 'print' n'admet pas d'argument
      >> copy List newList     // l'argument de 'copy' est un nom de liste
      >> cdr List e            // l'argument de 'cdr' est un élément

      Étape 1 : on extrait de la commande les deux premières chaînes : le nom de la commande et le nom de la liste. À partir du nom de la commande, on déduit son numéro. On en profite pour vérifier si la syntaxe est correcte. Si non : message d'erreur. Si oui : le switch nous dirige vers l'une des fonctions associées au numéro de commande.

      Étape 2, depuis la fonction associée au n° de commande : on analyse le paramètre. S'il n'est pas valide, message d'erreur. S'il est valide, on passe à la suite.

      Étape 3, la plus difficile je crois : analyser ce qui reste de la chaîne = l'argument, qui dépend de la commande.

      -
      Edité par robun 26 septembre 2021 à 13:36:36

      • Partager sur Facebook
      • Partager sur Twitter
        26 septembre 2021 à 17:31:21

        Bonjour,

        FlagadorTV a écrit:

        [...]

        De ce que j'ai lu je devrais utiliser sscanf mais j'ai plusieurs problèmes :

        [...]

        Si tu commences à vouloir parser des expressions il va surtout falloir construire une grammaire, parser une chaîne pour en faire une liste de tokens qui seront interprétés avec ladite grammaire. sscanf n'est pas forcément le meilleur choix.
        • Partager sur Facebook
        • Partager sur Twitter
          28 septembre 2021 à 11:22:52

          Il y a des outils pour ça, les antédiluviens flex et yacc par exemple. Mais cela reste possible à la main …

          Tu as bien une spécification pour ce que ton interpréteur doit reconnaître, non ? tu pourrais nous la partager peut-être …

          • Partager sur Facebook
          • Partager sur Twitter
            29 septembre 2021 à 8:56:48

            La syntaxe présentée, c'est des s-expr à la lisp, avec omission des parenthèses extérieures pour la ligne de commande. La grammaire elle est vite écrite.

            Le "cdr" est un indice gros comme une maison.

            De mémoire, le langage de commande de gcos6 (Et de multics) étaient de ce type. Ce qui ne nous rajeunit pas. (Ils utilisaient des crochets à la place des parentheses)

            - la Ligne de commande est une séquence d'expressions

            - une expression est soit un atome, soit une séquence d'expressions mise entre parenthèses,

            Et hop

            -
            Edité par michelbillaud 29 septembre 2021 à 9:40:06

            • Partager sur Facebook
            • Partager sur Twitter
              29 septembre 2021 à 10:21:00

              c'est un poil plus touffu tout de même, mais l'idée est là

              • Partager sur Facebook
              • Partager sur Twitter

              C : Utiliser parsing pour créer un intérpreteur

              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
              • Editeur
              • Markdown