1. Application des TAD à la construction d’analyseur
2.Exemples
d’instanciation de ce TAD générique
Voici maintenant dans un tout autre domaine une utilisation intéressante des TAD : il s’agit de la programmation par les grammaires qui fait partie du domaine de la compilation1. Comme exemple, nous allons construire un TAD générique de grammaire graphique, qui pourra être instancié en une grammaire quelconque de diagrammes syntaxiques. Nous nous servirons de ce TAD comme squelette de la construction d’un analyseur, puis ensuite nous verrons un autre TAD dérivé du premier permettant d’obtenir une spécification simple d’un générateur d’analyseur pour grammaire LL(1). Cet exercice part de la remarque que les diagrammes syntaxiques servent à décrire toutes les C-grammaires : ils représentent donc une abstraction générique.
Dans toute la suite les grammaires considérées sont des C-grammaires (type 2).
spécification
d’un générateur d’analyseur pour grammaire LL(1)
1.1 Un TAD générique
de grammaire graphique
Nous avons vu précédemment que les diagrammes syntaxiques sont une représentation graphique des règles d’une grammaire.
Nous allons établir une
spécification fondée sur les diagrammes syntaxiques comme
éléments de base, l’ensemble des diagrammes est noté
Diag.
Une grammaire est parfaitement définie par la donnée de :
son vocabulaire terminal VT, son vocabulaire auxiliaire VN et ses diagrammes
syntaxiques(ces dernières représentant l’axiome et les règles
de cette grammaire).
Nous proposons un type abstrait basé sur 8 opérateurs sur les diagrammes syntaxiques.
TAD : Diag
utilise : VT,
VN // les vocabulaires de la grammaire
opérations :
"tiÎ
Diag
(i ³1)
/ t1·ti
= ti·t1(élément
neutre)
ti(A)·tk(B) = ti(A)tk(B) (méthode de construction des diagrammes)
On rappelle que dans la représentation
en diagrammes syntaxiques, que le nom du paragraphe syntaxique A:, B:,
C: est un élément du vocabulaire auxiliaire VN. Il
correspond à la partie gauche de la règle.
Remarque :
l’opérateur t7 est redondant car il est possible de l’ exprimer à l’aide des 6 autres, par exemple : t7(B)=t5(t1,t3(t5(A,B))). |
2.1 Les identificateurs
pascal-like
Reprenons une grammaire déjà
utilisée auparavant, celle des identificateurs en pascal.
identif :
En utilisant le TAD Diag générique précédent, on obtient à partir des valeurs d’instanciation suivantes:
VN = { álettreñ,
áchiffreñ,
áidentifñ
}
VT = { 0,1,....,8,9,a,b,.....,z
}
(seuls VN,VT, et les axiomes changent les autres parties du TAD sont identiques)
Axiomes :
on obtient d’autres axiomes
en utilisant la transformation
t7(B)=t5(t1,t3(t5(A,B)))
Axiomes :
avec : VN ={álettreñ,áchiffreñ,áidentifñ,áinterneñ,ásortieñ,áboucleñ}
Ce dernier TAD correspond à une autre expression d’une grammaire des identificateurs pascal :
áidentifñ
:
áboucleñ
:
áinterneñ
:
Les deux autres diagrammes de
<lettre> et <chiffre> sont les mêmes que les précédents.
2.2 Les expressions arithmétiques
Soit une grammaire des expressions :
Nous obtenons pour <expr>
:
áexprñ
= t2(átermeñ)
·
t4(t5(‘+’,‘-‘
)·
t2(átermeñ))
De même pour átermeñ
:
átermeñ
= t2(áfactñ)
·
t4(t5(‘*’,’/’)·
t2(áfactñ))
Enfin pour áfactñ
les combinaisons d’opérateurs sont :
áfactñ
= t5(álettreñ,áchiffreñ,t2(‘(‘)·
t2(áexprñ)·
t2(‘)‘))
Pour áchiffreñ
et álettreñ
mêmes opérateurs que plus haut.
Nous laissons le soin au lecteur
d’écrire à l’aide du TAD Diag et des opérateurs fournis,
les axiomes du TAD grammaire graphique correspondant aux expressions.
A partir du TAD Diag de
grammaire graphique, nous proposons d’écrire un TAD GenerAnalyse
permettant de générer manuellement des squelettes pascal
permettant d’analyser chacun des opérateurs de Diag.
TAD : GenerAnalyse
utilise : Diag(instancié
Pascal),Pascal
opérations
:
Axiomes(de
traduction):
trad(t1)@ | if not sym in Follow(A) then Err; |
trad(t2(A)) @ si A ÎVN alors : | if
sym in Init(A) then
begin A ; if not(sym in Follow(A) then Err end else Err |
trad(t2(A))@ si A ÎVT alors : | if sym=A then symsuiv else Err |
trad(t3(A)) @ si A ÎVN alors : | repeat
A ; if not sym in Follow(A) then Err until not(sym in Init(A)); |
trad(t3(A))@ si A ÎVT alors : | repeat
symsuiv; until sym <>A ; |
trad(t6(B,C))@ selon que B ou C sont dans VT ou dans VN : | |
trad(t4(A)) @ si A ÎVT alors : | if
sym=A
then
while sym=A do symsuiv else if not sym in Follow(B) then Err |
trad(t4(A)) @ si A ÎVN alors : | if
sym=A
then
while sym in Init(A) do begin A ; if not sym in Follow(A) then Err end else if not sym in Follow(B) then Err |
trad(t5(A1,...,An))@ soit Ai ÎVN et Aj ÎVT alors : | ..........
if sym in Init(Ai) then begin Ai ; if not sym in Follow(Ai) then Err end else .......... if sym=Aj then symsuiv .......... else Err |
trad(t7(A,B))@ si A ÎVT alors : | if
sym=A
then
while sym=A do symsuiv else if not sym in Follow(B) then Err |
trad(t7(A,B)) @ si A ÎVN alors : | if
sym=A
then
while sym in Init(A) do begin A ; if not sym in Follow(A) then Err end else if not sym in Follow(B) then Err |
Application - exercice
Ecrivez et programmez
l’analyseur engendré par le TAD GenerAnalyse défini précédemment
instancié sur la grammaire des identificateurs Pascal-like. Pour
vous aider, voici une partie des déclarations ce ce programme:
Axiomes :
áidentifñ
= t2(<lettreñ)·
t7(álettreñ,áchiffreñ)
álettreñ
= t5(a,b,.....,z)
áchiffreñ
= t5(0,1,....,8,9)
procedure init;
begin
procedure symsuiv;
begin
procedure Err(num:integer);
begin
procedure init_ens;
begin
procedure identif;forward;
procedure lettre;forward;
procedure chiffre;forward;
{<identif> = t2(<lettre>)
·
t7(<lettre>,<chiffre>)}
procedure identif;
begin
procedure lettre;
begin
procedure chiffre;
begin
begin{prog-principal}