format normal

Transcription

format normal
Examen de compilation
UFR IEEA
Licence info, S5
1ère session COMPIL -3h- Décembre 2009
FIL
Tous documents autorisés. Sujet : 3 pages
Exercice 1 : Analyse ascendante
Cet exercice concerne la reconnaissance des instructions produites par un locigiel de navigation embarqué.
Les instructions possibles sont : tourner (TURN), éventuellement au panneau (PAN), ou avancer (GO). On considère
la grammaire Gi suivante, d’axiome route et de terminaux { TURN, GO, PAN } :
route → inst | inst route
inst → GO | TURN panneau
panneau → ǫ | PAN
Cette grammaire n’est pas celle qui a été vue en TD.
Q 1.1 : Donner l’automate LR-AFD de Gi .
2
Q 1.2 : Gi est-elle LR(0) ? SLR(1) ? Justifier formellement.
2
Q 1.3 : Donner la suite des piles résultant de l’analyse SLR(1) pour les mots GO GO et TURN.
2
Exercice 2 : Grammaire réduite
Soit la grammaire G1 de terminaux {a, b}, d’axiome S, de non-terminaux {X1 , X2 , X3 , X4 , S} et de productions :
X3 → aX3 | bX3 | X3 X4
S → X1 S | X1
X4 → X4 X4 | b
X1 → X2 | bX1
X2 → b | bX2 | X3
Q 2. 1 : Donner une grammaire réduite équivalente à G1 , en donnant les détails des calculs. (attention à ne
pas modifier une production par inadvertance si vous recopiez la grammaire)
2
Exercice 3 : Analyse LL(1)
On s’intéresse dans cet exercice à la description des tâches dans un gestionnaire de tâches. Une tâche est
décrite par un identifiant (une chaı̂ne de caractères, par exemple "tp2"), une priorité optionnelle (une chaı̂ne
de caractères, par exemple "normale") et des dépendances optionnelles décrivants les tâches qui doivent être
terminées avant le début de celle-ci et les tâches qui ne peuvent commencer que si celle-ci est terminée. On aura
par exemple la tâche :
\begin{tache} "tp2" \prio "normale" \apres "tp1" "tp1bis" \avant "tp3" \end{tache}
Un gestionnaire de tâches possède un nom et une liste de tâches. On le décrit au moyen de la grammaire Gt
suivante, d’axiome gestionnaire et de terminaux { GEST TACHES, DEB, FIN, STRING, PRIO, APRES, AVANT } :
gestionnaire → GEST TACHES STRING listeTaches
listeTaches → ǫ | listeTaches tache
tache → DEB STRING description FIN
description → priorite dependances
priorite → PRIO STRING | ǫ
dependances → apres avant
apres → APRES listeIdentTaches | ǫ
avant → AVANT listeIdentTaches | ǫ
listeIdentTaches → STRING | STRING listeIdentTaches
1ère session COMPIL
Décembre 2009
1ère session COMPIL
Examen de compilation
Q 3.1 : Le langage L(Gt ) est-il régulier ? Justifier intuitivement.
2
Q 3.2 : Gt n’est pas LL(1), de manière évidente, à cause des productions :
listeTaches → ǫ | listeTaches tache
listeIdentTaches → STRING | STRING listeIdentTaches
En utilisant les techniques vues en cours, transformer ces productions pour qu’elles ne nuisent plus au caractère
LL(1) de la grammaire.
2
La nouvelle grammaire est appelée G′t . La suite de l’exercice peut être réalisée même si vous n’avez pas su
répondre à la question précédente (utiliser alors Gt ).
Q 3.3 : Calculer les ensembles Premier et Suivant pour les non-terminaux gestionnaire, description, avant et
listeIdentTaches, en explicitant les calculs intermédiaires.
2
Q 3.4 : Donner les lignes (ou les colonnes) correspondant aux non-terminaux gestionnaire, avant et description
de la table d’analyse LL(1) de G′t .
2
Q 3. 5 : En utilisant les conventions du cours, et en supposant donné un type TypeSymboles contenant les
valeurs abrégées { TS.GEST TACHES, TS.DEB, TS.FIN, TS.STRING, TS.PRIO, TS.APRES, TS.AVANT }, donner le
code Java des méthodes description() et avant().
2
Q 3.6 : On attribue G′t pour calculer un graphe de dépendances entre tâches et vérifier ainsi qu’il ne contient
pas de cycles. Le graphe est construit lors de l’analyse descendante. Il est créé au tout début de l’analyse, hérité
par listeTaches, puis synthétisé une fois complété. On aura par exemple la production suivante :
gestionnaire → GEST TACHES STRING listeTaches { listeTaches.grapheH = new Graphe()
gestionnaire.grapheS = listeTaches.grapheS }
En utilisant les mêmes conventions que précédemment, donner le code Java de la méthode gestionnaire qui
effectue les actions ci-dessus.
2
Exercice 4 : Grammaire attribuée
On s’intéresse aux expressions arithmétiques à la Scheme (langage fonctionnel) engendrées par la grammaire
Ge de terminaux {+, *, (, ), entier } et d’axiome E :
E → entier | ( op listeE )
listeE → E listeE | ǫ
op → + | *
Ge engendre par exemple les mots entier, (+), (* entier), (+ (* entier entier) entier entier).
Scheme évalue les expressions en partant du principe que l’élément neutre pour l’addition est 0 et l’élément
neutre pour la multiplication est 1. L’interprète Scheme donne donc :
> (+)
> (*)
> 5
0
1
5
> (+ 2)
> (* 2)
> (* 4 3 2)
2
2
24
> (+ 0)
> (* 0)
> (+ (* 4 2) 3 (* 2 2))
0
0
15
On suppose que le terminal entier possède un attribut val de type entier qui contient sa valeur, synthétisé
par l’analyseur lexical. On suppose donnée la classe Java Oper :
Décembre 2009
2
Licence info, S5
1ère session COMPIL
Examen de compilation
public class Oper {
...
/** opérateur d’addition. */
public static final Oper ADD = ... ;
/** opérateur de multiplication. */
public static final Oper MULT = ... ;
/** retourne le résultat de l’opération appliquée aux deux valeurs
passées en paramètre. */
public int eval(int x, int y) { ... }
/** retourne l’élément neutre de l’opération. */
public int valNeutre() { ... }
}
Q 4. 1 : Attribuez la grammaire Ge pour associer à l’axiome la valeur de l’expression reconnue en écrivant
les règles sémantiques en Java. Vous préciserez pour chaque attribut à quel non-terminal il est attaché, quel est
son type de données et s’il est hérité ou synthétisé.
2
Exercice 5 : TP Ava
L’exercice a pour but d’envisager une partie du travail à réaliser sur le compilateur réalisé en TP pour
rajouter à Ava le type flottant.
Les constantes de type flottant, par exemple 823.5, 2e-12, 3.12E5, ont le format suivant :
– elles commencent par une suite de chiffres non signée ;
– cette suite de chiffre est suivie d’une partie réelle et d’une partie exposant, ou d’une partie exposant seule,
ou d’une partie réelle seule ;
– la partie réelle commence par un point suivi d’une suite de chiffres ;
– la partie exposant commence par la lettre e ou E suivie d’une suite de chiffres éventuellement signée par
- ou +.
Les variables de type flottant sont déclarées par le mot-clé float. On aura par exemple par float x,y ;.
Les opérateurs utilisés dans les expressions entières peuvent aussi être utilisés sur des valeurs de type flottant,
à l’exception de l’opérateur modulo (mod). La règle de typage est la suivante : si au moins l’un des opérandes
est de type flottant, alors le résultat est de type flottant. Par exemple 5/2.5 est une division sur flottant qui
retourne un flottant, 5/2 est une division entière qui retourne un entier.
Au niveau des impressions, on ajoute le format %f pour imprimer un flottant, par exemple writeln(%f,
x+1). L’expression peut être de type entier (conversion de type implicite). De même, lors d’une affection d’une
expression à une variable de type flottant, l’expression pourra être de type flottant ou entier.
Q 5. 1 : Quel symboles devez-vous rajouter à votre analyseur lexical ? Donner une expression ou description
régulière pour chacun d’entre eux et préciser si ce symbole est prioritaire sur l’un des symboles existants. Il
n’est pas demandé d’utiliser la syntaxe de JFlex.
2
Q 5.2 : Quelles productions devez-vous ajouter à votre analyseur syntaxique ? Il n’est pas demandé d’utiliser
la syntaxe de Cup.
2
Q 5. 3 : Quelles opérations de contrôle / inférence de type (incluant les types entier et booléen) devez-vous
mettre en œuvre pour :
– la déclaration d’un identificateur de type flottant (on supposera que Type inclut la valeur Type.FLOTTANT) ;
– l’affectation ;
– l’addition.
Il n’est pas demandé de répondre en terme de visiteur mais seulement en terme de structure de données et de
typage.
2
Décembre 2009
3
Licence info, S5