Créer son propre langage de programmation de A à Z
<< Évolution 7 : Les chaînes de caractères (Partie 2 - Concaténation et ré-allocation dynamique de la mémoire) | Évolution 8 : Autres boucles for | Évolution 9 : Les nombres décimaux >>
Petite évolution celle-là aussi. On va ajouter deux nouvelles syntaxes possibles pour la boucle for. La première permet de définir un début et une fin avec un pas par défaut de 1. La seconde est équivalente, cette fois avec un pas que l'on peut définir.
Évolution 8 du langage :
⚠ (:source lang=bnf linenum:)
<boucle_for> ::= "(" <expression_arithmetique> ")" "x" <code> ";"
| "(" <expression_arithmetique> ":" <expression_arithmetique> ")" <code> ";"
| "(" <expression_arithmetique> ":" <expression_arithmetique> ":" <expression_arithmetique> ")" <code> ";"
(:sourcend:)
L'analyseur lexical ne change pas. On ne changera pas non plus le fichier d'entête. On aura le même numéro de nœud d'AST qui aura 4 enfants : début, pas, fin et du code.
Exemple :
Notre boucle for sera toujours de la forme (debut:pas:fin).
- (10)x équivaut à (0:1:10) - Début : 0, Pas : 1, Fin : 10
- (5:10) équivaut à (5:1:10) - Début : 5, Pas : 1, Fin : 10
On modifie surtout l'analyseur syntaxique Bison. On va construire des nœuds et les ajouter directement à la main dans le nœud de la boucle for :
⚠ (:source lang=c header="syntaxe_simple.y" linestart=220 linenum:)
boucle_for: TOK_PARG expression_arithmetique TOK_PARD TOK_CROIX bloc_code TOK_FINSTR{
$$=g_node_new((gpointer)BOUCLE_FOR);
g_node_append($$,g_node_new((gpointer)ENTIER));
g_node_append_data(g_node_nth_child($$,0),strdup("0"));
g_node_append($$,g_node_new((gpointer)ENTIER));
g_node_append_data(g_node_nth_child($$,1),strdup("1"));
g_node_append($$,$2);
g_node_append($$,$5);
}
|
TOK_PARG expression_arithmetique TOK_DOUBLE_POINT expression_arithmetique TOK_PARD bloc_code TOK_FINSTR{
$$=g_node_new((gpointer)BOUCLE_FOR);
g_node_append($$,$2);
g_node_append($$,g_node_new((gpointer)ENTIER));
g_node_append_data(g_node_nth_child($$,1),strdup("1"));
g_node_append($$,$4);
g_node_append($$,$6);
}
|
TOK_PARG expression_arithmetique TOK_DOUBLE_POINT expression_arithmetique TOK_DOUBLE_POINT expression_arithmetique TOK_PARD bloc_code TOK_FINSTR{
$$=g_node_new((gpointer)BOUCLE_FOR);
g_node_append($$,$2);
g_node_append($$,$4);
g_node_append($$,$6);
g_node_append($$,$8);
};
(:sourcend:)
Ensuite le générateur de code :
⚠ (:source lang=c header="generation_code.c" linestart=267 linenum:)
case BOUCLE_FOR:
fprintf(fichier,"\tint i%i;\n\tfor(i%i=",nb_boucle,nb_boucle);
genere_code(g_node_nth_child(ast,0));
fprintf(fichier,";i%i<",nb_boucle);
genere_code(g_node_nth_child(ast,2));
fprintf(fichier,";i%i+=",nb_boucle);
genere_code(g_node_nth_child(ast,1));
fprintf(fichier,"){\n");
nb_boucle++;
genere_code(g_node_nth_child(ast,3));
fprintf(fichier,"\t}\n");
break;
(:sourcend:)
On construit le compilateur et on teste :
⚠ (:source lang=text header="programme.simple" linenum:)
e_Monentier = 0;
<:vspace>
(10*(e_Monentier+1))x
afficher "Je dis 10x Salut !\n";
;
<:vspace>
e_Monentier2 = 10;
<:vspace>
(e_Monentier:e_Monentier2)
afficher "Je dis 10x Au Revoir !\n";
;
<:vspace>
(e_Monentier:2:e_Monentier2)
afficher "Je dis 5x Salut !\n";
;
<:vspace>
e_pas=1;
e_cumulpas=0;
<:vspace>
afficher "(";
(e_Monentier:e_pas:100)
afficher e_pas;
afficher " + ";
e_cumulpas+=e_pas;
e_pas++;
;
afficher 100-e_cumulpas;
afficher ") = 100\n";
(:sourcend:)
Le programme en Simple sort :
⚠ (:source lang=text:)
Je dis 10x Salut !
Je dis 10x Salut !
Je dis 10x Salut !
Je dis 10x Salut !
Je dis 10x Salut !
Je dis 10x Salut !
Je dis 10x Salut !
Je dis 10x Salut !
Je dis 10x Salut !
Je dis 10x Salut !
Je dis 10x Au Revoir !
Je dis 10x Au Revoir !
Je dis 10x Au Revoir !
Je dis 10x Au Revoir !
Je dis 10x Au Revoir !
Je dis 10x Au Revoir !
Je dis 10x Au Revoir !
Je dis 10x Au Revoir !
Je dis 10x Au Revoir !
Je dis 10x Au Revoir !
Je dis 5x Salut !
Je dis 5x Salut !
Je dis 5x Salut !
Je dis 5x Salut !
Je dis 5x Salut !
(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 9) = 100
(:sourcend:)
Voilà pour cette courte évolution. Pour l'évolution 9, on implémentera les nombres décimaux pour plus de précisions dans les calculs mathématiques avec Simple.
<< Évolution 7 : Les chaînes de caractères (Partie 2 - Concaténation et ré-allocation dynamique de la mémoire) | Évolution 8 : Autres boucles for | Évolution 9 : Les nombres décimaux >>
Thomas Tributsch - (CC BY-NC-SA 3.0 FR)