This is an old revision of the document!
Parsez le fichier source SUPERFILS et générez un arbre de syntaxe abstraite JSON(AST).
Le devoir reçoit un ou deux paramètres de la ligne de commande. Le premier paramètre est le nom du fichier avec le script SuperFILS, le deuxième est le fichier de sortie. Si le fichier de sortie manque, son nom est identique au fichier de sortie, en ajoutant l'extension ”.json”.
node main.js script.sf script.sf.json
Ici il y a des conseils pour résoudre le devoir:
Essayez d'exécuter de petits scripts pour tester toutes les fonctionnalités.
Si vous utilisez Sublime Text, vous pourriez utiliser cela fichier mise en évidence de la syntaxe pour écrire le langage SuperFILS.
Vous pouvez lire ici comment ajouter le fichier.
Tous les noeuds de l'AST ont la forme suivante:
{ type:"node_type" }
La liste des types de noeuds est la suivante: * script - un script
Le langage est un langage typé SuperFILS défini comme:
* Définitions des variables * Définitions des fonctions * Définitions des structures (nouveau type de données) * Définitions des arrays (nouveau type de données) * Expressions * Valeurs * Attributions * Exécution des fonctions * Branche (if) * Boucle (while, for ou repeat)
<Note> Les instructions sont séparées par des lignes nouvelles. Cela signifie qu'il n'y a qu'une seule instruction sur une ligne.
a <- 10 b <- 5
</note>
Les valeurs sont:
7
7.5
"s"
"this is a text"
false
null
Les commentaires sont des parties ignorées du fichier source. Ils sont enfermés entre ”<*” et “*>” et ne sont pas imbriqués.
<*Texte pour décrire le script*> var a:float
Un identificateur peut être n'importe quelle valeur qui commence par une lettre, $ ou _ et qui peut contenir aussi des nombres dans son nom.
identifier $identifier _identifier
{ type:"identifier", id:"identifier_name" }
Une valeur est un nombre entier, un nombre réel, un logique (true ou false) ou une chaîne de caractères.
5674 5674.432 true "a" "string"
{ type:"value", t:"value_type", // int, float, symbol, boolean, string value:actual_value }
var variable_name :[variable_type] [<- value or expression], ...
var a:int <- 5 var b:float var c:<- true, d:<- 4.5
* int - nombre entier * float - nombre à virgule flottante
* string - texte * boolean - true ou false * défini par l'utilisateur (struct, array)
{ type:"define", elements:[ // array of variables { type:"data type", id: "variable name" }, ] }
struct struct_name: var element_name:data_type [<- initial_value] ... ... endstruct
{ type:"struct", id:"struct_name", elements:[ // array of elements { type:"element data type", id: "element name", value: "element value" // if it exists } ] }
array array_name:data_type integer_number, integer_number
{ type:"array", id: array_name, element_type: elements_data_type, from: from_integer_number, to: to_integer_number }
array_name[index]
{ type: "element_of_array", array: array_identifier, index: index_identifier }
Operator | Precedence |
---|---|
= != | Low |
> >= < ⇐ | |
and or xor | |
not | |
+ - | |
* / mod | High |
3.6 + 5 2 * 10 + 19 variable + 5 x > y x = y 2 + (x + y) * (5 + 6)
{ type:"expression", op:"operator", left:left_operand, right:right_operand }
<Note> L'opérateur '-' a un AST différent s'il est utilisé comme un unaire (ex: -50)
{ type:"expression", op:"negative", value:50 }
</note>
variable <- expression
x <- 1000 s <- "text" + "s" y <- valueof f -> () a[i] <- 900 q.element <- "this is a text"
{ type:"attribution", to: { ... id, element_of_struct, element_of_array }, from: { ... expression } }
function function_name:[function_type][(parameter1:parameter1_type, ...)] return statement;
function function_name:[function_type][(parameter1:parameter1_type, ...)] { statemet ... statement }
function f:(x:int, y:float) { var a: <- x + y return a }
function f:float (x:int, y:float) return x + y
function f:float (x:int, y:float){ var p:int var i:int if n = 0 { for i, 1 to n, 1 { p = p * a } } return p }
{ type:"define_function", id:"function_name", parameters:[ // array of parameters { type:"data type", id: "parameter name" }, ], value_type:"le type retourné par la fonction", statements:[ // array des intructions (meme s'il y a seulement un) ... ] }
Il s'agit des instructions qui définissent la valeur de retour de la fonction.
return x + y
{ type:"value_of_function", value: { ... } }
Il existe seulement un façon d'exécuter une fonction: en utilisant valueof.
valueof function_name -> ([parameter1 <- expression1, parameter2 <- expression2, parameter3 <- expression3, ...)]
s <- valueof sum -> (n1 <- 3, n2 <- 5) valueof getdir -> ()
{ type:"valueof", function: { id:"function_name", }, parameters:{ // dictionnaire des valeurs des parametres "parameter1": parameter_value, ... } }
if expression { ... }
if expression { ... } elseif { ... } else{ ... }
{ type:"if", expression: expression, then: [ // liste d'instructions ] }
{ type:"if", expression:expression, then: [ // liste d'instructions ], else: [ // liste d'instructions ] }
Il y a deux types de boucles: while et for.
while expression { ... }
do { ... } while expression
{ type:"while", expression:expression, statements: [ // liste d'instructions ] }
for variable_name, expression to expression, expression_for_nr_of_steps { ... }
{ type:"for", variable:variable_name, from:expression, to:expression, step:expression, statements: [ // liste d'instructions ] }
Si le fichier source a des erreurs, vous devez avoir un output dans le JSON avec l`erreur. Il y a deux types des erreurs: * lexicale (token inconnu) * syntaxe (token inattendu)
Pour n`importe quel erreur lexicale, on a:
{ error:"lexical", line: line_number, text: "text that is not recognised" } </code> ==== Syntaxe ==== Pour n`importe quel erreur de syntaxe, on a: <code javascript> { error:"syntax", line: line_number, token: "token that the parser saw", // le nom du token ne va pas être vérifié par le checker expected: [liste des tokens attendus] // le nom du token ne va pas être vérifié par le checker } </code> <note warning> Les noms des tokens seront différents pour chacun d`entre vous, il seront ignorés par le checker. Le checker vérifiera seulement si vous avez un token dans le token item et dans la liste. </note> <note>Le nombre des lignes commence avec 1</note> ===== Tester ===== Le devoir va être testé automatiquement en utilisant un set avec des tests publics et privés. ==== Les tests publics ==== Vous pouvez télécharger les tests publics de GitHub [[https://github.com/alexandruradovici/alf-alfy-language-public|repository]]. Pour exécuter les tests, télécharger le contenu du repository dans un dossier avec le devoir. Entrez dans le dossier //verify// et exécuter ./run_all.sh. <code bash> cd verify ./run_all.sh
Vous devez avoir bash pour faire ça. Vous pouvez utiliser soit Linux, soit Windows Linux Subsystem.
wget https://nodejs.org/dist/v6.10.0/node-v6.10.0-linux-x64.tar.xz tar xvfJ node-v6.10.0-linux-x64.tar.xz cd node-v6.10.0-linux-x64 sudo cp -R * /usr
Quand vous téléchargez le devoir, c`est possible que vous avez des tests nécéssaires qu`il doit passer. vmcheker va les exécuter.
Le devoir doit être télécharger sur vmchecker. Connectez vous avec votre nom d`utilisateur de moodle, séléctionnez le course Automates et Langages Formelles (FILS) et téléchargez le homework archive.
Le fichier Readme doit avoir le format suivant:
Votre nom complet Groupe Une explication comment vous avez écrit le devoir, qu`est-ce que vous avez utilisé, quels sont les idées principales.
Pour télécharger le devoir, je vous en prie de suivre les pas suivants:
NE PAS inclure node_modules.
Quand l`archive est téléchargée, vmcheker va tester:
unzip archive.zip homework cd homework # if the file yarn.lock exists yarn # else npm install echo '{ "node":true, "loopfunc": true, "esnext":true }' > .jshintrc jshint *.js jison alfy.jison -o alfy.js