diff --git a/.github/workflows/check_correctness.yml b/.github/workflows/check_correctness.yml
index 58b844f98..d1349f260 100644
--- a/.github/workflows/check_correctness.yml
+++ b/.github/workflows/check_correctness.yml
@@ -63,6 +63,11 @@ jobs:
eval $(opam env)
OPTIMIZE=0 make tests
+ - name: Test irj-checker
+ run: |
+ eval $(opam env)
+ make test_irj
+
- name: Test DGFIP C backend
run: |
eval $(opam env)
diff --git a/Makefile b/Makefile
index 755ed41af..52a0a137b 100644
--- a/Makefile
+++ b/Makefile
@@ -39,3 +39,16 @@ clean: FORCE remise_a_zero_versionnage
rm -f doc/doc.html
dune clean
+doc-deps: FORCE
+ python3 -m venv .venv
+ .venv/bin/pip install sphinx myst-parser
+
+sphinx-doc: FORCE
+ @command -v .venv/bin/sphinx-build >/dev/null 2>&1 || \
+ { echo "Pour construire la documentation, vous avez besoin de sphinx-build avec \
+ l'extension 'myst-parser'. Lancez `make doc-deps`."; exit 1; }
+ rm -rf _build/default/doc/*
+ cp -rf doc/* _build/default/doc/
+ mkdir -p examples/doc
+ .venv/bin/sphinx-build -M html _build/default/doc/ examples/doc
+ .venv/bin/sphinx-build -M latexpdf _build/default/doc/ examples/doc
diff --git a/compare_traces.sh b/compare_traces.sh
deleted file mode 100755
index 715d9f8cc..000000000
--- a/compare_traces.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#! /bin/bash
-DGFIP_TARGET_FLAGS=-g,-O,-k4,-t YEAR=2022 make compile_dgfip_c_backend -B
-~/fuzzing-calculette/calculette/trunk/2022/AIT \
- -f tests/2022/fuzzing/fuzzer_3469.m_test |& \
- sed -e 's/\x1b\[[0-9;]*m//g' &> aif_trace.txt
-NO_BINARY_COMPARE=1 ./examples/dgfip_c/ml_primitif/cal \
- tests/2022/fuzzing/fuzzer_3469.m_test &> mlang_trace.txt
-diff aif_trace.txt mlang_trace.txt -u > diff_trace.txt
diff --git a/doc/architecture.png b/doc/architecture.png
deleted file mode 100644
index 20c96e2f8..000000000
Binary files a/doc/architecture.png and /dev/null differ
diff --git a/doc/conf.py b/doc/conf.py
new file mode 100644
index 000000000..5b231de11
--- /dev/null
+++ b/doc/conf.py
@@ -0,0 +1,27 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# For the full list of built-in configuration values, see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+# -- Project information -----------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
+
+project = 'MLang'
+copyright = '2025, Direction Générale des FInances Publiques'
+author = 'Direction Générale des FInances Publiques'
+
+# -- General configuration ---------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
+
+extensions = ['myst_parser']
+
+templates_path = ['_templates']
+exclude_patterns = []
+
+language = 'fr'
+
+# -- Options for HTML output -------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
+
+html_theme = 'alabaster'
+html_static_path = ['_static']
diff --git a/doc/exemples/fonctions.md b/doc/exemples/fonctions.md
new file mode 100644
index 000000000..a2a7f7795
--- /dev/null
+++ b/doc/exemples/fonctions.md
@@ -0,0 +1,322 @@
+(exemples/fonctions)=
+
+# Les fonctions
+
+## Fichier test : test.m
+```
+espace_variables GLOBAL : par_defaut;
+domaine regle mon_domaine_de_regle: par_defaut;
+domaine verif mon_domaine_de_verifications: par_defaut;
+application mon_application;
+variable calculee : attribut mon_attribut;
+
+evenement
+: valeur ev_val
+: variable ev_var;
+
+X : calculee mon_attribut = 0 : "";
+TAB : tableau[10] calculee mon_attribut = 2 : "";
+
+cible init_tab:
+application : mon_application;
+iterer : variable I : entre 0..(taille(TAB) - 1) increment 1 : dans (
+ TAB[I] = I;
+)
+
+cible reinit_tab:
+application : mon_application;
+iterer : variable I : entre 0..(taille(TAB) - 1) increment 1 : dans (
+ TAB[I] = indefini;
+)
+
+cible test_abs:
+application : mon_application;
+afficher "\n__ABS__";
+afficher "\n abs(indefini) = ";
+afficher (abs(indefini));
+afficher "\n abs(1) = ";
+afficher (abs(1));
+afficher "\n abs(-1) = ";
+afficher (abs(-1));
+afficher "\n";
+
+cible test_arr:
+application : mon_application;
+afficher "\n__ARR__";
+afficher "\n arr(indefini) = ";
+afficher (arr(indefini));
+afficher "\n arr(1.8) = ";
+afficher (arr(1.8));
+afficher "\n arr(-1.7) = ";
+afficher (arr(-1.7));
+afficher "\n";
+
+cible test_attribut:
+application : mon_application;
+afficher "\n__ATTRIBUT__";
+afficher "\n attribut(X, mon_attribut) = ";
+afficher (attribut(X, mon_attribut));
+afficher "\n attribut(TAB, mon_attribut) = ";
+afficher (attribut(TAB, mon_attribut));
+afficher "\n";
+
+cible test_champ_evenement_base:
+application : mon_application;
+afficher "\n champ_evenement(0, ev_val) = ";
+afficher (champ_evenement (0,ev_val));
+afficher "\n champ_evenement(0, ev_var) = ";
+afficher (champ_evenement (0,ev_var));
+afficher "\n";
+
+cible test_champ_evenement:
+application : mon_application;
+afficher "\n__CHAMP_EVENEMENT__";
+arranger_evenements
+ : ajouter 1
+ : dans (
+ afficher "\nAvant d'initialiser les champs de l'événement:";
+ calculer cible test_champ_evenement_base;
+ champ_evenement (0,ev_var) reference X;
+ champ_evenement (0,ev_val) = 42;
+ X = 2;
+ afficher "\n Après avoir initialisé les champs de l'événement:";
+ calculer cible test_champ_evenement_base;
+ X = indefini;
+ )
+
+cible test_inf:
+application : mon_application;
+afficher "\n__INF__";
+afficher "\n inf(indefini) = ";
+afficher (inf(indefini));
+afficher "\n inf(1.8) = ";
+afficher (inf(1.8));
+afficher "\n inf(-1.7) = ";
+afficher (inf(-1.7));
+afficher "\n";
+
+cible test_max:
+application : mon_application;
+afficher "\n__MAX__";
+afficher "\n max(indefini, indefini) = ";
+afficher (max(indefini, indefini));
+afficher "\n max(-1, indefini) = ";
+afficher (max(-1, indefini));
+afficher "\n max(indefini, -1) = ";
+afficher (max(indefini, -1));
+afficher "\n max(1, indefini) = ";
+afficher (max(1, indefini));
+afficher "\n";
+
+cible test_meme_variable:
+application : mon_application;
+afficher "\n__MEME_VARIABLE__";
+afficher "\n meme_variable(X,X) = ";
+afficher (meme_variable(X,X));
+afficher "\n meme_variable(X,TAB) = ";
+afficher (meme_variable(X,TAB));
+afficher "\n meme_variable(TAB[0],TAB) = ";
+afficher (meme_variable(TAB[0],TAB));
+afficher "\n";
+
+cible test_min:
+application : mon_application;
+afficher "\n__MIN__";
+afficher "\n min(indefini, indefini) = ";
+afficher (min(indefini, indefini));
+afficher "\n min(1, indefini) = ";
+afficher (min(1, indefini));
+afficher "\n min(indefini, 1) = ";
+afficher (min(indefini, 1));
+afficher "\n min(-1, indefini) = ";
+afficher (min(-1, indefini));
+afficher "\n";
+
+cible test_multimax_base:
+application : mon_application;
+afficher "\n multimax(indefini, TAB) = ";
+afficher (multimax(indefini, TAB));
+afficher "\n multimax(7, TAB) = ";
+afficher (multimax(7, TAB));
+afficher "\n multimax(taille(TAB) + 1, TAB) = ";
+afficher (multimax(taille(TAB) + 1, TAB));
+afficher "\n multimax(0, TAB) = ";
+afficher (multimax(0, TAB));
+afficher "\n multimax(-1, TAB) = ";
+afficher (multimax(-1, TAB));
+
+cible test_multimax:
+application : mon_application;
+afficher "\n__MULTIMAX__";
+afficher "\nAvant initialisation du tableau :";
+calculer cible test_multimax_base;
+calculer cible init_tab;
+afficher "\nAprès initialisation du tableau :";
+calculer cible test_multimax_base;
+calculer cible reinit_tab;
+afficher "\n";
+
+cible test_nb_evenements_base:
+application : mon_application;
+afficher "\n nb_evenements() = ";
+afficher (nb_evenements ());
+afficher "\n";
+
+cible test_nb_evenements:
+application : mon_application;
+afficher "\n__NB_EVENEMENTS__";
+afficher "\nAvant la définition d'un événement :";
+calculer cible test_nb_evenements_base;
+arranger_evenements
+ : ajouter 1
+ : dans (
+ afficher "\nPendant la définition d'un événement :";
+ calculer cible test_nb_evenements_base;
+ )
+afficher "\nAprès la définition d'un événement :";
+calculer cible test_nb_evenements_base;
+
+cible test_null:
+application : mon_application;
+afficher "\n__NULL__";
+afficher "\n null(indefini) = ";
+afficher (null(indefini));
+afficher "\n null(0) = ";
+afficher (null(0));
+afficher "\n null(1) = ";
+afficher (null(1));
+afficher "\n";
+
+cible test_positif:
+application : mon_application;
+afficher "\n__POSITIF__";
+afficher "\n positif(indefini) = ";
+afficher (positif(indefini));
+afficher "\n positif(0) = ";
+afficher (positif(0));
+afficher "\n positif(1) = ";
+afficher (positif(1));
+afficher "\n positif(-1) = ";
+afficher (positif(-1));
+afficher "\n";
+
+cible test_positif_ou_nul:
+application : mon_application;
+afficher "\n__POSITIF OU NUL__";
+afficher "\n positif_ou_nul(indefini) = ";
+afficher (positif_ou_nul(indefini));
+afficher "\n positif_ou_nul(0) = ";
+afficher (positif_ou_nul(0));
+afficher "\n positif_ou_nul(1) = ";
+afficher (positif_ou_nul(1));
+afficher "\n positif_ou_nul(-1) = ";
+afficher (positif_ou_nul(-1));
+afficher "\n";
+
+cible test_present:
+application : mon_application;
+afficher "\n__PRESENT__";
+afficher "\n present(indefini) = ";
+afficher (present(indefini));
+afficher "\n present(0) = ";
+afficher (present(0));
+afficher "\n present(1) = ";
+afficher (present(1));
+afficher "\n";
+
+cible test_somme:
+application : mon_application;
+afficher "\n__SOMME__";
+afficher "\n somme() = ";
+afficher (somme());
+afficher "\n somme(indefini) = ";
+afficher (somme(indefini));
+afficher "\n somme(1, indefini) = ";
+afficher (somme(1, indefini));
+afficher "\n somme(1, 2, 3, 4, 5) = ";
+afficher (somme(1, 2, 3, 4, 5));
+afficher "\n";
+
+cible test_supzero:
+application : mon_application;
+afficher "\n__SUPZERO__";
+afficher "\n supzero(indefini) = ";
+afficher (supzero(indefini));
+afficher "\n supzero(42) = ";
+afficher (supzero(42));
+afficher "\n supzero(-1) = ";
+afficher (supzero(-1));
+afficher "\n supzero(0) = ";
+afficher (supzero(0));
+afficher "\n";
+
+cible test_taille:
+application : mon_application;
+afficher "\n__TAILLE__";
+afficher "\n taille(TAB) = ";
+afficher (taille(TAB));
+afficher "\n taille(X) = ";
+afficher (taille(X));
+afficher "\n";
+
+cible fun_test:
+application : mon_application;
+# Abs
+calculer cible test_abs;
+# Arr
+calculer cible test_arr;
+# Attribut
+calculer cible test_attribut;
+# Champ evenement
+calculer cible test_champ_evenement;
+# Inf
+calculer cible test_inf;
+# Max
+calculer cible test_max;
+# Meme variable
+calculer cible test_meme_variable;
+# Min
+calculer cible test_min;
+# Multimax
+calculer cible test_multimax;
+# Null
+calculer cible test_nb_evenements;
+# Null
+calculer cible test_null;
+# Positif
+calculer cible test_positif;
+# Positif ou nul
+calculer cible test_positif_ou_nul;
+# Présent
+calculer cible test_present;
+# Somme
+calculer cible test_somme;
+# Supzero
+calculer cible test_supzero;
+# Taille
+calculer cible test_taille;
+```
+
+## Fichier irj : test.irj
+
+```
+#NOM
+MON-TEST
+#ENTREES-PRIMITIF
+#CONTROLES-PRIMITIF
+#RESULTATS-PRIMITIF
+#ENTREES-CORRECTIF
+#CONTROLES-CORRECTIF
+#RESULTATS-CORRECTIF
+##
+```
+
+## Commande
+
+```
+mlang test.m \
+ --without_dfgip_m \
+ -A mon_application \
+ --mpp_function fun_test \
+ --run_test test.irj
+```
diff --git a/doc/exemples/valeurs.md b/doc/exemples/valeurs.md
new file mode 100644
index 000000000..2ab328aae
--- /dev/null
+++ b/doc/exemples/valeurs.md
@@ -0,0 +1,141 @@
+(exemples/valeurs)=
+
+# Calcul des valeurs
+
+## Fichier test : test.m
+```
+espace_variables GLOBAL : par_defaut;
+domaine regle mon_domaine_de_regle: par_defaut;
+domaine verif mon_domaine_de_verifications: par_defaut;
+application mon_application;
+variable saisie : attribut mon_attribut;
+variable calculee : attribut mon_attribut;
+X : saisie mon_attribut = 0 alias AX : "";
+
+cible indefini_test:
+application : mon_application;
+afficher "Bonjour, monde, X = ";
+afficher (X);
+afficher " !\n";
+# Addition
+afficher "X + 1 = ";
+afficher (X + 1);
+afficher " !\n";
+afficher "1 + X = ";
+afficher (1 + X);
+afficher " !\n";
+afficher "X + X = ";
+afficher (X + X);
+afficher " !\n";
+# Soustraction
+afficher "X - 1 = ";
+afficher (X - 1);
+afficher " !\n";
+afficher "1 - X = ";
+afficher (1 - X);
+afficher " !\n";
+afficher "X - X = ";
+afficher (X - X);
+afficher " !\n";
+# Multiplication
+afficher "X * 1 = ";
+afficher (X * 1);
+afficher " !\n";
+afficher "1 * X = ";
+afficher (1 * X);
+afficher " !\n";
+afficher "X * X = ";
+afficher (X * X);
+afficher " !\n";
+# Division
+afficher "X / 1 = ";
+afficher (X / 1);
+afficher " !\n";
+afficher "1 / X = ";
+afficher (1 / X);
+afficher " !\n";
+afficher "1 / 0 = ";
+afficher (1 / 0);
+afficher " !\n";
+afficher "X / 0 = ";
+afficher (X / 0);
+afficher " !\n";
+afficher "X / X = ";
+afficher (X / X);
+afficher " !\n";
+# Comparaisons
+afficher "(X = 0) = ";
+afficher (X = 0);
+afficher " !\n";
+afficher "(X = X) = ";
+afficher (X = X);
+afficher " !\n";
+afficher "(X >= 0) = ";
+afficher (X >= 0);
+afficher " !\n";
+afficher "(X >= X) = ";
+afficher (X >= X);
+afficher " !\n";
+afficher "(X > 0) = ";
+afficher (X > 0);
+afficher " !\n";
+afficher "(X > X) = ";
+afficher (X > X);
+afficher " !\n";
+afficher "(X <= 0) = ";
+afficher (X <= 0);
+afficher " !\n";
+afficher "(X < 0) = ";
+afficher (X < 0);
+afficher " !\n";
+afficher "(X <= X) = ";
+afficher (X <= X);
+afficher " !\n";
+afficher "(X < X) = ";
+afficher (X < X);
+afficher " !\n";
+# Opérations booléennes
+afficher "(X et X) = ";
+afficher (X et X);
+afficher " !\n";
+afficher "(X et 1) = ";
+afficher (X et 1);
+afficher " !\n";
+afficher "(X ou X) = ";
+afficher (X ou X);
+afficher " !\n";
+afficher "(X ou 1) = ";
+afficher (X ou 1);
+afficher " !\n";
+afficher "non X = ";
+afficher (non X);
+afficher " !\n";
+# Vérifier la définition d'une valeur
+afficher "present(X) = ";
+afficher (present(X));
+afficher " !\n";
+```
+
+## Fichier irj : test.irj
+
+```
+#NOM
+MON-TEST
+#ENTREES-PRIMITIF
+#CONTROLES-PRIMITIF
+#RESULTATS-PRIMITIF
+#ENTREES-CORRECTIF
+#CONTROLES-CORRECTIF
+#RESULTATS-CORRECTIF
+##
+```
+
+## Commande
+
+```
+mlang test.m \
+ --without_dfgip_m \
+ -A mon_application \
+ --mpp_function indefini_test \
+ --run_test test.irj
+```
diff --git a/doc/fonctions.md b/doc/fonctions.md
new file mode 100644
index 000000000..cda4e8ea1
--- /dev/null
+++ b/doc/fonctions.md
@@ -0,0 +1,149 @@
+(fonctions)=
+# Les fonctions
+
+Voici la liste de toutes les fonctions standard du M.
+Leur utilisation est présentée dans l'exemple sur
+{ref}`exemples/fonctions`.
+
+## abs(X)
+
+Cette fonction prend un argument et renvoie sa valeur absolue.
+Si `X` est `indefini`, alors `abs(X) = indefini`.
+
+## afficher(X) / afficher "texte"
+
+Cette fonction affiche sur la sortie standard la valeur de l'expression en argument.
+
+## arr(X)
+
+Cette fonction prend un argument et renvoie l'entier le plus
+proche, ou `indefini` s'il est `indefini`.
+
+## attribut(X, attribut)
+
+Cette fonction prend un argument `X` et un nom d'attribut `a` et retourne
+la valeur associée à l'attribut `a` de `X`.
+
+## champ_evenement(X, champ)
+
+Cette fonction prend un argument `X` et un nom de champ d'événement `champ`.
+La valeur `X` correspond à l'identifiant de l'événement. %TODO: référence chap événement
+Si le `champ` correspond à une valeur, `champ_evenement` la retourne. Si
+le `champ` correspond à une variable, `champ_evenement` retourne sa valeur.
+
+**Note** : `champ_evenement` peut être utilisée pour assigner des valeurs et
+des références à des événéments. Exemple:
+```
+evenement
+: valeur ev_val
+: variable ev_var;
+
+# Associe la valeur 42 au champ ev_val de l'événement 0.
+champ_evenement (0,ev_val) = 42;
+# Associe la variable X au champ ev_var de l'événement 0.
+champ_evenement (0,ev_var) reference X;
+```
+
+## inf(X)
+
+Cette fonction prend un argument et renvoie l'entier inferieur
+le plus proche, ou `indefini` s'il est `indefini`.
+
+## max(X, Y)
+
+Cette fonction prend deux arguments et renvoie la plus grande
+valeur des deux.
+Si les deux valeurs sont `indefini`es, alors la fonction renvoie
+`indefini`.
+Si `X` est défini et `Y` est `indefini`, alors `max(X,Y) = max(X, 0)`. De même,
+si `X` est `indéfini` et `Y` est defini, alors `max(X,Y) = max(0, Y)`.
+
+## meme_variable(X, Y)
+
+Cette fonction prend en argument deux variables et vérifie s'il s'agit de la même
+variable.
+Elle est notamment utilisée dans les iterateurs de variables pour effectuer des
+traitements spécifiques.
+
+## multimax(X, TAB)
+
+Cette fonction prend deux arguments `X` une valeur et `TAB` un tableau
+de valeurs.
+Elle calcule la plus grande valeur contenue dans `TAB` entre `0` et `X - 1`.
+Si X est `indefini` ou `X <= 0`, alors `multimax(X, TAB) = indefini`.
+`X` peut être plus grand que la taille de `TAB`, auquel cas `multimax` calculera le
+maximum de `TAB`.
+
+## min(X, Y)
+
+Cette fonction prend deux arguments et renvoie la plus petite
+valeur des deux.
+Si les deux valeurs sont `indefini`es, alors la fonction renvoie
+`indefini`.
+Si `X` est défini et `Y` est `indefini`, alors `min(X,Y) = min(X, 0)`. De même,
+si `X` est `indéfini` et `Y` est defini, alors `min(X,Y) = min(0, Y)`.
+
+## nb_evenements()
+
+Cette fonction renvoie le nombre total d'événements.
+
+## null(X)
+
+Cette fonction prend un argument `X` et renvoie `1` si `X` est
+égal à `0`, `0` si `X` est défini et différent de `0`,
+et `indefini` s'il est `indefini`.
+
+Cette fonction est strictement équivalente à l'expression `(X = 0)`
+
+## positif(X)
+
+Cette fonction prend un argument `X` et renvoie `1` si `X` est
+**strictement** supérieur à `0`, `0` si `X` est inferieur ou égal à `0`, et
+`indefini` si `X` est indefini.
+
+Cette fonction est strictement équivalente à l'expression `X > 0`.
+
+## positif_ou_nul(X)
+
+Cette fonction prend un argument `X` et renvoie `1` si `X` est
+supérieur ou égale à `0`, `0` si `X` est strictement inferieur ou égal à
+`0`, et `indefini` si `X` est indefini.
+
+Cette fonction est strictement équivalente à l'expression `X >= 0`.
+
+## present(X)
+
+Cette fonction prend un argument `X` et renvoie `0` s'il
+est `indefini` et `1` sinon.
+
+**Note** : cette fonction est la seule façon de tester si une valeur est
+égale à `indefini` car l'expression booléenne `(indefini = indefini)`
+est égale à `indefini`.
+
+## somme(X, Y, ...)
+
+Cette fonction n'a pas de limite d'arguments.
+Elle calcule leur somme.
+Si aucun argument n'est donné à la fonction `somme`, elle renvoie `0`.
+Si tous ses arguments sont `indefini`s, alors elle renvoie la valeur
+`indefini`.
+
+## supzero(X)
+
+Cette fonction prend un argument `X` et renvoie sa valeur s'il est strictement supérieur
+à `0`, sinon il renvoie `indefini`.
+
+## taille(TAB)
+
+Cette fonction prend en argument soit une variable, soit un tableau.
+S'il s'agit d'une variable, `taille` renvoie `1`, sinon elle renvoie la taille du
+tableau.
+Elle échoue si l'argument est une constante ou une valeur.
+
+% TODO
+
+% ## numero_compil()
+% Unsupported, raises assert false!
+
+% ## numero_verif()
+% Unsupported as well
diff --git a/doc/index.md b/doc/index.md
new file mode 100644
index 000000000..d3cd2fb4b
--- /dev/null
+++ b/doc/index.md
@@ -0,0 +1,38 @@
+
+
+
+
+ .____. ________________________
+ | ._ ' | |
+ | | \ | Direction Générale des |
+ .-+-+-' | |
+ | | | Finances Publiques |
+ ! ! !________________________!
+
+
+
+# Documentation du langage M
+
+## Le langage M
+
+```{toctree}
+:maxdepth: 2
+
+intro
+syntax
+fonctions
+syntax_irj
+mlang
+```
+
+## Exemples
+
+```{toctree}
+:maxdepth: 1
+
+exemples/valeurs
+exemples/fonctions
+```
+
+
+
diff --git a/doc/intro.md b/doc/intro.md
new file mode 100644
index 000000000..a88c6b59e
--- /dev/null
+++ b/doc/intro.md
@@ -0,0 +1,195 @@
+(intro_m)=
+
+# Introduction au langage M
+
+## Les éléments de base
+
+Un programme M se caracterise par la définition successive :
+* de types de variables avec leurs attributs ;
+* de domaines et d'événements ;
+* d'espaces de variables ;
+* d'applications ;
+* de variables et de constantes ;
+* des fonctions ;
+* de règles de calcul associées ou non à une application.
+
+Exécuter d'un tel programme pour une application donnée correspond à
+exécuter l'ensemble des règles de calcul associée la dite application.
+%%
+L'ordre d'exécution des règles de calcul dépend des dépendances entre les
+variables. Si une variable est affectée dans une règle, alors cette règle
+sera exécutée avant toutes celles utilisant la valeur de la dite variable.
+%%
+Si une variable est lue et écrite cycliquement, l'ordre d'exécution des règles
+n'est pas garanti.
+
+## Définitions par défaut
+
+Les types de variables, leurs attributs, les domaines et les événements
+sont historiquement des mots clés propres au langage M.
+%%
+Il est aujourd'hui possible de les définir à la main.
+
+## Aperçu de la syntaxe
+
+Voici un exemple simple de programme M minimal.
+
+```
+# Fichier: test.m
+
+# On définit un espace de variable global dans lequel nos variables
+# seront stockées par défaut.
+espace_variables GLOBAL : par_defaut;
+
+# On définit deux domaines obligatoires:
+# * un domaine pour les règles;
+# * un domaine pour les vérificateurs.
+domaine regle mon_domaine_de_regle: par_defaut: calculable;
+domaine verif mon_domaine_de_verifications: par_defaut;
+
+# On définit une ou plusiseurs application pour nos règles.
+application mon_application;
+
+# On définit une cible, un ensemble d'instructions à exécuter.
+cible hello_world:
+application : mon_application;
+afficher "Bonjour, monde!\n";
+```
+
+Cet exemple jouet n'utilise ni ne définit aucune variable, les domaines
+et les espaces de variables ne sont pas utilisés ici mais ils seront nécessaires
+plus tard.
+%%
+Pour essayer notre exemple, nous allons créer un fichier 'test.irj' avec le
+contenu suivant :
+%%
+```
+#NOM
+MON-TEST
+#ENTREES-PRIMITIF
+#CONTROLES-PRIMITIF
+#RESULTATS-PRIMITIF
+#ENTREES-CORRECTIF
+#CONTROLES-CORRECTIF
+#RESULTATS-CORRECTIF
+##
+```
+Le détail de la syntaxe irj peut être sur la page dédiée : {ref}`syntax_irj`
+
+Enfin, on peut lancer mlang.
+
+```
+ $ mlang --without_dfgip_m test.m -A mon_application --mpp_function hello_world --run_test test.irj
+ Parsing: completed!
+ Bonjour, monde!
+ [RESULT] test.irj
+ [RESULT] No failure!
+ [RESULT] Test passed!
+```
+
+## Définition de variables
+
+Les variables sont divisées en deux catégories.
+* Les variables `saisie`s sont les variables d'entrées du
+programme M.
+* Les variables `calculee`s sont les variables sur lesquelles seront
+calculées les données.
+
+Chacune de ces catégories principales doivent être dotées d'attributs,
+un ensemble d'entiers constants pour une variable donnée.
+Ainsi, on peut rajouter à notre programme test les lignes suivantes :
+```
+variable saisie : attribut mon_attribut;
+variable calculee : attribut mon_attribut;
+X : saisie mon_attribut = 0 alias ALIAS_DE_X : "Cette variable s'appelle X";
+Y : calculee mon_attribut = 1 : "Cette variable s'appelle Y";
+```
+
+Notez que la variable `X` a un alias `ALIAS_DE_X`.
+Toutes les variables saisies doivent être parées d'un alias qui peut être
+utilisé de la même façon que son nom original.
+Cet alias existe initialement pour faire le lien entre la variable utilisée
+dans le M (nom original) et le code de la variable dans le formulaire de
+déclaration de l'impot sur le revenu tel qu'on le retrouve aujourd'hui sur
+le site de déclaration (1AP, 8TV, ...).
+
+Ajoutons une nouvelle cible à notre calcul :
+```
+cible hello_world2:
+application : mon_application;
+afficher "Bonjour, monde, X = ";
+afficher (X);
+afficher " !\n";
+Y = X + 1;
+afficher "Y = ";
+afficher (Y);
+afficher " !\n";
+```
+
+Et lançons le calcul :
+```
+ $ mlang --without_dfgip_m test.m -A mon_application --mpp_function hello_world2 --run_test test.irj
+Parsing: completed!
+Bonjour, monde, X = indefini !
+Y = 1 !
+[RESULT] test.irj
+[RESULT] No failure!
+[RESULT] Test passed!
+```
+
+Pour comprendre la valeur finale de Y, référez-vous à la
+section {ref}`valeurs`.
+
+## Règles de calcul
+
+Les règles en M sont des unités de calcul de variables associées à une ou
+plusieurs application et optionnellement à un domaine de règles.
+Elles sont composées d'une successions d'affectations.
+Voici la définition de deux règles simples que nous rajoutons à notre fichier test :
+```
+Z : calculee mon_attribut = 1 : "Cette variable s'appelle Z";
+
+regle mon_domaine_de_regles 1:
+application : mon_application;
+Z = Y + 1;
+
+regle 2:
+application : mon_application;
+Y = X + 1;
+```
+
+La première règle est associée au domaine `mon_domaine_de_regles` tandis que la
+seconde n'étant pas spécifié, sera associée au domaine de règle par défaut.
+Dans notre exemple, il s'agissait également de `mon_domaine_de_regles`.
+
+Le calcul d'un domaine correspond au calcul de l'ensemble de ses règles.
+L'ordre d'application des règles dépend de l'ordre d'affectation des variables.
+Dans notre cas, `X` est une entrée dont `Y` dépend (règle 2), et `Z` dépend de
+`Y`.
+
+Par conséquent, la règle 2 sera appliquée avant la règle 1.
+On peut ainsi rajouter une cible qui calcule le domaine de règles :
+```
+cible calc_test:
+application : mon_application;
+calculer domaine mon_domaine_de_regles;
+afficher "X = ";
+afficher (X);
+afficher "\nY = ";
+afficher (Y);
+afficher "\nZ = ";
+afficher (Z);
+afficher "\n";
+```
+
+Et lancer le calcul :
+```
+ $ mlang --without_dfgip_m test.m -A mon_application --mpp_function calc_test --run_test test.irj
+ Parsing: completed!
+ X = indefini
+ Y = 1
+ Z = 2
+ [RESULT] test.irj
+ [RESULT] No failure!
+ [RESULT] Test passed!
+```
diff --git a/doc/mlang.md b/doc/mlang.md
new file mode 100644
index 000000000..bdf599e54
--- /dev/null
+++ b/doc/mlang.md
@@ -0,0 +1,306 @@
+(mlang)=
+
+# Le compilateur MLang
+
+## Utiliser MLang
+
+Le binaire `mlang` prend en argument le fichier *M* à exécuter.
+Il peut également prendre en argument une liste de fichiers, auquel cas leur
+traitement sera équivalent au traitement d'un seul et même fichier dans lequel
+serait concatené le contenu de chaque fichier.
+%%
+
+Les deux options principales sont :
+* `-A`: le nom de l'application à traiter;
+* `--mpp_function`: le nom de la fonction principale à traiter.
+
+### Mode interpreteur
+
+Le mode interpreteur de `mlang` utilise un fichier *IRJ* (voir {ref}`syntax_irj`)
+pour exécuter le code *M* directement depuis sa représentation abstraite.
+
+Voici une commande simple pour invoquer l'interpreteur :
+```
+$ mlang test.m \
+ -A mon_application \
+ -b interpreter \
+ --mpp_function hello_world \
+ --run_test test.irj \
+ --without_dfgip_m
+```
+
+### Mode transpilation
+
+Le mode transpilation de `mlang` permet de traduire le code *M* dans un autre
+langage.
+En 2025, seul le langage C est supporté.
+Voici une commande simple pour traduire un fichier *M* en *C* :
+
+```
+$ mlang test.m \
+ -A mon_application \
+ -b dgfip_c \
+ --mpp_function hello_world
+ --dgfip_options=''
+ --output output/mon-test.c
+```
+
+NB: le dossier `output` doit avoir été créé en amont.
+
+### Options DGFiP
+
+Les options DGFiP sont à usage interne.
+
+```
+ -b VAL
+ Set application to "batch" (b0 = normal, b1 = with EBCDIC sort)
+
+ -D Generate labels for output variables
+
+ -g Generate for test (debug)
+
+ -I Generate immediate controls
+
+ -k VAL (absent=0)
+ Number of debug files
+
+ -L Generate calls to ticket function
+
+ -m VAL (absent=1991)
+ Income year
+
+ -O Optimize generated code (inline min_max function)
+
+ -o Generate overlays
+
+ -P Primitive calculation only
+
+ -r Pass TGV pointer as register in rules
+
+ -R Set application to both "iliad" and "pro"
+
+ -s Strip comments from generated output
+
+ -S Generate separate controls
+
+ -t Generate trace code
+
+ -U Set application to "cfir"
+
+ -x Generate cross references
+
+ -X Generate global extraction
+
+ -Z Colored output in chainings
+```
+
+## Comportement de mlang
+
+### Traduction
+
+% A faire : traduction du M en M_AST
+
+### Pré-traitement
+
+Le prétraitement est une opération purement syntaxique.
+Son but est triple :
+- éliminer les constructions relatives aux applications non-sélectionnées ;
+- remplacer les constantes par leur valeur numérique ;
+- remplacer les expressions numériques débutant par `somme` avec des
+ additions ;
+- éliminer les ``s en les remplaçant par des séries de ``s.
+
+Toute substitution transformant un programme M syntaxiquement valide en un
+texte ne correspondant à aucun programme M provoque l'échec du traitement.
+
+#### Cas des applications
+
+On élimine du programme M:
+- les déclarations des applications non-sélectionnées ;
+- les déclarations des enchaîneurs ne spécifiant pas une application
+ sélectionnée ;
+- les déclarations des règles ne spécifiant pas une application
+ sélectionnée ;
+- les déclarations des vérifications ne spécifiant pas une application
+ sélectionnée ;
+- les déclarations des cibles ne spécifiant pas une application sélectionnée.
+
+Dans les déclarations des règles spécifiant une application sélectionnée, on
+élimine les enchaîneurs qui ne sont plus déclarés dans le programme M obtenu.
+
+#### Cas des constantes
+
+Pour prétraiter un programme, on le parcourt du début à la fin. Pour chaque
+`` rencontrée, si elle correspond à une contante défini précédemment,
+alors il est remplacé dans le programme par la valeur numérique correspondante.
+
+Un intervalle de la forme `..` est
+converti par substitution de la constante `const` en l'intervalle
+`..`, avec `fin` le naturel correspondant
+à `const`.
+
+*Exemple* : considérons le programme suivant :
+```
+fin : const = 10;
+…
+pour i = 9-fin :
+ Bi = Bi + fin;
+```
+
+Par substitution de la constante `fin`, il est remplacé dans un premier temps
+remplacée par le programme :
+
+```
+fin : const = 10;`
+…
+pour i = 9..10 :
+ Bi = Bi + fin;
+```
+
+puis dans un second temps par le programme :
+```
+fin : const = 10;
+…
+pour i = 9..10 :
+ Bi = Bi + 10;
+```
+
+#### Interprétation des indices
+
+Pour rappel, les *indices* ont la forme suivante :
+```
+ ::= ; …
+ ::= = , …
+```
+
+avec :
+* ` ::= [a-z]`
+* ` ::= [A-Z]`
+* ` ::= + | .. | (.. | - )?`
+
+Chaque `` associe à une lettre minuscule une série de chaînes de
+caractères de même taille.
+Cette série est composée de la succession de chaque
+ à droite du symbole `=`.
+
+Les séries associées aux sont définis comme suit :
+* `+` est la série composée de chacune des majuscules prises
+ séparément, donc de taille 1 (*par exemple* : `AXF` représente la série `A`, `X`, `F`);
+* `****` est la série composée de toutes
+ les majuscules comprises entre /début/ et /fin/, bornes comprises, suivant
+ l'ordre alphabétique, donc de taille 1 (*par exemple* : `A..D` représente la série `A`, `B`, `C`, `D`);
+* `..` est la série composée de tous les
+ nombres naturels entre `début` et `fin`, bornes comprises, la taille des
+ éléments étant égale à la taille du plus grand naturel en base 10; les
+ naturels trop petits pour avoir la taille requise sont complétés par des 0 à
+ gauche (*par exemple* : `9..11` représente la série `09`, `10`, `11`);
+* `-` est converti lors du prétraitement des constantes
+ en un intervalle de la forme `..`.
+
+#### Cas des expressions `somme(…)`
+
+Pour une expression numérique
+`somme ( : )`,
+l'expression *expr* sera remplacée par la somme des expressions construites
+ainsi : pour chaque chaîne de caractères de la série introduite par *ind*, les
+symboles apparaîssant dans *expr* sont remplacés par ceux dans lesquels la
+lettre minuscule de /ind/ est substituéé par la chaine de caractère.
+%
+La somme ainsi générée est parenthésée.
+
+Une expression numérique
+`somme ( ; : )`,
+est remplacée par la somme des expressions
+*`somme`*` : expr'> )` avec `expr'` prenant sa valeur
+dans la série `sub(ind, expr)`.
+%
+La procédure est ensuite appliquée récursivement à cette somme.
+%
+La somme ainsi générée est parenthésée.
+%
+Notons que les sous-sommes récursivement produites n'ont pas besoin de l'être
+car l'addition est associative.
+
+On applique cette transformation à toutes les expressions `somme(…)` tant
+qu'il en existe dans le programme.
+
+**Exemple**. Considérons l'expression suivante :
+
+* `somme(i = XZ ; j = 9..10 : Bi + Bj)`
+
+Elle est dans un premier temps remplacée par la somme suivante :
+
+* `(somme(j = 9..10 : BX + Bj) + somme(j = 9..10 : BZ + Bj))`
+
+puis dans un second temps par la somme :
+
+* `(BX + B09 + BX + B10 + BZ + B09 + BZ + B10)`
+
+On remarque que seule l'expression globale est parenthésée car l'addition est
+associative.
+
+#### Cas des multi-formules
+
+On commence par substituer toutes les expressions `somme(…)` apparaissant dans
+les multi-formules.
+%
+Puis on transforme les multi-formules en séries de formules en suivant la
+méthode décrite ci-dessous.
+
+Pour chaque multi-formule rencontrée, de la forme `pour : `,
+dès que les constantes apparaîssant dans les ont été substitués, on
+remplace cette multi-formule par la série de formules générée de la manière
+suivante.
+
+Pour une multi-formule `pour : `, la
+formule `f` sera remplacée par la série des formules construites ainsi : pour
+chaque chaîne de caractères de la série introduite par `ind`, les symboles
+apparaîssant dans `f` sont remplacés par ceux dans lesquels la lettre
+minuscule de `ind` est substituéé par la chaïne de caractère.
+%
+On notera `sub(ind, f)` la série constituée des formules ainsi régérées.
+
+Une multi-formule `pour ; : `,
+est remplacée par la série des multi-formules
+`pour : f'>` avec `f'` prenant sa valeur
+dans la série `sub(ind, f)`.
+%
+La procédure est ensuite appliquée récursivement
+à ces multi-formules.
+
+**Exemple**. Considérons la multi-formule suivante :
+```
+pour i = XZ ; j = 9..10 :
+ Bi = Bi + Bj;
+```
+
+Elle est dans un premier temps remplacée par la série suivante :
+```
+pour j = 9..10 :
+ BX = BX + Bj;
+
+pour j = 9..10 :
+ BZ = BZ + Bj;
+```
+
+Puis dans un second temps par la série des formules :
+```
+BX = BX + B09;
+BX = BX + B10;
+BZ = BZ + B09;
+BZ = BZ + B10;
+````
+
+### Vérification de cohérence
+
+% A faire : documentation de la verification
+
+### Traitement
+
+#### Interpreteur
+
+Lecture du fichier IRJ et interpretation du code.
+
+#### Transpilation
+
+Ecriture du code C équivalent au code M.
diff --git a/doc/syntax.md b/doc/syntax.md
new file mode 100644
index 000000000..2863faabb
--- /dev/null
+++ b/doc/syntax.md
@@ -0,0 +1,575 @@
+(syntax)=
+
+# La syntaxe du M
+
+## Programme M et applications
+
+Un programme M est formé d'une suite de caractères codés sur 8 bits.
+Les 128 premiers codes de caractères correspondent aux codes ASCII.
+Un programme M est constitué d'une suite d'éléments parmi lesquels on compte :
+* des déclarations d'applications ;
+* des définitions de constantes ;
+* des déclarations d'enchaîneurs ;
+* des définitions de catégories de variables ;
+* des déclarations de variables ;
+* des déclarations d'erreurs ;
+* des déclarations de fonctions externes ;
+* des définitions de domaines de règles ;
+* des définitions de domaines de vérifications ;
+* des déclarations de sorties ;
+* des règles ;
+* des vérifications ;
+* des fonctions ;
+* des cibles.
+
+Un programme M peut définir plusieurs applications.
+Pour être traité (compilation, interprétation, etc.), il nécessite la donnée
+d'une liste d'applications.
+Cette liste est typiquement fournie comme argument du compilateur, de
+l'interpréteur ou de tout autre outil de traitement.
+Cette liste sera appelée la liste des applications sélectionnées.
+
+## Définitions liminaires
+Les formes de Backus-Naur étendues sont utilisées pour préciser la morphologie
+du langage.
+Un lexème est une suite de caractères et chaque forme est susceptible d'en
+reconnaître un ensemble.
+
+Ces formes sont étendues avec les notations suivantes :
+
+* `` représente le non-terminal, pour lequel la
+chaîne de caractères qu'il reconnaît est représentée par identifiant ;
+* `forme 1 ^ … ^ forme n` qui représente une suite de lexèmes correspondants
+aux formes 1 à n, dans n'importe quel ordre;
+* et : `(forme 0) séparateur …` qui représente une liste non-vide de lexèmes
+reeconnus par la forme 0, tous séparés par des lexèmes correspondants au
+séparateur.
+
+Les lexèmes suivants sont les mots réservés :
+**BOOLEEN**,
+**DATE_AAAA**,
+**DATE_JJMMAAAA**,
+**DATE_MM**,
+**ENTIER**,
+**REEL**,
+**afficher**,
+**afficher_erreur**,
+**aiguillage**,
+**ajouter**,
+**alias**,
+**alors**,
+**anomalie**,
+**application**,
+**apres**,
+**argument**,
+**arranger_evenements**,
+**attribut**,
+**autorise**,
+**avec**,
+**base**,
+**calculable**,
+**calculee**,
+**calculer**,
+**cas**,
+**categorie**,
+**champ_evenement**,
+**cible**,
+**const**,
+**dans**,
+**dans_domaine**,
+**discordance**,
+**domaine**,
+**enchaineur**,
+**entre**,
+**erreur**,
+**espace**,
+**espace_variables**,
+**et**,
+**evenement**,
+**evenements**,
+**exporte_erreurs**,
+**faire**,
+**filtrer**,
+**finalise_erreurs**,
+**finquand**,
+**finsi**,
+**fonction**,
+**increment**,
+**indefini**,
+**indenter**,
+**informative**,
+**iterer**,
+**leve_erreur**,
+**meme_variable**,
+**nb_anomalies**,
+**nb_bloquantes**,
+**nb_categorie**,
+**nb_discordances**,
+**nb_informatives**,
+**neant**,
+**nettoie_erreurs**,
+**nettoie_erreurs_finalisees**,
+**nom**,
+**non**,
+**numero_compl**,
+**numero_verif**,
+**ou**,
+**par_defaut**,
+**pour**,
+**puis_quand**,
+**quand**,
+**reference**,
+**regle**,
+**restaurer**,
+**restituee**,
+**resultat**,
+**saisie**,
+**si**,
+**sinon**,
+**sinon_si**,
+**sortie**,
+**specialise**,
+**stop**,
+**tableau**,
+**taille**,
+**trier**,
+**type**,
+**un**,
+**valeur**
+**variable**,
+**verif**,
+**verifiable**,
+et **verifier**.
+
+Les lexèmes numériques sont définis comme suit :
+* ` ::= [0-9] [0-9 _]*`
+* ` ::= (. )?`
+* `` est la forme `[a-z A-Z 0-9 _]+` dont sont exclus ``s et
+les mots réservés ;
+* `` est un `` que l'on distingue pour représenter les
+mots pouvant prendre le nom d'une constante.
+
+On définit également les atomes numériques, prenant une valeur soit par un
+nombre littéral, soit par un symbole représentant une constante ou une
+variable :
+
+* ` ::= | `
+* ` ::= | `
+
+Les chaînes de caractères littérales ont la forme suivante :
+* ` :: = " [^ "]* "`
+
+### Déclaration une d'application
+
+Les *déclarations d'applications* ont la forme suivante :
+```
+application ;
+```
+
+où `` est le nom de l'application
+déclarée.
+
+### Définition d'une constante
+
+Les *définitions de constantes* ont la forme suivante :
+```
+ : const = ;
+```
+
+Le symbole est le nom de la constante.
+
+### Déclaration d'un enchaîneur
+Les *déclarations d'enchaîneurs* ont la forme suivante :
+```
+enchaineur : ;
+```
+
+avec :
+` ::= , …` représente l'ensemble des applications incluant cet enchaîneur.
+Le `` de l'enchaineur est le nom de l'application déclarée.
+
+
+### Définition d'une catégorie de variables
+
+Les *définitions de catégories de variables* ont la forme suivante :
+```
+variable (saisie | calculee) (: attribut )? ;
+```
+
+avec :
+
+* ` ::= +` est le nom de la catégorie de variables;
+* ` ::= , …` représente l'ensemble de ses attributs.
+
+### Déclaration d'une variable
+
+La forme des *types de variables *est comme suit :
+
+```
+ ::= BOOLEEN | DATE_AAAA | DATE_JJMMAAAA | DATE_MM | ENTIER | REEL
+```
+
+#### Variable saisie
+
+Les *déclarations de variables saisies* ont la forme suivante :
+
+```
+ : saisie alias : type ;
+```
+
+avec :
+
+* ` ::= +`
+* ` ::= restituee? `
+* ` ::= = `
+
+Le `` est le nom de la variable.
+
+#### Variable calculée
+
+Les *déclarations de variables calculées* ont la forme suivante :
+```
+
+: (table [ ])? calculee (base? ^ restituee?)
+: type ;
+```
+
+Le est le nom de la variable. Si c'est un tableau, l'
+est sa taille.
+
+### Déclaration d'une erreur
+
+Les *déclarations d'erreurs* ont la forme suivante :
+```
+ : : : : : : ;
+```
+avec :
+* ` ::= anomalie | discordance | informative`
+
+Le symbole est le nom de l'erreur.
+% A faire: documenter les s !
+
+### Déclaration d'une fonction externe
+
+Les *déclarations de fonctions* externes ont la forme suivante :
+
+```
+ : fonction ;
+```
+
+Le `` est le nom de la fonction, et l' son arité.
+
+### Définition d'un domaine de règles
+
+Les *défintions de domaines de règles* ont la forme suivante :
+
+```
+domaine regle ;
+```
+
+avec :
+* ` ::= +` est le nom du domaine de règles.
+* ` ::= (: specialise )? ^ (: calculable)? ^ (: par_defaut)?
+* ::= , …` représente l'ensemble des domaines de règles que spécialise ce domaine.
+
+### Définition d'un domaine de vérifications
+
+Les *définitions de domaines de vérifications* ont la forme suivante :
+
+```
+domaine verif ;
+```
+
+avec :
+* ` ::= +` est le nom domaine de vérifications que spécialise ce domaine.
+* ` ::= (: specialise )? ^ (: autorise )? ^ (: par_defaut)? ^ (: verifiable)?`
+* ` ::= , …`
+* ` ::= * | saisie (* | ) | calculee (* | base)?` représente les catégories des variables autorisées à êtres utilisées dans les vérifications de ce domaine.
+
+### Déclaration d'une sortie
+
+Les *déclarations de sorties* ont la forme suivante :
+```
+sortie ( ) ;
+```
+
+### Indices
+
+Les *indices* ont la forme suivante :
+
+```
+ ::= ; …
+ ::= = , …
+```
+
+avec :
+* ` ::= [a-z]`
+* ` ::= [A-Z]`
+* ` ::= + | .. | (.. | - )?`
+
+
+### Expressions
+
+Les *expressions atomiques* ont la forme suivante :
+
+```
+ ::=
+( )
+| (<= | >= | < | > | != | =)
+| non? dans ( )
+| (present | non_present) ( ([ ])? )
+
+ ::=
+|
+|
+| [ ]
+| ( ( , …)? )
+| somme ( : )
+| si ( )
+ alors ( )
+ (( sinon ))?
+ finsi
+```
+
+avec :
+* ` ::= | ou `
+* ` ::= | et `
+* ` ::= | non `
+* ` ::= | (+ | -) `
+* ` ::= | (* | /) `
+* ` ::= | - `
+* ` ::= , …`
+* ` ::= (.. )?`
+
+
+Les `formules` ont la forme suivante :
+```
+ ::=
+ ([ ])? =
+```
+
+Les `multi-formules` ont la forme suivante :
+```
+ ::= pour :
+```
+
+### Instructions
+
+Les *instructions* ont la forme suivante :
+```
+ ::=
+
+ |
+ | si
+ alors +
+ (sinon +)?
+ finsi
+ | calculer domaine +;
+ | calculer enchaineur ;
+ | calculer cible
+ (: avec , …)?;
+ | verifier domaine +
+ (: avec );
+ | (afficher | afficher__erreur) +;
+ | iterer
+ : variable
+ : categorie + , …
+ (: avec )?
+ : dans ( + )
+ | restaurer
+ (
+ : , …
+ | : variable : categorie + , …
+ (: avec )?
+ )+
+ : apres ( + )
+ | leve__erreur ?;
+ | (
+ nettoie__erreurs
+ | exporte__erreurs
+ | finalise__erreurs
+ ) ;
+ | aiguillage (nom)? () : ()
+ | stop ?
+```
+
+avec :
+
+```
+ ::=
+
+ | `*(*` `*)*`
+ (`*:*` (`*..*` )?)?
+ | (`*nom*` | `*alias*`) `*(*` `*)*`
+ | `*indenter*` `*(*` `*)*`
+
+ ::= *
+
+ ::=
+ cas : +
+ | cas indefini : +
+ | cas : +
+ | par_default : +
+
+ ::=
+ application
+ | cible
+ | fonction
+ |
+```
+
+Les *instructions simples* ont la forme suivante :
+
+```
+ ::=
+
+ |
+ | `*si*`
+ `*alors*` +
+ (`*sinon*` +)?
+ `*finsi*`
+ | (`*afficher*` | `*afficher__erreur*`) + `*;*`
+```
+
+### Définition d'une règle
+
+Les *règles* ont la forme suivante :
+```
+ ::=
+ regle .. :
+ (
+ application : , … ;
+ ^^ (enchaineur : , … ;)?
+ ^^ (variable temporaire : , … ;)?
+ )
+ +
+```
+
+avec :
+
+* ` ::= ([