This is an old revision of the document!
Le but du devoir est de créer le tableau de symboles et d'écrire l'analyse sémantique pour le langage Alf.
Vous recevrez un AST de l'analyseur qui analyse correctement une source de langue Alf et doit écrire:
@var i:int ← 3;', seront remplacés par un noeud d'attribution
i ← 3;
- la list des erreurs
<note>
Toutes les trois exigences sont vérifiées et classées séparément. Les exemples qui ne produisent pas d'erreurs recevront des points d'erreur uniquement si le tableau de symboles et le nouvel AST sont corrects.
</note>
Le programme recevra deux paramètres de la ligne de commande:
* le fichier source
* le fichier de sortie
<code bash>
noeud main.js source.alf source.alf.json
</code>
===== Le fichier de grammaire Alf =====
Vous pouvez utiliser votre fichier de grammaire ou le fichier reference
===== Conseils pour résoudre le devoir =====
* Faire le tableau des symboles
* Déterminer tous les types de variables dans le tableau des symboles
* Déterminer les types pour toutes les instructions qui retournent un résultat
* Lors de la détermination des types, écrivez les erreurs
===== Fichier de sortie =====
Le format du fichier de sortie est le suivant
<code javascript>
{
symbol_table: […], le tableau symbol_table
ast: […], l'ast avec le type pour un noeud qui retourne une valeur
error_list: [] la liste des erreurs
}
</code>
===== Tableau des symboles =====
Le tableau des symboles est un objet Javascript, ou chaque propriété est le nom d'un contexte. Dans l'exemple ci-dessous, on peut voir qu'il y a 2 contextes:
* script - le contecte du script principal
* function_sum - le contexte généré par la fonction sum
<code javascript>
{
“script”: {
“type”: “script”,
“variables”: {},
“functions”: {
“sum”: {
“type”: “int”,
“parameters”: [
{
“type”: “int”,
“title”: “n1”,
“line”: 4
},
{
“type”: “int”,
“title”: “n2”,
“line”: 4
}
],
“line”: 4
}
},
“types”: {}
},
“function_sum”: {
“title”: “sum”,
“type”: “function”,
“parent”: “script”,
“variables”: {
“n1”: {
“type”: “int”,
“parameter”: true,
“index”: 0
},
“n2”: {
“type”: “int”,
“parameter”: true,
“index”: 1
}
},
“functions”: {},
“types”: {}
}
}
</code>
Lors de la détermination de la table de symboles, ajoutez à chaque noeud AST un paramètre symbole_table avec le nom du tableau de symboles ou il a les variables, fonctions et types.
==== Objet de contexte ====
Les objets de contexte stockent
* la variable déclarée dans ce contexte
* la fonction déclarée dans ce contexte
* les types (array, struct) déclarés dans ce contexte
* l'identifiant de contexte parent (position dans le tableau symbol_table)
* le nom du contexte
* le type du contexte (script, statements ou function)
* le nom de la fonction, si le contexte est de type 'function'
<note>
Les objets de contexte sont générés par
* le module principal
* une définition de message
* une classe
</note>
L'objet ressemble à:
<code javascript>
{
“variables”: { un dictionnaire des variables
“variable_name”: {
“type”: type de la variable
“line”: la ligne où la variable a été déclarée
“value”: l'expression que la variable a initialement (facultatif, si elle a ete definie avec une valeur)
}
},
“functions”: { un dictionnaire des fonctions
function_title”: {
“type”: le type de retour de la fonction
“parameters”: [] la liste des paramètres que la fonction prenne (le noeud parameters de l'AST)
“line”: la ligne où la fonction a été déclarée
}
},
“types”: { un dictionnaire de types
“type”: {
“type”: le type de la nouvelle classe de type ou tableau
“line”: la ligne où le type a été déclaré
pour le tableau
“elements_type”: le type de chaque élément du tableau
“first”: le premier index
“length”: numero d'elements
pour la classe
“properties”: [ une liste d'éléments de tableau (le noeud de l'AST)
{
“type”:
“title”:
“value”:
“line”:
“symbol_table”:
},
…
]
}
},
“parent”:
“type”:
}
</code>
=== Noms des contextes ===
- script
- script
- function
- titre de la fonction
- if_then
- loop_when
- loop_go
===== Le nouvel AST =====
L'AST donné par le parser doit etre transformé afin de ne plus contenir de variables, fonctions ou définitions de types.
Le nouvel AST sera une liste d'objets, chaque objet étant soit le script, soit une fonction.
<code javascript>
[
“script”: {
statements: [
…
]
},
“function_title”: {
statements: [
…
]
}
]
</code>
==== Définition des variables ====
Les définitions des variables seront écrites dans le tableau de symboles. La définition sera supprimée de l'AST (elle ne sera pas placée dans les statements). Si la définition inclut une attribution @var x: int ← 7;
, elle sera remplacée par un noeud d'attribution equivalent a x ← 7;
.
==== Définition des types ====
Les structures et les vecteurs sont des définitions des types. Ils seront écrits dans la partie types
du tableau de symboles.
Pour struct, si les propriétés ont des valeurs par défaut, chaque déclaration de variable de la structure sera remplacée par des attribution pour toutes les propriétés. Il y a un example dans le repository.
===== Vérification des types dans l'AST =====
==== Type de retour d'expression ====
Pour chacun des noeuds suivants, déterminez le type de retour
* expr
* value
* identifier
* return
* element_of_vector
* property
* function
Définissez le type en ajoutant une propriété type dans le noeud.
Tous les autres éléments ont le type de retour none
. S'il y a une erreur de types, le type sera error.
<note>
Au moment de la recherche d'une variable, l''algorithme est:
- recherche dans le contexte local
- si on n'obtient pas un résultat, recherche dans le contexte parent
</note>
=== Exemple ===
<code javascript>
{
“id”: “expr”,
“op”: ”+”,
“left”: {
“id”: “value”,
“type”: “int”,
“value”: “2”,
“line”: 3,
“symbol_table”: “script”,
},
“right”: {
“id”: “value”,
“type”: “int”,
“value”: 3,
“line”: 3,
“symbol_table”: “script”
},
“line”: 3,
“symbol_table”: script,
“type”: “int”
}
</code>
==== Vérifier les types ====
Pour tous les noeuds AST, vérifiez que les types correspondent:
* attributions sont faisables
* les expressions peuvent être calculées
* l'expression if / while / repeat a une valeur logique
* la variable est un nombre / string / boolean
* que les variables sont définies avant d'être utilisées
* les fonctions sont définies avant d'être utilisées
* les index de tableau sont des nombres
* les propriétés de la classe existent
* la variable pour element_of_array est un tableau
* la variable pour une propriété est une classe
* les variables ne sont pas redéfinies
* les fonctions ne sont pas redéfinies
* les types ne sont pas redéfinis
<note>
C'est là que la plupart des erreurs apparaissent.
</note>
===== Liste d'erreurs =====
La liste d'erreurs est un tableau qui contient des objets d'erreur. L'ordre dans lequel ces erreurs figurent dans la liste vous appartient.
==== Format d'objet d'erreur ====
Chaque erreur a le format suivant:
<code javascript>
{
type: chaîne avec le type d'erreur
elements: {
éléments pour l'erreur, chaque type d'erreur a des éléments différents
line:
},
text: le message d'erreur
}
</code>
==== Type d'erreur ====
Le type d'erreur est une chaîne avec l'un des titres suivants
=== VARIABLE_ALREADY_DEFINED ===
L'erreur se produit lorsqu'une définition de variable est répétée.
== Eléments ==
<code javascript>
{
variable: nom de la variable
}
</code>
=== FUNCTION_ALREADY_DEFINED ===
L'erreur se produit lorsqu'une définition de fonction est répétée.
== Eléments ==
<code javascript>
{
function: nom de la fonction
}
</code>
=== TYPE_ALREADY_DEFINED ===
L'erreur se produit lors de la répétition d'une définition de type (tableau ou struct).
== Eléments ==
<code javascript>
{
type: nom du type
}
</code>
=== STRUCT_PROPERTY_ALREADY_DEFINED ===
L'erreur se produit lorsqu'une définition d'élément struct est répétée.
== Eléments ==
<code javascript>
{
type: nom du type de structure
title: nom de l'élément
}
</code>
=== ARRAY_INDEX_VALUE ===
L'erreur se produit lorsque l'index inférieur du tableau est supérieur à l'index supérieur
== Eléments ==
<code javascript>
{
array: nom du type de tableau
length:
}
</code>
=== TYPE_RESOLUTION ===
L'erreur se produit lorsque le type d'une variable n'est pas déterminable (bonus uniquement).
== Eléments ==
<code javascript>
variable
{
variable: le nom de la variable avec le type non résolu
}
struct property
{
struct: nom du type de structure
property: nom de l'élément struct avec le type non résolu
}
</code>
=== UNDEFINED_FUNCTION ===
L'erreur se produit lorsqu'un appel de fonction est effectué sur une fonction qui n'est pas définie.
== Eléments ==
<code javascript>
{
title: nom du message
}
</code>
=== UNDEFINED_VARIABLE ===
L'erreur se produit lorsqu'une variable non définie est utilisée.
== Eléments ==
<code javascript>
{
variable: nom de la variable
}
</code>
=== UNDEFINED_TYPE ===
L'erreur se produit lorsqu'un type qui n'est pas défini est utilisé.
== Eléments ==
{
value: le type qui n'est pas definit
}
=== NOT_STRUCT_PROPERTY ===
L'erreur se produit lorsqu'un élément ne fait pas partie de cette structure.
== Eléments ==
<code javascript>
{
type: nom de la structure
title: nom de l'élément
}
</code>
=== NOT_STRUCT ===
L'erreur se produit lorsqu'une propriété est demandée pour une variable qui n'est pas un type de classe
== Eléments ==
<code javascript>
{
type: type réel que la variable est (au lieu d'un type struct)
}
</code>
=== NOT_ARRAY ===
L'erreur se produit lorsqu'un index est demandé pour une variable qui n'est pas un tableau
== Eléments ==
<code javascript>
{
type: type réel que la variable est (au lieu d'un type de tableau)
}
</code>
=== ARRAY_INDEX_TYPE ===
L'erreur se produit lorsqu'un index pour un tableau n'est pas un nombre ou un symbole
== Eléments ==
<code javascript>
{
type:
}
</code>
=== RETURN_OUTSIDE_MESSAGE ===
L'erreur se produit lorsqu'une instruction de valeur (noeud de retour) est utilisée en dehors d'un message
== Eléments ==
<code javascript>
{
vide
}
</code>
=== TYPE_EXPRESSION ===
L'erreur se produit lorsqu'une expression a des types incompatibles
== Eléments ==
<code javascript>
left op right
{
left:
right:
op:
}
op value
{
value:
op:
}
if, loop-go, loop-when
{
exp: expression type
op: if, while, repeat
} from: provided type
assign
{
to: to type
op: ”←”
from: from type
}
return
{
op: “return”
to: type de return
from: type
}
iteration (for i in exp go)
{
op: “iteration”
value: the exp type
}
typecast
{
op: “typecast”,
to: to type,
from: from type
}
=== LEXICAL ===
Ceci est une erreur lexicale.
== Eléments ==
{
line: le numéro de ligne
text: le texte de l'erreur
}
</ code>
=== SYNTAXE ===
Ceci est une erreur de syntaxe
== Eléments ==
<code javascript>
{
line: le numéro de ligne
text: le texte de l'erreur
token: le jeton obtenu
expected: [] / la liste des jetons attendus
}
</code>
===== Bonus =====
Pour un 0.5p supplémentaire, trouver le type de variables qui sont déclarées en utilisant juste une attribution.
<note>
Le bonus ne sera attribué que si tous les autres tests réussissent.
</note>
===== Copiage =====
Le devoir est individuel. Toute tentative de copiage entraînera 0p pour les devoirs. Système anti-copiage automatisé sera utilisé.
===== Questions =====
Si vous avez des questions concernant les devoirs, posez-les en postant un problème sur le github repository avec le format de titre [semantic] <votre titre de la question> . Vous aurez besoin d'un compte github pour cela.
<note warning>
NE POSEZ AUCUN CODE . Ceci est considéré comme copiage et vous aurez 0p pour ce devoir.
</note>
Si vous souhaitez recevoir un e-mail lorsque des problèmes sont signalés ou lorsqu'il y a de nouveaux messages, accédez au site github repository et cliquez sur Watch .
===== Tests =====
Les devoirs seront testés automatiquement en utilisant un ensemble de tests publics et privés.
==== Tests publics ====
Vous pouvez télécharger les tests publics de GitHub repository.
Pour exécuter les tests, téléchargez le contenu du référentiel dans le directoire avec les devoirs. Entrez dans le directoire verify et exécutez ./run_all.sh.
<code bash>
cd verify
./run_all.sh
</code>
Vous aurez besoin de bash pour ça. Vous pouvez utiliser Linux ou Windows Linux Subsystem.
<note>
Pour installer nodejs sous Linux ou Windows Linux Subsystem, procédez comme suit:
<code bash>
wget https://nodejs.org/dist/v8.9.4/node-v8.9.4-linux-x64.tar.xz
tar xvfJ node-v8.9.4-linux-x64.tar.xz
cd node-v8.9.4-linux-x64
sudo cp -R * /usr
</code>
</note>
==== Tests privés ====
Lors du téléchargement des devoirs, il est possible qu'on a des tests privés à faire passer. vmchecker les exécutera.
<note>
Vous pouvez toujours télécharger les devoirs autant de fois que vous le souhaitez jusqu'à la date limite. Cela va exécuter tous les tests pour vous et afficher le résultat.
</note>
===== Télécharger les devoirs =====
Le devoir doit être téléchargé sur vmchecker. Connectez-vous avec votre nom d'utilisateur moodle, sélectionnez le cours Automates et Langages Formelles (FILS) et téléchargez homework archive.
==== Readme ====
Le fichier readme a le format suivant:
<code>
Nom complet
Groupe
Une explication comment vous avez écrit vos devoirs, qu'avez vous utilisé, quelles sont les idées principales.
</code>
==== Archive des devoirs ====
Pour télécharger vos devoirs, suivez les instructions suivantes:
- Créer une archive zip (pas rar, ace, 7zip ou autre) conten
* votre fichier principal
* votre fichier grammar.jison
* vos fichiers javascript (*.js)
* le fichier package.json
* le fichier Readme
- Connectez-vous avec vmchecker
- sélectionner les Automates et Langages Formelles (FILS) cours
- sélectionnez 4. Sémantique
- télécharger l'archive
<note>
L'archive doit contenir les fichiers dans sa racine, pas dans un directoire. NE PAS archiver un dossier avec des fichiers, archiver DIRECTEMENT les fichiers.
NE PAS inclure node_modules .
</note>
Lorsque l'archive est téléchargée, vmchecker va exécuter:
<code bash>
unzip archive.zip homework
cd homework
npm install
echo '{ “node”:true, “esnext”:true }' > .jshintrc
jshint *.js
</code>