Table des symboles
Pr ZEGOUR DJAMEL EDDINE
Ecole Supérieure d’Informatique (ESI)
www.zegour.uuuq.com
email: [email protected]
Table des symbolesIntroduction
Symboles
Portée des symboles
Types
Univers
Rôles de la table des symboles
1. Elle range tous les noms déclarés avec leurs attributs• type• valeur (pour les constantes)• adresse (pour les variables locales et les paramètres de procédures)• paramètre (pour les procédures)• ...
2. Elle est utilisée pour retrouver les attributs d’un nom
• Fonction : nom (type, value, adresse, ...)
Contenu de la table des symboles• Les nœuds de symbole : information sur les noms déclarés• Les nœuds de Structure : information sur les types déclarés
C’est plus commode de l’implémenter par une structure de données dynamique :- liste linéaire chaînée- arbre binaire- Hash-code
Table des symboles comme une liste
Soient les déclarations suivantes
const int n = 10;class T { ... }int a, b, c;void M () { ... }
Nous obtenons la liste linéaire chaînée suivante Pour chaque nom déclaré il existe un nœud de symbole
+ simple+ l’ordre des déclarations est retenu (important si les adresses sont attribuées plus tard)
- lent s’il existe beaucoup de déclarations
Interface de base
public class Tab {public static Symbol Insert (Symbol.Kinds kind, string name, ...);public static Symbol Find (string name);
}
"n"Const
"T"Type
"a"Field
"b"Field
"c"Field
"M"Meth
Table des symboles comme un arbre binaireDéclarations
const int n = 10;class T { ... }int a, b, c;void M () { ... }
Arbre binaire résultant
+ rapide
- l’arbre peut dégénérer sauf s’il est équilibré- Consommation de la mémoire- l’ordre des déclarations est perdu
Utile seulement s’il y a beaucoup de déclarations"n"Const
"M"Meth
"b"Field
"c"Field
"a"Field
"T"Type
Table des symboles comme une table hash-codeDéclarations
const int n = 10;class T { ... }int a, b, c;void M () { ... }
Table hash-code résultante
+ rapide
- plus compliqué qu’une liste- l’ordre des déclarations est perdu
Pour notre propos une liste est suffisante• Chaque étendue (portée) est une liste de ses propres déclarations• Une étendue a à peine plus de 10 noms
"n"Const
"M"Meth
"b"Field
"c"Field
"a"Field
"T"Type
0
1
2
3
Table des symbolesIntroduction
Symboles
Portée des symboles
Types
Univers
Les nœuds de symboleChaque nœud déclaré est rangé dans un nœud de symbole
Sortes courants de symboles • constantes• variables globales• champs• paramètres• variables locales• types• méthodes• programme
public enum Kinds {Const,Global,Field,Arg,Local,Type,Meth,Prog
}
Quelles sont les informations désirées sur les objets?• pour tous les symboles nom, type structuré, sorte de symbole, ..• pour les constantes valeur• pour les paramètres adresse (= ordre de déclaration)• pour les variables locales adresse (= ordre de déclaration)• pour les méthodes nombre d’arguments et variables locales,
symboles locaux (paramètres + variables locales)• pour le programme symboles globaux(= locaux au programme)• pour les variables globales, champs, types, ….
La classe des symboles
class Symbol {public enum Kinds { Const, Global, Field, Arg, Local, Type, Meth, Prog }
Kinds kind;string name;Struct type;Symbol next;int val; // Const: valueint adr; // Arg, Local: addressint nArgs; // Meth: number of argumentsint nLocs; // Meth: number of local variablesSymbol locals; // Meth: parameters & local variables; Prog: symbol table of program
}
Const"n"
10----
const int n = 10;class T { ... }int a, b;void M (int x, int y)
char ch;{ ... }
kindnamenextvaladrnArgsnLocslocals
Type"T"
-----
Global"a"
-----
Global"b"
-----
Meth"M"
--21
Arg"x"
-0---
Exemple
Local"ch"
-0---
Arg"y"
-1---
Défini plus loin
Introduction des noms dans la table des symbolesLa méthode suivante est appelée quand un nom est déclaré
Symbol sym = Tab.Insert(kind, name, type);
• Crée un nouveau nœud d’objet avec kind, name, type• Vérifie si name est déjà déclaré (si c’est le cas => message d’erreur)• Attribuer des adresses successives aux variables et champs• Entrer le niveau de déclaration pour les variables (Global, Local,…)• Ajouter le nouveau nœud en fin de la liste linéaire des symboles• Retourner le nouveau nœud à l’appelant
Exemple d’appel à la méthode Insert()
VarDecl<Symbol.Kinds kind>= Type<type>
ident (. Tab.insert(kind, name, type); .){ ";" ident (. Tab.insert(kind, name, type); .)}.
Les symboles (noms) prédéfinis
Exemples de noms prédéfinis ?
• Types standards : int, char• Constants standards : null• Fonctions Standards : ord(ch), chr(i), len(arr)
On peut aussi ranger les noms prédéfinis dans la table des symboles ("Univers")kindnamevaladrnArgsnLocslocals
Type"int"
-----
Type"char"
-----
Const"null"
0----
Meth"ord"
--10
Meth"chr"
--10
Meth"len"
--10
kindnamevaladrnArgsnLocslocals
Arg"ch"
-0---
Arg"i"-0---
Arg"arr"
-0---
Noms spéciaux comme des mot-clés
int et char peuvent aussi être implémentées comme des mot-clés.
Exige un traitement spécial dans la grammaire
Type<Struct type>= ident (. Symbol sym = Tab.Find(token.str); type = sym.type; .)| "int" (. type = Tab.intType; .)| "char" (. type = Tab.charType; .).
C’est plus simple de les avoir pré déclarés dans la table des symboles
Type<Struct type>= ident (. Symbol sym = Tab.Find(token.str); type = sym.type; .)
+ traitement uniforme pour les noms pré déclarés et les noms utilisateur- on peut re déclarer "int" comme un type utilisateur
Table des symbolesIntroduction
Symboles
Portée des symboles
Types
Univers
Portée = Domaine où l’objet est valide(connu)
Il y a des portées séparées (listes d’objets) pour• L’ "univers" contient les noms pré définis ( on ajoute le symbole ‘P’ pour programme)• Le programme contient noms globaux (= constantes, variables globales, classes, méthodes)• Chaque méthode contient les noms locaux (= arguments et variables locales)• Chaque classe contient des champs
Exemple
class P
int a, b;
{
void M (int x)
int b, c;
{
...
}
...
}
Portée M(tous les noms déclarés dans M)
Portée P(tous les noms déclarés dans P)
univers(noms pré déclarés)
• La recherche d’un nom commence toujours dans topScope• Si non trouvé, la recherche continue dans la prochaine portée englobante (outer)• Exemple: rechercher b, a et int
"x"locals
"b" "c"
"a" "b" "M"
outer
"int" "char" "P"
topScope
...
Les nœuds d’une portée
class Scope {Scope outer; // vers la portée englobanteSymbol locals; // vers les symboles de cette portéeint nArgs; // nombre of arguments de cette portée (pour l’attribution des adresses)int nLocs; // nombre de variables locales dans cette portée (pour l’attribution des adresses)
}
Méthode pour l’ouverture d’une portée
static void OpenScope () { // in class TabScope s = new Scope();s.nArgs = 0; s.nLocs = 0;s.outer = topScope;topScope = s;
}
• Appelée au début d’une méthode ou une classe• Relie la nouvelle portée avec celles existantes• La nouvelle portée devient topScope• Tab.Insert() crée toujours des symboles dans topScope
Méthode pour la fermeture d’une portée
static void CloseScope () { // in class TabtopScope = topScope.outer;
}
• Appelée à la fin d’une méthode ou une classe• La prochaine portée englobante(outer) devient topScope
Introduction des noms dans une portéeLes noms sont toujours introduit dans topScope
class Tab {static Scope topScope; // pointer to current scope...static Symbol Insert (Symbol.Kinds kind, string name, Struct type) {
//--- create symbol nodeSymbol sym = new Symbol(name, kind, type);
if (kind == Symbol.Kinds.Arg) sym.adr = topScope.nArgs++;else if (kind == Symbol.Kinds.Local) sym.adr = topScope.nLocs++;
//--- insert symbol nodeSymbol cur = topScope.locals, last = null;while (cur != null) {
if (cur.name == name) Error(name + " declared twice");last = cur; cur = cur.next;
}if (last == null) topScope.locals = sym; else last.next = sym;return sym;
}...
}
Struct : Défini plus loin
Ouverture et fermeture d’une portée
Remarques• Le nom de la méthode est introduit dans la portée englobant la méthode
• Avant de fermer une portée, les objets locaux sont attribués au champ locals de la méthode en cours
• Même principe pour les classes(les portées sont aussi ouvertes et fermés pour les classes)
MethodDecl (. Struct type; .)= Type<type>
ident (. curMethod = Tab.insert(Symbol.Kinds.Meth, token.str, type);Tab.OpenScope();
.)..."{"..."}" (. curMethod.nArgs = topScope.nArgs;
curMethod.nLocs = topScope.nLocs;curMethod.locals = Tab.topScope.locals;Tab.CloseScope();
.).
variable globale
Exemple
class P "int" "char" "P"
topScope
Tab.OpenScope();
...
Exemple
class Pint a, b;
{
"a" "b"
topScope
Tab.Insert(..., "a", ...);Tab.Insert(..., "b", ...);
"int" "char" "P"...
Exemple
class Pint a, b;
{void M ()
topScope
Tab.Insert(..., "M", ...);Tab.OpenScope();
"M""a" "b"
"int" "char" "P"...
Exemple
class Pint a, b;
{void M ()
int x, y;
topScope
Tab.Insert(..., "x", ...);Tab.Insert(..., "y", ...);
"x" "y"
"M""a" "b"
"int" "char" "P"...
Exemple
class Pint a, b;
{void M ()
int x, y;{
...} topScope "x" "y"
meth.locals =Tab.topScope.locals;
Tab.CloseScope();
"M""a" "b"
"int" "char" "P"...
Exemple
class Pint a, b;
{void M ()
int x, y;{
...}...
}
topScopeprog.locals =Tab.topScope.locals;
Tab.CloseScope();
"x" "y"
"M""a" "b"
"int" "char" "P"...
Recherche des noms dans la table des symboles
La méthode suivante est appelée quand un nom est utilisé
Symbol sym = Tab.Find(name);
Si un nom est non trouvé la méthode retourne un symbole spécial : noSym
• Symbole pré déclaré• Mieux que null, car il évite les effets de bord
(exceptions)
kindnametypevaladrnArgsnLocslocals
Const"noSymbol"
0000
noSym
noType
static Symbol Find (string name) {for (Scope s = topScope; s != null; s = s.outer)
for (Symbol sym = s.locals; sym != null; sym = sym.next)if (sym.name == name) return sym;
Parser.Error(name + " is undeclared");return noSym;
}
• La recherche commence dans topScope• Si non trouvé, la recherche continue dans la portée englobante (pointeur outer )
x b clocals
a b m
outer
int char
topScope
Table des symbolesIntroduction
Symboles
Portée des symboles
Types
Univers
Les types
Chaque objet a un type avec les propriétés suivantes
• taille • structure (champs pour les classes, type des éléments pour les tableaux, ...)
Sortes de types ?• types primitives (int, char)• tableaux• classes
Les types sont représentés par des nœuds de structure
class Struct {public enum Kinds { None, Int, Char, Arr, Class }
Kinds kind;Struct elemType; // Arr: element typeSymbol fields; // Class: list of fields
}
Nœuds de structure pour les types primitifs
Nœud d’objet
Nœud de structure
Il existe un seul nœud de structure pour le type int dans toute la table des symboles.Tous les symboles de type int référencent celui-ci.
Même chose pour le nœud de structure correspondant au type char.
Local"a"
-0---
int a, b;char c;
kindnametypenextvaladrnArgsnVarslocals
Local"b"
-1---
Local"c"
--2---
kindelemTypefields
Int--
Char--
Nœuds de structure pour les tableaux
La longueur d’un tableau peut ne pas être connue au moment de la compilation.Elle sera déterminée à l’exécution.
Local"a"
-0---
int[] a;int b;
kindnametypenextvaladrnArgsnVarslocals
Local"b"
--1---
kindelemTypefields
Arr
-
Int--
Nœuds de structure pour les classes
Field"x"
-----
Type"C"
-----
class C {int x;int y;int z;
}C v;
kindnametypenextvaladrnArgsnVarslocals
Global"v"
------
kindelemTypefields
Class-
Int--
kindnametypenextvaladrnArgsnVarslocals
Field"y"
-----
Field"z"
-----
Table des symbolesIntroduction
Symboles
Portée des symboles
Types
Univers
Structure de l "univers"
kindnametypevaladrnArgsnLocslocals
Type"int"
-----
Type"char"
-----
Const"null"
0----
Meth"chr"
--1-
Meth"ord"
--1-
Meth"len"
--1-
Arg"i"
-0---
Arg"ch"
-0---
Arg"arr"
-0---
Int--
Char--
Class--
Arr
-
Const"noSymbol"
0----
None--
intType charType nullType noType
chrSym ordSym lenSym noSym
kindelemTypefields
Interface de la table des symboles
class Tab {static Scope topScope; // current top scope
static Struct intType; // predefined typesstatic Struct charType;static Struct nullType;static Struct noType;
static Symbol chrSym; // predefined symbolsstatic Symbol ordSym;static Symbol lenSym;static Symbol noSym;
static Symbol Insert (Symbol.Kinds kind, string name, Struct type) {...}static Symbol Find (string name) {...}static void OpenScope () {...}static void CloseScope () {...}
static void Init () {...} // builds the universe and initializes Tab}