Qu’est-ce qu’une conception de compilateur ? Types, outils de construction, exemple
⚡ Résumé intelligent
Les phases du compilateur décrivent les six étapes qui transforment le code source en code machine : analyse lexicale, analyse syntaxique, analyse sémantique, génération de code intermédiaire, optimisation du code et génération de code, prises en charge par la gestion de la table des symboles et la gestion des erreurs.
Quelles sont les phases de conception du compilateur ?
A Compilateur Le compilateur fonctionne en plusieurs phases, chacune transformant le programme source d'une représentation à une autre. Chaque phase reçoit les données de la phase précédente et transmet sa sortie à la phase suivante. Un compilateur comporte six phases. Chacune d'elles contribue à la conversion du langage de haut niveau en code machine. Les phases d'un compilateur sont :
- Analyse lexicale
- Analyse syntaxique
- Analyse sémantique
- Générateur de code intermédiaire
- Code optimiseur
- Code générateur
Phases du compilateur
Toutes ces phases transforment le code source en le divisant en jetons, en créant des arbres d'analyse syntaxique et en optimisant le code source à travers différentes phases.
Phase 1 : Analyse lexicale
L'analyse lexicale est la première phase, durant laquelle le compilateur parcourt le code source. Ce processus s'effectue de gauche à droite, caractère par caractère, et regroupe ces caractères en jetons.
Ici, le flux de caractères provenant du programme source est regroupé en séquences significatives grâce à l'identification des jetons. Les jetons correspondants sont ensuite insérés dans la table des symboles et transmis à l'étape suivante.
Les principales fonctions de cette phase sont :
- Identifier les unités lexicales dans un code source.
- Classez les unités lexicales en catégories telles que les constantes et les mots réservés, et enregistrez-les dans des tables distinctes. Les commentaires du programme source seront ignorés.
- Identifiez un jeton qui ne fait pas partie de la langue.
Exemple : x = y + 10
| Token | Type |
|---|---|
| X | identifiant |
| = | Opérateur d'assignation |
| Y | identifiant |
| + | Opérateur d'addition |
| 10 | Numéro |
Phase 2 : Analyse syntaxique
L'analyse syntaxique consiste à découvrir la structure du code. Elle détermine si un texte respecte le format attendu. L'objectif principal de cette phase est de s'assurer de la validité du code source écrit par le programmeur.
L'analyse syntaxique repose sur les règles du langage de programmation concerné et consiste à construire l'arbre d'analyse syntaxique à l'aide de jetons. Elle détermine également la structure du langage source ainsi que sa grammaire ou syntaxe.
Voici la liste des tâches effectuées au cours de cette phase :
- Obtenez les jetons à partir de l'analyseur lexical.
- Vérifiez si l'expression est syntaxiquement correcte ou non.
- Signalez toutes les erreurs de syntaxe.
- Construisez une structure hiérarchique appelée arbre d'analyse syntaxique.
Exemple
Tout identificateur/nombre est une expression. Si x est un identificateur et y+10 une expression, alors x = y+10 est une instruction. Considérons l'arbre d'analyse syntaxique pour l'exemple suivant :
(a+b)*c
Dans l'arbre d'analyse syntaxique :
- Nœud interne : enregistrement avec un champ opérateur et deux champs pour les enfants.
- Feuille : enregistrements comportant 2 champs ou plus ; un pour le jeton et d’autres informations concernant le jeton.
- Veillez à ce que les composantes du programme s'articulent de manière cohérente.
- Recueille les informations de type et vérifie la compatibilité des types.
- Les opérandes de vérification sont autorisés par le langage source.
Phase 3 : Analyse sémantique
L'analyse sémantique vérifie la cohérence sémantique du code. Il utilise l'arbre syntaxique de la phase précédente ainsi que la table des symboles pour vérifier que le code source donné est sémantiquement cohérent. Il vérifie également si le code véhicule une signification appropriée.
L'analyseur sémantique vérifiera les incompatibilités de types, les opérandes incompatibles, une fonction appelée avec des arguments incorrects, une variable non déclarée, etc.
Les fonctions de la phase d'analyse sémantique sont les suivantes :
- Permet de stocker les informations de type collectées et de les enregistrer dans la table des symboles ou l'arbre syntaxique.
- Permet d'effectuer une vérification de type.
- En cas d'incompatibilité de type, lorsqu'il n'existe pas de règles de correction de type exactes permettant de réaliser l'opération souhaitée, une erreur sémantique est affichée.
- Collecte les informations de type et vérifie la compatibilité des types.
- Vérifie si le langage source autorise ou non les opérandes.
Exemple
float x = 20.2; float y = x*30;
Dans le code ci-dessus, l'analyseur sémantique convertira l'entier 30 en nombre flottant 30.0 avant la multiplication.
Phase 4 : Intermédiaire Code Génération
Une fois la phase d'analyse sémantique terminée, le compilateur génère du code intermédiaire pour la machine cible. Ce code représente un programme pour un certain nombre d'abstractions.tracmachine t.
Le code intermédiaire se situe entre le langage de haut niveau et le langage machine. Ce code intermédiaire doit être généré de manière à faciliter sa traduction en code machine cible.
Fonctions intermédiaires Code génération:
- Elle devrait être générée à partir de la représentation sémantique du programme source.
- Contient les valeurs calculées lors du processus de traduction.
- Permet de traduire le code intermédiaire dans le langage cible.
- Permet de conserver l'ordre de priorité du langage source.
- Il contient le nombre correct d'opérandes de l'instruction.
Exemple
Par exemple :
total = count + rate * 5
Le code intermédiaire obtenu grâce à la méthode du code d'adresse est :
t1 := int_to_float(5)
t2 := rate * t1
t3 := count + t2
total := t3
Lot 5: Code Optimisation
La phase suivante consiste à optimiser le code intermédiaire. Cette phase supprime les lignes de code inutiles et réorganise la séquence d'instructions afin d'accélérer l'exécution du programme sans gaspiller de ressources. L'objectif principal est d'améliorer le code intermédiaire pour générer un code plus rapide et moins gourmand en espace.
Les principales fonctions de cette phase sont :
- Cela vous aide à établir un compromis entre la vitesse d'exécution et la vitesse de compilation.
- Améliore le temps d'exécution du programme cible.
- Génère un code simplifié, toujours sous forme de représentation intermédiaire.
- Suppression du code inaccessible et des variables inutilisées.
- Suppression des instructions qui n'ont pas été modifiées dans la boucle.
Exemple : Considérez le code suivant :
a = intofloat(10)
b = c * a
d = e + b
f = d
Peut devenir :
b = c * 10.0
f = e + b
Lot 6: Code Génération
Code La génération est la dernière phase d'un compilateur. Elle reçoit les données issues de la phase d'optimisation du code et produit le code objet. Son objectif est d'allouer de la mémoire et de générer du code machine relogeable.
Il alloue également des emplacements mémoire pour les variables. Les instructions du code intermédiaire sont converties en instructions machine. Cette phase convertit le code optimisé ou intermédiaire dans le langage cible.
Le langage cible est le code machine. Par conséquent, toutes les adresses mémoire et tous les registres sont sélectionnés et alloués lors de cette phase. Le code généré est ensuite exécuté pour recevoir des entrées et produire les sorties attendues.
Exemple
a = b + 60.0 pourrait éventuellement se traduire en registres comme suit :
MOVF a, R1 MULF #60.0, R2 ADDF R1, R2
Gestion des tables de symboles
Une table des symboles contient un enregistrement pour chaque identificateur, avec des champs pour ses attributs. Ce composant facilite la recherche et la récupération rapide des identificateurs par le compilateur. La table des symboles simplifie également la gestion de la portée. La table des symboles et le gestionnaire d'erreurs interagissent avec toutes les phases d'exécution, et la table des symboles est mise à jour en conséquence.
Routine de gestion des erreurs
Lors de la conception d'un compilateur, des erreurs peuvent survenir dans toutes les phases suivantes :
- Analyseur lexical : Jetons mal orthographiés.
- Analyseur syntaxique : Parenthèse manquante.
- Générateur de code intermédiaire : Opérandes incompatibles pour un opérateur.
- Code Optimiseur: Lorsque la requête est inaccessible.
- Code Generator: Lorsque la mémoire est pleine ou que les registres appropriés ne sont pas alloués.
- Tableaux de symboles : Erreur liée à la présence de plusieurs identificateurs déclarés.
Les erreurs les plus courantes sont les séquences de caractères invalides lors de l'analyse, les séquences de jetons invalides lors de la saisie, les erreurs de portée et les erreurs d'analyse sémantique.
L'erreur peut survenir à n'importe quelle étape du processus. Après la détection des erreurs, l'étape concernée doit les traiter pour poursuivre la compilation. Ces erreurs doivent être signalées au gestionnaire d'erreurs, qui les prend en charge afin de mener à bien la compilation. Généralement, les erreurs sont signalées sous forme de message.



