Aller au contenu principal
Version: 2024

02 - Analyse syntaxique

Informations​

info

Deadline: le 25 avril, 23:59
Points: 2 points de la note finale
Lien: https://classroom.github.com/a/A5xk-pKC
Téléchargement tardif: 0.5p/jour (maximum 4 jours)

Demandes​

Analysez le fichier avec du code source dans le langage ALF et générez un arbre abstrait de syntaxe (AST). Utilisez un Visiteur pour réaliser une représentation à partir des classes de la bibliothèque de compilateur. Ensuite, affichez l'arbre obtenu sous la forme d'un JSON.

Vous recevrez le nom du fichier de la ligne de commande.

Syntaxe du langage ALF​

Le langage Alf est un langage typé qui contient les instructions suivantes:

  • définitions des variables
  • définitions des fonctions
  • définitions des classes (en tant que nouveau type de données)
  • définitions des listes (en tant que nouveau type de données)
  • expressions
  • attributions
  • appels des fonctions
  • branches (des instructions if)
  • boucles (while, for, repeat)

Les instructions sont séparées par ;.

Notations​

  • [facultatif]: ce qui se trouve entre [] est une partie optionnelle de l'instruction
  • <nom> : ce qui se trouve entre <> est seulement un modèle

Commentaires​

Les commentaires font partie du fichier source et ils sont ignorés. Ils sont encadrés par /* et */ et ne sont pas imbriqués. Ils peuvent s'étendre sur plusieurs lignes.

info

Tous les fichiers de test ont un commentaire sur la première ligne. Si votre grammaire n'a pas de règles pour les commentaires, vous pouvez tout simplement ignorer la première ligne.

/* Ceci est un texte pour décrire le script */
declare integer v = 5;

Types de données​

Nom du typeSignificationExemple d'une valeur
integernombre entier7
floatnombre réel7.5
charcaractère'a'
stringchaîne"ceci est une texte"
booleanvaleur logiquefalse
attention

Pour les valeurs et les variables avec les types integer et float, on vous demande d’utiliser I64 et F64 pour les noms des types. Par exemple, pour le code suivant:

45;

la sortie sera:

{
"@type" : "Module",
"block" : {
"@type" : "Block",
"statements" : [ {
"@type" : "Value",
"value" : "45",
"typeName" : "I64",
"line" : 1
} ],
"line" : 1,
"scope" : {
"@type" : "SymbolTable",
"variables" : { },
"types" : { },
"functions" : { }
}
},
"line" : 1,
"scope" : null
}

Valeurs​

Syntaxe:

<valeur>;

Exemples:

5;
"string";
true;
info

Les chaînes peuvent avoir les caractères spéciaux suivants:

  • ” - notée \”
  • \ - noté \
  • \r - noté \r
  • \n - noté \n
attention

Notre langage peut aussi contenir la valeur vide:

emtpy;

Expressions​

Priorité des opérateurs

OpérateurPriorité
*, /, modHaute
+, -
! (not logique)
and, or, xor
>, >=, <, <=
==, !=Bas

Exemples:

2+5;
2*4+5;
variable+5;
2+(x+y)*(exec func());
not true;

Déclarations des variables​

Syntaxe:

   declare [type_de_la_variable_1] <nom_de_la_variable_1> [ = <expréssion_1>] [, [type_de_la_variable_2] <nom_de_la_variable_2> [ = <expréssion_2>], ... ]

Exemples:

    declare a;
declare integer b;
declare boolean c = false;
declare integer d = 7, string e = "texte", float f = 3.14;

Les noms des variables sont des chaînes qui commencent par une lettre ou _ et peuvent contenir d’autres lettres ou des chiffres.

Exemples:

    var13
variable
_nomVar12
_a

Définitions des classes​

Syntaxe:

class <nom_de_la_classe>
[local <property_type> <property_name> [= <valeur_initiale>]]
...
...
end;

Exemple:

class person
local string name;
local integer age = 20;
end;

Accès aux propriétés d'une classe​

Syntaxe:

<nom_du_objet>.<nom_de_la_propriété>

Exemple:

p.name = "Un autre nom";

Définitions des listes​

De la même manière comme pour les classe, définir une liste en fait défini un nouveau type des données. Pour l’utiliser, il faut déclarer une variable de ce nouveau type (avec la syntaxe normale pour la déclaration des variables).

Syntaxe:

//note: dans ce cas, [] sont des parenthèses réelles et sont obligatoires
<nom_du_type_des_données> array <nom_du_type_de_liste>[<from>:<to>];

Exemple:

integer array exemple[1:9];

Accès aux éléments d’une liste​

Syntaxe:

//note: dans ce cas, [] sont des parenthèses réelles et sont obligatoires
<nom_de_la_variable_liste>[<index>]

Exemple:

v[5] = "New value inside the array";

Affectations​

Syntaxe:

<variable> = <expression>;

Exemples:

var2 = 2*4+5;
obj.classfield = true;
v[5] = "New value inside the array";

Définitions des fonctions​

Syntaxe:

function <nom_de_la_fonction>[([<type_paramètre_1> <nom_paramètre_1>[, <type_paramètre_2> <nom_paramètre_2>, ...]])] : <return_type> [=><expression>]
function <nom_de_la_fonction>[([<type_paramètre_1> <nom_paramètre_1>[, <type_paramètre_2> <nom_paramètre_2>, ...]])] : <return_type>
begin
<instructions>
end

Exemples:

function sample(float f1, float f2): integer;

function returns : string => "Fonction sans paramètres";

function withbody(integer i1, integer i2): integer
begin
s = i1 + i2;
end

L’instruction return​

Syntaxe:

return <expression>;

Exemples:

return s;

return 2*3+1;

Appel des fonctions​

Syntaxe

exec <nom_de_la_fonction>(<valeur_paramètre_1>, <valeur_paramètre_2>, ...);

Exemples:

exec write("Text");
s = exec _sum(2, 5);
exec getdir();

Branches​

Syntaxe

if <expression>
<instructions>
end;
if <expression>
<instructions>
else
<instructions>
end;

Exemples

if var1 > 2
exec function1(s);
else
s = s + 9;
end;

Boucles​

While​

Syntaxe

while <expression> start
<instructions>
finish;

Repeat​

Syntaxe

repeat 
<instructions>
while <expression>;

For​

Syntaxe

for <nom_de_variable> from <expression> to <expression> start
<instructions>
finish;

For iteration​

Syntaxe

for <nom_de_variable> in <nom_de_variable> start
<instructions>
finish;

Exemple de représentation JSON​

Pour afficher le résultat sous la forme d’un JSON, on va utiliser une instance de ObjectMapper de la manière suivante:

import com.fasterxml.jackson.databind.ObjectMapper

fun main(){
val serializer = ObjectMapper().writerWithDefaultPrettyPrinter()
val module: Module = ...
//votre code ici

//pour obtenir le JSON comme String (pour pouvoir l’écrire dans un fichier):
val jsonModule : String = serializer.writeValueAsString(module)
}

Pour le programme suivant:

/* Variable value Attribution */

declare integer n;

n = 6;

La sortie dans le format JSON sera:

{
"@type" : "Module",
"block" : {
"@type" : "Block",
"statements" : [ {
"@type" : "Group",
"declarations" : [ {
"@type" : "VariableDefinition",
"variable" : {
"@type" : "Identifier",
"title" : "n",
"typeName" : "I64",
"line" : 3
},
"init" : null,
"line" : 3
} ],
"line" : 3
}, {
"@type" : "Assignment",
"to" : {
"@type" : "Identifier",
"title" : "n",
"typeName" : null,
"line" : 5
},
"from" : {
"@type" : "Value",
"value" : "6",
"typeName" : "I64",
"line" : 5
},
"line" : 5
} ],
"line" : 3,
"scope" : {
"@type" : "SymbolTable",
"variables" : { },
"types" : { }
}
},
"line" : 3,
"scope" : null
}

Vous pouvez aussi regarder les testes ici.

Bonus​

Implantez une fonctionalité pour traiter les erreurs.

Si le fichier source contient des erreurs, vous devez générer un JSON avec elles. Il y a deux types d'erreurs:

  • lexicales (jéton pas reconnu)
  • syntaxe (jéton inattendu)

Au lieu d’afficher l’AST pour le code reçu, vous devez afficher une liste contenant toutes les erreurs, ordonées en fonction de la ligne sur laquelle elles se trouvent.

Pour le code suivant:


declare variable < integer;

La sortie sera:

[ {
"id" : "Syntax Error",
"line" : 2,
"charPosition" : 17,
"msg" : "no viable alternative at input 'variable<'"
} ]

Conseils d'implantation​

Pour chaque instruction possible du langage, on vous conseil de suivre les étapes suivantes:

  1. Écrivez les règles de la grammaire pour l’instruction.
  2. Implantez les fonctions du visiteur pour l’instruction.
  3. Testez votre implantation. Vous pouvez utiliser les données dans les testes.

Questions​

Si vous avez des questions concernant les devoirs, posez-les en publiant un problème sur le github repository pour les questions avec le format du titre [syntaxique]<titre de votre question>. Vous aurez besoin d'un compte github pour cela.

Attention

Ne postez pas de code. Cette action est considéré comme tentative de tricher et alors vous obtiendrez 0p pour le devoir.

Si vous souhaitez recevoir un e-mail lorsque des problèmes sont publiés ou lorsqu'il y a de nouveaux messages, accédez au repository pour les questions et cliquez sur Regarder.