Devoir 4 - Sémantique

Information

Date limite: le 22 mai, 23h55
Points: 2 points hors de la note finale
Téléchargez le devoir: GitHub Devoir 4
Téléchargement tardif: 1 point / jour (maximum 3 jours)

Demande

L'objectif du devoir est de créer la table de symboles et d'écrire l'analyse sémantique pour le langage Alf.

Vous recevrez comme entrée un fichier qui contient un AST qui analyse correctement un langage source. Ce que vous devez faire est de générer:

  1. la table des symboles
  2. un nouvel AST avec les modifications suivantes
    1. le nouvel AST est une liste d'instructions (statements)
    2. tous les noeuds de l'AST ont une nouvelle propriété appellée symbol, qui fait référence a l'entrée du tableau de symboles ou ils déclarent des variables, fonctions et types
    3. le programme principal s'appelle “Statements”
  3. une liste des erreurs

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 la table de symboles et le nouvel AST sont corrects.

Le programme recevra deux paramètres de la ligne de commande:

  • le fichier source
  • le fichier de sortie
node main.js source.alf.ast.json source.alf.json

Conseils pour résoudre le devoir

  • Générer la table des symboles
  • Déterminer tous les types des variables dans la table des symboles
  • Déterminer les types pour toutes les instructions qui retournent un résultat (expressions, fonctions)
  • Intégration des messages d'erreur

Fichier de sortie

Le format du fichier de sortie est le suivant

{
    symbol_table: [...], // la table de symboles
    ast: [...], // le nouvel AST
    error_list: [] // la liste des erreurs
}

La table de symboles

La table de symboles est une liste composée par des objets représentant des contextes. Dans l'exemple ci-dessous, on peut voir qu'il y a 2 contextes:

  • “type”: “Statements” - le contexte du module principal, qui contient toutes les instructions
  • “type”: “function” - le contexte généré par la fonction _sum
"symbol_table": [
    {
      "variables": {},
      "functions": {
        "_sum": {
          "type": "integer",
          "parameters": [
            {
              "id": "FunctionDefinitionParameter",
              "type": "integer",
              "name": "n1",
              "symbol": 1
            },
            {
              "id": "FunctionDefinitionParameter",
              "type": "integer",
              "name": "n2",
              "symbol": 1
            }
          ],
          "line": 4,
          "symbol": 1
        }
      },
      "types": {},
      "type": "Statements"
    },
    {
      "variables": {},
      "functions": {},
      "types": {},
      "parent": 0,
      "type": "function",
      "function": "_sum",
      "return_type": "integer"
    }
  ]

Lors de la création de la table de symboles, vous devez ajouter à chaque noeud AST un paramètre symbole, représentant l'identifiant du contexte.

Objet de contexte

Les objets de contexte stockent les suivantes propriétés:

  • 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 du contexte parent (position dans le tableau symbol_table)
  • le type du contexte (Statements ou function)
  • le nom de la fonction, si le contexte est de type 'function',
  • le type de retour de la fonction

Les objets de contexte sont générés par

  • le module principal
  • une définition de fonction
  • une classe

L'objet ressemble à:

{
   "variables": { // a dictionary of variables
      "variable_name": {
         "type": // type of the variable
         "line": // the line where the variable was declared
         "value": // the expression that the variable initially has (optional, if the define was with an assignment)
      }
   },
   "messages": { // a dictionary of functions
      "message_name": {
         "type": // the return type of the function
         "parameters": [] // the list of parameters the function takes (the parameters node from the AST)
         "line": // the line where the function was declared
         "symbol": // the context object id that the function creates
 
      }
   }, 
   "types": {  // a dictionary of types
      "type": {
               "type":  // the type of the new type class or array
               "line":  // the line where the type was declared
               // for array
               "elements_type":  // the type of each array element
               "from":  // the first index
               "to": // the last index
               // for class
               "elements": [ // a list of array elements (the node form the AST)
                  {
                     "type": 
                     "id": 
                     "line": 
                  },
                  ...
               ]
            }
   },
   "parent": 0, // the parent context position in the symbol_table (except of the main script that has no parent), usually 0, 
   "type": // the type of the 
   "message": // the message name if this is a function context
   "class": // the class name if the context is in a message that is in a class
   "return_value": // the return type of the function if this is a function context
}

Exemple

{
      "variables": {},
      "functions": {
        "_sum": {
          "type": "integer",
          "parameters": [
            {
              "id": "FunctionDefinitionParameter",
              "type": "integer",
              "name": "n1",
              "symbol": 1
            },
            {
              "id": "FunctionDefinitionParameter",
              "type": "integer",
              "name": "n2",
              "symbol": 1
            }
          ],
          "line": 4,
          "symbol": 1
        }
      },
      "types": {},
      "type": "Statements"
    }

Vérification des types dans l'AST

Type de retour des expressions

Pour chacun des noeuds suivants, déterminez le type de retour

  • Expression
  • Value
  • Variable
  • ReturnFunction
  • ArrayElement
  • ClassProperty
  • FunctionDefinition

Définissez le type en ajoutant une propriété type dans le noeud.

L'algorithme pour chercher une variable suppose les étapes suivantes:

  1. S'il s'agit d'un contexte de fonction, recherchez dans le contexte des variables locales
  2. S'il n'a pas été trouvé, cherchez dans les parametres
  3. S'il n'a pas été trouvé, chechez dans le contexte des variables locales des classes
  4. S'il s'agit du contexte du module principal, cherchez dans les variables globales

Exemple

{
         "id": "Expression",
         "op": "+",
         "left": {
           "id": "Value",
           "type": "integer",
           "value": 2,
           "line": 5,
           "symbol": 0
         },
         "right": {
           "id": "FunctionCall",
           "function_name": "number",
           "parameters": [],
           "line": 5,
           "symbol": 0,
           "type": "integer"
         },
         "line": 5,
         "symbol": 0,
         "type": "integer"
       }

Vérification de la correctitude du langage

Pour tous les noeuds AST, vérifiez que les types correspondent:

  • les attributions sont faisables
  • les expressions peuvent être calculées
  • la variable est un nombre / string / boolean
  • les variables sont définies avant d'être utilisées
  • les fonctions sont définies avant d'être utilisées
  • les indices 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

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:

{
    type: //  string with the error type
    line: // the line number in the source (starting at 1)
    elements: // items for the error, each type of error has different items
    text: // the error text message
}

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
{
       "type": "VARIABLE_ALREADY_DEFINED",
       "line": 5,
       "elements": {
         "variable": "var_name"
       },
       "text": "variable var_name is already defined"
}

FUNCTION_ALREADY_DEFINED

L'erreur se produit lorsqu'une définition de fonction est répétée.

Eléments
{
       "type": "FUNCTION_ALREADY_DEFINED",
       "line": 5,
       "elements": {
         "variable": "function_name"
       },
       "text": "Function function_name is already defined"
}

TYPE_ALREADY_DEFINED

L'erreur se produit lors de la répétition d'une définition de type (tableau ou struct).

Eléments
{
       "type": "TYPE_ALREADY_DEFINED",
       "elements": {
         "type": "s"
       },
       "text": "type s is already defined"
     }

CLASS_PROPERTY_ALREADY_DEFINED

L'erreur se produit lorsqu'une définition d'élément class est répétée.

Eléments
{
       "type": "CLASS_PROPERTY_ALREADY_DEFINED",
       "line": 5,
       "elements": {
         "struct": "s" // class_name
       },
       "text": "struct's class_name element title is already defined"
 
}

ARRAY_INDEX_VALUE

L'erreur se produit lorsque l'index inférieur du tableau est supérieur à l'index supérieur

Eléments
{
       "type": "ARRAY_INDEX_VALUE",
       "line": 3,
       "elements": {
         "array": "array_name",
         "low_index": "low_index_value",
         "high_index": "high_index_value"
       },
       "text": "Array index lower value (low_index_value) must be smaller that the upper value (high_index_value)"
     }

TYPE_RESOLUTION

L'erreur se produit lorsque le type d'une variable n'est pas déterminable (bonus uniquement).

Eléments
// 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
}

UNDEFINED_FUNCTION

L'erreur se produit lorsqu'un appel de fonction est effectué pour une fonction qui n'est pas définie.

Eléments
{
       "type": "UNDEFINED_FUNCTION",
       "line": 2,
       "elements": {
         "id": "function_name"
       },
       "text": "Undefined function function_name"
}

UNDEFINED_VARIABLE

L'erreur se produit lorsqu'une variable non définie est utilisée.

Eléments
{
       "type": "UNDEFINED_VARIABLE",
       "line": 3,
       "elements": {
         "variable": "var_name"
       },
       "text": "Undefined variable var_name"
}

UNDEFINED_TYPE

L'erreur se produit lorsqu'un type qui n'est pas défini est utilisé.

Eléments

{

     "type": "UNDEFINED_TYPE",
     "line": 3,
     "elements": {
       "variable": "type_name"
     },
     "text": "Undefined type type_name"

}

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
{
        "type": "NOT_STRUCT",
        "line": 13,
        "elements": {
          "type": "var_name"
        },
        "text": "var_name is not a struct"
}

NOT_ARRAY

L'erreur se produit lorsqu'un index est demandé pour une variable qui n'est pas un tableau

Eléments
{
       "type": "NOT_ARRAY",
       "line": 5,
       "elements": {
         "type": "var_name"
       },
       "text": "var_name is not an array"
}

ARRAY_INDEX_TYPE

L'erreur se produit lorsqu'un index pour un tableau n'est pas un nombre ou un symbole

Eléments
{
       "type": "ARRAY_INDEX_TYPE",
       "line": 7,
       "elements": {
         "array": "array_name",
         "index": "string"
       },
       "text": "Array (array_name) index must be integer or symbol"
     }

RETURN_OUTSIDE_FUNCTION

L'erreur se produit lorsqu'une instruction de valeur (noeud de retour) est utilisée en dehors d'un message

Eléments
{
       "type": "RETURN_OUTSIDE_FUNCTION",
       "line": 3,
       "elements": {},
       "text": "value is used out of function"
}

TYPE_EXPRESSION

L'erreur se produit lorsqu'une expression a des types incompatibles

Eléments
{
       "type": "TYPE_EXPRESSION",
       "line": 6,
       "elements": {
         "op": "=",
         "to": "to_type",
         "from": "from_type"
       },
       "text": "Type expression error to_type is from_type"
}

Bonus

Pour un 0.5p supplémentaire, trouver le type de variables qui sont déclarées en utilisant juste une attribution.

Le bonus ne sera attribué que si tous les autres tests réussissent.

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.

NE POSEZ AUCUN CODE . Ceci est considéré comme copiage et vous aurez 0p pour ce devoir.

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 .

alf/teme/tema4.txt · Last modified: 2022/05/03 12:23 by diana.ghindaoanu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0