I. Introduction▲
Le framework .NET expose des classes permettant d'accéder au compilateur C#. Au cours de cet article, nous verrons comment utiliser ces classes afin de créer notre propre compilateur C#.
II. Interface graphique▲
Nous allons commencer par réaliser l'interface graphique de notre application en WPF. Ouvrez Visual Studio et sélectionnez Fichier - Nouveau projet, puis choisissez Application WPF et appelez le « Compilateur » :

Nous allons ensuite ajouter une TextBox dans notre fenêtre principale. Celle-ci nous servira à écrire le code qui devra être compilé. Puis nous ajouterons un TabControl contenant deux TabItem. Ces deux TabItem serviront à afficher le résultat de la compilation et la liste des erreurs relatives au code. Nous ajouterons également un Button afin de générer le code et l'exécuter si la génération s'est déroulée avec succès. Votre fenêtre devrait normalement (ou à peu de choses près) ressembler à ceci :

A présent, nous pouvons passer au chapitre suivant ;)
III. Implémentation du code▲
III-A. Présentation de la classe CSharpCodeProvider▲
Comme je vous le disais en introduction, le framework .NET contient des classes permettant d'accéder aux instances du générateur de code et donc de pouvoir créer son propre compilateur. Dans le cadre de cet article, nous allons nous intéresser de plus près à la classe CSharpCodeProvider.
Cette classe est une classe dérivée de la classe de base CodeDomProvider et fournit l'accès au compilateur de code C#.
L'équivalent existe pour les langages VB et JScript.
III-B. Compilation du code▲
En premier lieu, nous allons ajouter au code behind, les instructions using suivantes :
using
System.
CodeDom.
Compiler;
using
Microsoft.
CSharp;
Nous allons ensuite créer l'événement Click du Button Build en double-cliquant sur celui-ci depuis le fichier .xaml puis implémenter sa logique. Tout d'abord, nous allons effacer le contenu des TextBox des onglets :
//
Cleaning
txtItemOutput
and
txtItemErrors
txtItemOutput
.
Text=
"
"
;
txtItemErrors
.
Text=
"
"
;
On va ensuite créer une instance de CodeDomProvider pour le langage C# :
//
Create
instance
of
CodeDomProvider
CodeDomProvider provider
=
CSharpCodeProvider.
CreateProvider
("
CSharp
"
);
La prochaine étape sera de préciser que nous souhaitons générer un fichier exécutable et spécifier son nom. Pour y parvenir, nous devons utiliser la classe CompilerParameters représentant la liste des paramètres d'un compilateur :
//
Name
of
.exe
file
string
Output=
"
MyProgram.exe
"
;
CompilerParameters parameters
=
new
CompilerParameters
();
//
Specify
we
want
an
.exe
file
instead
of
a
.dll
parameters
.
GenerateExecutable=
true
;
//
Name
of
output
assembly
parameters
.
OutputAssembly=
Output;
On passe maintenant à la partie « Compilation » en utilisant la méthode CompileAssemblyFromSource de l'objet provider. Cette méthode permet de compiler un assembly et renvoie un objet de type CompilerResults contenant le résultat de la compilation. Elle prend deux objets en paramètres. Tout d'abord un objet de type CompileParameters que nous avons créé précédemment puis un tableau de string contenant les sources à compiler.
CompilerResults results
=
provider.
CompileAssemblyFromSource
(parameters,
txtCodeSource.
Text);
La dernière étape consiste à vérifier si l'objet results contient des erreurs de compilation et le cas échéant, à l'indiquer dans l'onglet Output et afficher le détail dans l'onglet Errors :
if
(results.
Errors.
Count>
0
){
txtItemOutput
.
Text=
results.
Errors.
Count+
"
error(s).
See
Errors
Menu.
"
;
foreach
(CompilerError CompErrin
results.
Errors){
txtItemErrors
.
Text=
txtItemErrors.
Text+
"
Line
number
"
+
CompErr.
Line+
"
,
Error
Number:
"
+
CompErr.
ErrorNumber+
"
,
'
"
+
CompErr.
ErrorText+
"
;
"
+
Environment
.
NewLine+
Environment.
NewLine;
}
}
III-C. Exécution du code▲
Afin de pouvoir exécuter votre code, une nouvelle instruction using doit être ajouté à votre fichier .xaml :
using
System.
Diagnostics;
Cette instruction nous permet d'accéder à la classe Process, Nous allons ajouter une condition else gérant le cas où la compilation s'est déroulée sans erreurs :
else
{
//
Successful
Compile
txtItemOutput
.
Text=
"
Compile
successful!
"
;
Process
.
Start
(Output);
}
C'est aussi simple que ça :)
Voici le programme complet :
private
void
Build_Click
(object
sender,
RoutedEventArgs e){
//
Cleaning
txtItemOutput
and
txtItemErrors
txtItemOutput
.
Text=
"
"
;
txtItemErrors
.
Text=
"
"
;
//
Create
instance
of
CodeDomProvider
CodeDomProvider provider
=
CSharpCodeProvider.
CreateProvider
("
CSharp
"
);
//
Name
of
.exe
file
string
Output=
"
MyProgram.exe
"
;
CompilerParameters parameters
=
new
CompilerParameters
();
//
Specify
we
want
an
.exe
file
instead
of
a
.dll
parameters
.
GenerateExecutable=
true
;
//
Name
of
output
assembly
parameters
.
OutputAssembly=
Output;
CompilerResults results
=
provider.
CompileAssemblyFromSource
(parameters,
txtCodeSource.
Text);
if
(results.
Errors.
Count>
0
){
txtItemOutput
.
Text=
results.
Errors.
Count+
"
error(s).
See
Errors
Menu.
"
;
foreach
(CompilerError CompErrin
results.
Errors){
txtItemErrors
.
Text=
txtItemErrors.
Text+
"
Line
number
"
+
CompErr.
Line+
"
,
Error
Number:
"
+
CompErr.
ErrorNumber+
"
,
'
"
+
CompErr.
ErrorText+
"
;
"
+
Environment
.
NewLine+
Environment.
NewLine;
}
}
else
{
//
Successful
Compile
txtItemOutput
.
Text=
"
Compile
successful!
"
;
Process
.
Start
(Output);
}
}
Allez ! On se fait le classique Hello World ? :)
Exécutez votre programme et copier coller le code suivant dans la TextBox source :
using
System;
namespace
HelloWorld{
class
HelloWorld{
static
void
Main
(string
[
]
args){
Console
.
WriteLine
("
Hello
World!
"
);
Console
.
ReadLine
();
}
}
}
Normalement, vous devriez obtenir ceci :


La compilation et l'exécution se sont bien déroulées et en vérifiant dans le dossier bin/Debug de votre projet, un fichier .exe a bien été généré. Vous pouvez également modifier le code source de façon à générer une erreur et voir comment se comporte le programme.
IV. Conclusion▲
Dans cet article, nous avons vu qu'il n'était pas bien compliqué de réaliser un compilateur C#. Il ne vous reste plus qu'à l'améliorer à votre sauce en ajoutant d'autres fonctionnalités telles que la coloration syntaxique, la gestion des tabulations, etc..
V. Remerciements▲
Je tiens à remercier xxx et xxx pour la relecture attentive de cet article ainsi que les corrections apportées.