Phases de compilation avec exemple, processus et étapes

⚡ Résumé intelligent

Les phases du compilateur décrivent comment un compilateur transforme le code source en code machine à travers six étapes : analyse lexicale, analyse syntaxique, analyse sémantique, génération de code intermédiaire, optimisation du code et génération de code, le tout pris en charge par la gestion de la table des symboles et la gestion des erreurs.

  • 🔤 Analyse lexicale : La première phase analyse le code source et regroupe les caractères en jetons, remplissant ainsi la table des symboles.
  • 🌳 Analyse syntaxique : Les jetons sont vérifiés par rapport aux règles grammaticales et organisés dans un arbre d'analyse syntaxique.
  • Analyse sémantique : Le compilateur vérifie la compatibilité des types et leur signification à l'aide de l'arbre syntaxique et de la table des symboles.
  • (I.e. Intermédiaire Code: Une représentation indépendante de la machine, telle qu'un code à trois adresses, est générée pour faciliter la traduction.
  • | Optimisation: Le code redondant et inaccessible est supprimé afin de rendre le programme plus rapide et plus compact.
  • Code Génération: La phase finale convertit le code optimisé en code machine cible, en allouant les registres et la mémoire.

Quelles sont les phases de conception du compilateur ?

Compilateur fonctionne en différentes phases, chaque phase transforme le programme source d'une représentation à une autre. Chaque phase prend les entrées de son étape précédente et transmet sa sortie à la phase suivante du compilateur.
Il y a 6 phases dans un compilateur. Chacune de ces phases aide à convertir la langue de haut niveau en code machine. Les phases d'un compilateur sont :

  1. Analyse lexicale
  2. Analyse syntaxique
  3. Analyse sémantique
  4. Générateur de code intermédiaire
  5. Code optimiseur
  6. Code générateur
Phases du compilateur
Phases du compilateur

Toutes ces phases convertissent le code source en le divisant en jetons, en créant des arbres d'analyse et en optimisant le code source par différentes phases.

Phase 1 : Analyse lexicale

L'analyse lexicale est la première phase au cours de laquelle le compilateur analyse le code source. Ce processus peut être effectué de gauche à droite, caractère par caractère, et regrouper ces caractères en jetons.
Ici, le flux de caractères du programme source est regroupé en séquences significatives en identifiant les jetons. Il entre les tickets correspondants dans la table des symboles et transmet ce jeton à la phase suivante.
Les principales fonctions de cette phase sont :

  • Identifier les unités lexicales dans un code source
  • Classez les unités lexicales en classes comme les constantes, les mots réservés et saisissez-les dans différents tableaux. Il ignorera les commentaires dans le programme source
  • Identifier le jeton qui ne fait pas partie du langage

Exemple:
x = y + 10

Tokens

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. Il détermine si un texte suit ou non le format attendu. L'objectif principal de cette phase est de s'assurer que le code source écrit par le programmeur est correct ou non.
L'analyse syntaxique est basée sur les règles basées sur le langage de programmation spécifique en construisant l'arbre d'analyse à l'aide de jetons. Il détermine également la structure de la langue source et la grammaire ou syntaxe de la langue.
Voici une liste des tâches effectuées au cours de cette phase :

  • Obtenir des jetons de l'analyseur lexical
  • Vérifie si l'expression est syntaxiquement correcte ou non
  • Signaler toutes les erreurs de syntaxe
  • Construire une structure hiérarchique connue sous le nom d'arbre d'analyse

Exemple

Tout identifiant/numéro est une expression
Si x est un identifiant et y+10 est une expression, alors x= y+10 est une instruction.
Considérez l'arbre d'analyse pour l'exemple suivant

(a+b)*c

Exemple d'analyse syntaxique

Dans l'arbre d'analyse

  • Noeud intérieur : fiche avec un opérateur déposé et deux fiches pour enfants
  • Feuille : enregistrements avec 2 champs ou plus ; un pour le jeton et d'autres informations sur le jeton
  • Veiller à ce que les composantes du programme s’emboîtent de manière significative
  • Rassemble les informations de type et vérifie la compatibilité des types
  • Vérifie que les opérandes sont autorisés par la langue 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.
Semantic Analyser vérifiera les incompatibilités de type, les opérandes incompatibles, une fonction appelée avec des arguments inappropriés, une variable non déclarée, etc.
Les fonctions de la phase d'analyse sémantique sont :

  • Vous aide à stocker les informations de type recueillies et à les enregistrer dans la table des symboles ou l'arborescence syntaxique
  • Vous permet d'effectuer une vérification de type
  • Dans le cas d'une incompatibilité de type, lorsqu'il n'existe pas de règles de correction de type exactes satisfaisant 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 la langue 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 transtypera l'entier 30 en float 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 de niveau machine. Ce code intermédiaire doit être généré de manière à faciliter sa traduction dans le code machine cible.
Fonctions de niveau intermédiaire Code génération:

  • Il doit être généré à partir de la représentation sémantique du programme source
  • Contient les valeurs calculées pendant le processus de traduction
  • Vous aide à traduire le code intermédiaire dans la langue cible
  • Vous permet de conserver l’ordre de priorité de la langue source
  • Il contient le nombre correct d'opérandes de l'instruction

Exemple

Par exemple,

total = count + rate * 5

Le code intermédiaire à l’aide de 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 est l'optimisation du code ou code intermédiaire. Cette phase supprime les lignes de code inutiles et organise la séquence d'instructions pour accélérer l'exécution du programme sans gaspiller de ressources. L'objectif principal de cette phase est d'améliorer le code intermédiaire pour générer un code qui s'exécute plus rapidement et occupe moins d'espace.
Les principales fonctions de cette phase sont :

  • Il 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 du code rationalisé toujours en représentation intermédiaire
  • Suppression du code inaccessible et suppression des variables inutilisées
  • Supprimer les instructions qui ne sont pas modifiées de 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 des phases d'optimisation du code et produit le code de page ou 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 la variable. Les instructions du code intermédiaire sont converties en instructions machine. Cette phase convertit le code d'optimisation ou intermédiaire dans le langage cible.
La langue cible est le code machine. Par conséquent, tous les emplacements mémoire et registres sont également sélectionnés et attribués au cours de cette phase. Le code généré par cette phase est exécuté pour prendre les entrées et générer les sorties attendues.

Exemple

une = b + 60.0
Serait éventuellement traduit en registres.

MOVF a, R1
MULF #60.0, R2
ADDF R1, R2

Gestion des tables de symboles

Une table de symboles contient un enregistrement pour chaque identifiant avec des champs pour les attributs de l'identifiant. Ce composant permet au compilateur de rechercher plus facilement l'enregistrement d'identifiant et de le récupérer rapidement. La table des symboles vous aide également pour la gestion du périmètre. La table des symboles et le gestionnaire d'erreurs interagissent avec toutes les phases et la table des symboles est mise à jour en conséquence.

Routine de gestion des erreurs

Dans le processus de conception du compilateur, une erreur peut survenir dans toutes les phases indiquées ci-dessous :

  • Analyseur lexical : jetons mal orthographiés
  • Analyseur de syntaxe : parenthèse manquante
  • Générateur de code intermédiaire : opérandes incompatibles pour un opérateur
  • Code Optimiseur : Lorsque l’instruction est inaccessible
  • Code Generator: Lorsque la mémoire est pleine ou que les registres appropriés ne sont pas alloués
  • Tables de symboles : erreur de plusieurs identifiants déclarés

Les erreurs les plus courantes sont les séquences de caractères non valides lors de l'analyse, les séquences de jetons non valides dans le type, les erreurs de portée et l'analyse dans l'analyse sémantique.
L'erreur peut survenir dans l'une des phases ci-dessus. Après avoir trouvé des erreurs, la phase doit traiter les erreurs pour poursuivre le processus de compilation. Ces erreurs doivent être signalées au gestionnaire d'erreurs qui gère l'erreur pour effectuer le processus de compilation. Généralement, les erreurs sont signalées sous forme de message.

FAQ

La phase d'analyse (front-end) décompose le code source par une analyse lexicale, syntaxique et sémantique. La phase de synthèse (back-end) construit le programme cible par la génération de code intermédiaire, l'optimisation et la génération de code.

Un compilateur traduit l'intégralité du programme source en code machine avant de l'exécuter. Un interpréteur, quant à lui, traduit et exécute le code ligne par ligne, ce qui facilite le débogage mais est généralement plus lent à l'exécution.

Le code à trois adresses est une représentation intermédiaire où chaque instruction comporte au maximum trois opérandes, comme par exemple t1 = a + b. Il est simple à optimiser et facile à traduire en code machine cible.

L'IA et l'apprentissage automatique aident les compilateurs modernes à prendre des décisions d'optimisation plus intelligentes, comme le choix des transformations de boucles, l'intégration en ligne et l'allocation des registres. Ils prédisent quelles optimisations amélioreront les performances d'un programme et d'une cible donnés.

Oui. L'IA peut expliquer chaque phase avec des exemples. tracExpliquez comment une instruction type passe des jetons au code machine et répondez aux questions complémentaires. Cela facilite l'apprentissage de la conception de compilateurs pour les étudiants.

Résumez cet article avec :