Xalg / Fix / Apprendre Fix — 5. La syntaxe
Navigation
Apprendre
Recettes
Référence
Comprendre
Bonnes pratiques
En pratique
Explications

Apprendre Fix — 5. La syntaxe

Cinquième étape. Tes données ont souvent déjà une notation — un DSL métier, un format d'échange. Fix te laisse la déclarer, et la déclaration marche dans les deux sens : le même programme lit le texte vers l'AST et écrit l'AST vers le texte. Compte 20 minutes.


1. L'AST d'abord, la syntaxe ensuite

Le principe tient en une phrase : la structure d'un langage vit dans son type (les constructeurs, leur récursivité) ; la syntaxe ne fait que donner une apparence à chaque constructeur. On déclare donc le type, puis on l'habille — et comme un langage, c'est un module, tout vit ensemble :

module(er, []).
  type atype   = string | int.          % FERMÉ : le vocabulaire de types
  type attr_t  = attr(aname, atype).    % aname OUVERT (nom) · atype fermé
  type attrs   = nil | cons(attr_t, attrs).
  type ent_t   = ent(ename, attrs).     % ename OUVERT : tout identifiant

  ent(N, L)  := "entity" N "fields" L "end".   % la syntaxe : une apparence par constructeur
  attr(N, T) := "attr" N T.
  syntax(er, cons, sequence("[", ",", "]", cons, nil)).
end_module.

Une clause ent(N, L) := "entity" N "fields" L "end" se lit : « le constructeur ent(N, L) s'écrit entity, puis le nom, puis fields, puis la liste, puis end ». Les guillemets sont des mots-clés ; les variables sont les trous, remplis récursivement selon leur type. Remarque ce qui manque : aucune règle de grammaire pour « une liste d'attributs » — la récursion vient du type (attrs = nil | cons(...)), pas de la syntaxe.


2. Lire : du texte vers l'AST

lire est le pont texte → terme, en requête. Donne-lui le langage, le type racine, le texte — il te rend le terme :

?- lire(er, ent_t, "entity person fields [ attr name string ] end", M).
M = ent(person, cons(attr(name, string), nil))

Le texte est devenu un AST — un terme Fix ordinaire, que tu peux interroger, transformer, tester comme tout le reste. person (un nom d'entité) et name (un nom d'attribut) sont acceptés parce que leurs types sont ouverts ; mais string en position de type est vérifié (atype est fermé) — un non-type y serait refusé.


3. Écrire : et l'aller-retour

Il n'y a qu'une déclaration par constructeur, et elle sert aux deux sens. ecrire rend un terme dans un langage :

?- ecrire(er, ent_t, ent(person, cons(attr(name, string), nil)), S).
S = entity person fields [ attr name string ] end

Pas de parseur à écrire, pas d'imprimeur à maintenir en miroir : c'est la même clause, parcourue dans un sens ou dans l'autre. Ce qui est lu puis écrit retombe sur ses pieds (aller-retour exact). Et le même AST peut porter plusieurs notations — une par module/langage — ce qui rend la transformation de modèles courte (l'étape suivante). Le détail : La syntaxe de surface.


Ce que tu sais faire

Déclarer un langage = déclarer un type (l'AST) + l'habiller (la syntaxe), dans un module. lire fait texte → terme, ecrire fait terme → texte, avec une seule clause par constructeur (aller-retour exact).

6. Dériver : le sommet — transformer un modèle en un autre, texte à texte.