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.