Differences

This shows you the differences between two versions of the page.

Link to this comparison view

alf:laboratoare:06 [2020/03/26 09:49]
diana.ghindaoanu [TP 6 - Parser du langage]
alf:laboratoare:06 [2021/04/09 23:33] (current)
diana.ghindaoanu
Line 1: Line 1:
-====== TP 6 - Parser du langage ​======+====== TP 6 - AST: Continuation ​======
  
-<​note>​ +L'​**AST** est une représentation arborescente de la structure syntaxique abstraite du code source écrit dans un langage de programmationChaque nœud de l'​arborescence désigne un jeton identifié, reconnu comme étant dans un ordre correct pour le langage défini dans la grammaire.
-Microsoft Teams: [[https://​teams.microsoft.com/​l/​channel/​19%3a7f8fb09bb94548988ef630aedc96733f%40thread.tacv2/​TP%25206?​groupId=0c1b36fc-0332-4f9d-98cf-85bad7e6c898&​tenantId=2d8cc8ba-8dda-4334-9e5c-fac2092e9bac|TP6]]+
  
-   * username: votre username ​de fils.curs.pub.ro (username@stud.fils.upb.ro) +La structure ​de l'AST dépend beaucoup ​de la complexité ​de la grammaire: ​
-   * password: votre mot de passe de fils.curs.pub.ro+
  
-Selectez channel TP 6 et appuyez sur le boutton Join.+{{ :​alf:​laboratoare:​ast.jpg?​750&​nolink }}
  
-Les archives ​avec les exercices seront envoyées à l'adresse diana.ghindaoanu@stud.fils.upb.ro +Le but de ce TP est de vous habituer a travailler plus avec le //parser//, le //​visiteur//​ et la generation de l'//arbre de syntaxe abstraite//,​ en continuant le dévéloppement du TP passé.
-</note>+
  
-===== Parse Tree =====+Etant donnée la grammaire suivante:
  
-Un parser génère un arbre, nommé parse tree. Cela reflète les règles de grammaire. Jison ne génère pas le parse tree par défaut et nous permet de créer cet parse tree dans n'​importe quel format que nous voulons.+<code g4> 
 +grammar Ex1;
  
-Un format possible est+start               : (statement SEMICOLON NEWLINE*)* ​              #​multilineProg 
 +                    | statement SEMICOLON NEWLINE* ​                 #​singlelineProg  
 +                    ;
  
-==== Règle de la grammaire ​==== +statement ​          : declaration ​                                  #​declarationRule 
-Le format d'un nœud d'arbre de règles de grammaire+                    | expression ​                                   #​expressionRule 
 +                    | attribution ​                                  #​attributionRule 
 +                    ; 
 + 
 +declaration ​        : type VARIABLE EQ expression ​                  #​variableDeclaration 
 +                    ; 
 + 
 +type                : INT                                           #​typeInt 
 +                    | FLOAT                                         #​typeFloat 
 +                    | STRING ​                                       #​typeString 
 +                    ; 
 + 
 +value               : INT_NUMBER ​                                   #valueInt 
 +                    | FLOAT_NUMBER ​                                 #​valueFloat 
 +                    | STRING_TEXT ​                                  #​valueString 
 +                    | VARIABLE ​                                     #​valueVariable 
 +                    ; 
 + 
 +expression ​         : left=expression op=MUL right=expression ​      #​expressionMultiply 
 +                    | left=expression op=DIV right=expression ​      #​expressionDivision ​                   
 +                    | left=expression op=REM right=expression ​      #​expressionRem ​ 
 +                    | left=expression op=ADD right=expression ​      #​expressionAddition 
 +                    | left=expression op=SUB right=expression ​      #​expressionSubtraction 
 +                    | LP expression RP                              #​expressionParanthesis 
 +                    | value                                         #​expressionValue 
 +                    ; 
 + 
 +/** TODO 1: Add the tokens (in the Lexer part) and the rules (with aliases) for boolean expressions 
 +  * Operators: OR, AND, NOT 
 +  * Values: true, false, variables  
 + */ 
 + 
 + 
 +attribution ​        : VARIABLE EQ expression ​                       #​variableAttribution 
 +                    ; 
 + 
 + 
 +/** TODO 4: Add the tokens (in the Lexer part) and the rules (with aliases) for lists declaration 
 +  * Keyword: list 
 +  * Name: any variable name 
 +  * Values: any value separated by comma 
 + */ 
 + 
 + 
 +/** TODO 5: Add the tokens (in the Lexer part) and the rules (with aliases) for functions declaration 
 +  * Keyword: function 
 +  * Name: any variable name 
 +  * Parameters: any declaration separated by comma 
 +  * Instructions:​ any statement separated by a semicolon and one or more new lines 
 +  * Return: "​return"​ keyword + any statement ending with a semicolon  
 + */ 
 + 
 +/** BONUS: Add the tokens (in the Lexer part) and the rules (with aliases) for function calls 
 +  * Function name: any variable name 
 +  * Parameters: any value separated by comma 
 +  * Add the function call to the variable declaration ​  
 + */ 
 + 
 + 
 +WS                  :   (' ​'​) ​      -> skip; 
 +NEWLINE ​            : ​  ([\r\n]+)   -> skip; 
 +VARIABLE ​           :   ​('​_'​[a-zA-Z0-9]+);​ 
 +ADD                 : ​  '​+';​ 
 +SUB                 : ​  '​-';​ 
 +MUL                 : ​  '​*';​ 
 +DIV                 : ​  '/';​ 
 +REM                 : ​  '​%';​ 
 +INT                 : ​  '​int';​ 
 +FLOAT               : ​  '​float';​ 
 +STRING ​             :   '​string';​ 
 +LP                  :   '​(';​ 
 +RP                  :   '​)';​ 
 +EQ                  :   '​=';​ 
 +SEMICOLON ​          : ​  ';';​ 
 +INT_NUMBER ​         :   ​([0-9]+);​ 
 +FLOAT_NUMBER ​       :   ​([0-9]+'​.'​[0-9]+);​ 
 +STRING_TEXT ​        : ​  ​('"'​~["​]+'"'​|'​\''​~['​]+'​\'​');
  
-<code javascript>​ 
-{ 
-  rule: '​grammar rule name', 
-  items: [] 
-} 
 </​code>​ </​code>​
  
-==== Jeton ==== +Et l'écrasement des méthodes ​de visiteur:
-Le format d'une feuille d'​arbre ​de jeton+
  
 <code javascript>​ <code javascript>​
-+import ​CharStreams,​ CodePointCharStream,​ CommonTokenStream,​ Token } from '​antlr4ts';​ 
-  ​token: ​'TOKEN', +import { Ex1Lexer } from './​Ex1Lexer.js'
-  ​value:​ value +import { Ex1ParserExpressionAdditionContext,​ ExpressionDivisionContext,​ ExpressionMultiplyContext,​ ExpressionParanthesisContext,​ ExpressionRemContext,​ ExpressionSubtractionContext,​ MultilineProgContext,​ SinglelineProgContext,​ TypeFloatContext,​ TypeIntContext,​ TypeStringContext,​ ValueFloatContext,​ ValueIntContext,​ ValueStringContext,​ VariableDeclarationContext,​ ExpressionValueContext,​ ValueVariableContext,​ VariableAttributionContext } from '​./​Ex1Parser.js';​ 
-+import { Ex1Visitor ​from '​./​Ex1Visitor.js';​ 
-</code>+import * as fs from '​fs';​ 
 +import { AbstractParseTreeVisitor } from '​antlr4ts/tree/​AbstractParseTreeVisitor';​
  
-==== Actions pour construire le parse tree ====+let input: string ​fs.readFileSync('​./​sample.txt'​).toString();​ 
 +let inputStream:​ CodePointCharStream ​CharStreams.fromString(input);​ 
 +let lexer: Ex1Lexer ​new Ex1Lexer(inputStream);​ 
 +let tokenStream:​ CommonTokenStream ​new CommonTokenStream(lexer);​ 
 +let parser: Ex1Parser ​new Ex1Parser(tokenStream);​
  
-D'​abord nous écrivons deux fonctions: une pour construire un noeud de parse tree et une autre pour construire une feuille de parse tree.+let tree = parser.start();
  
-<code javascript>​ +abstract class ASTNode { 
-function rule (rule_name, items) +    ​constructor(){};
-{ +
-  return { +
-    rule: rule_name,​ +
-    items: items +
-  ​};+
 } }
-</​code>​ 
  
-<code javascript>​ +class StatementsNode extends ASTNode { 
-function token (token_namevalue+    ​constructor(public readonly statements: ASTNode[]public readonly line: number{ 
-+        ​super();​ 
-  return { +    } 
-    ​tokentoken_name+    toJSON() ​
-    value: value +        return { 
-  };+            id: "​statements",​ 
 +            statements: this.statements,​ 
 +        } 
 +    ​
 +
 +class DeclarationNode extends ASTNode { 
 +    constructor(public readonly variable_typestringpublic readonly variable: string, public readonly op: string, public readonly value: Expression|ValueNode, ​ public readonly line: number) { 
 +        super(); 
 +    ​
 +    toJSON() { 
 +        return { 
 +            id: "​declaration",​ 
 +            variable_type:​ this.variable_type,​ 
 +            variable: this.variable,​ 
 +            ​value: ​this.value, 
 +        } 
 +    ​}
 } }
-</​code>​ 
  
-Nous allons écrire les deux fonctions dans la section %%du fichier alf.y.+class ValueNode extends ASTNode ​{ 
 +    constructor(public readonly value: number|string|boolean,​ public readonly line: number) { 
 +        super(); 
 +    ​} 
 +    toJSON() { 
 +        return { 
 +            id: "​value",​ 
 +            value: this.value, 
 +        } 
 +    } 
 +
 +class TypeNode extends ASTNode { 
 +    constructor(public readonly type_name: string, public readonly line: number) { 
 +        super(); 
 +    } 
 +    toJSON() { 
 +        return ​ { 
 +            type: this.type_name,​ 
 +        } 
 +    } 
 +
 +class Expression extends ASTNode { 
 +    constructor(public readonly op: string, public readonly left: Expression, public readonly right: Expression, public readonly line: number) { 
 +        super(); 
 +    } 
 +    toJSON() { 
 +        return { 
 +            id: "​expression",​ 
 +            left: this.left,​ 
 +            right: this.right,​ 
 +            op: this.op, 
 +        } 
 +    } 
 +}
  
-La règle de début renvoie le parse tree.+class AttributionNode extends ASTNode { 
 +    constructor(public readonly variable: string, public readonly value: Expression, public readonly line: number) { 
 +        super(); 
 +    } 
 +    toJSON() { 
 +        return { 
 +            id: "​attribution",​ 
 +            to: this.variable, 
 +            from: this.value,​ 
 +        } 
 +    } 
 +}
  
-<note+/** TODO 1: Create a class for List Nodes which will return a Node with the following properties 
-Si les règles de départ comportent plus d'un élémentnous devons construire le nœud dans le parse tree et le retourner. +     * id =list_declaration 
-</note>+     * list_type => the actual typewhich will be set in the Visitor as list 
 +     * list_name =the name of the list 
 +     * values => an array of values 
 +*/
  
-<code jison alf.l> 
-Ws                      \s+ 
-Identifier ​             [A-Za-z\$_][A-Za-z\$_0-9]* 
-  
-%%  
-"​var"​         { return '​VAR';​ } 
-","​  ​       { return ',';​ } 
-{Ws}                    { /* skip whitespace */ } 
-{Identifier} { return '​IDENTIFIER';​ } 
  
-</code>+/** TODO 5: Create a class for Function Nodes which will return a Node with the following properties 
 + * id =function 
 + * function_name:​ the actual name of the function, taken from the variable 
 + * parameters: the list of the parsed nodes set as parameters 
 + * instructions:​ the list of the parsed nodes set as statements in the function 
 + * return: the parsed return node 
 + */
  
-<code jison alf.y+/** TODO 5: Recommandations for solving this exercice 
-%+ * You should create a class for the Parameter Node, with the following properties:  
-// function for grammar rule +        * id: function_parameter,​ 
-function rule (rule_nameitems+        * type: the type of the parameter from the declaration 
-+        * value: the parsed value assigned to the parameter 
-  return { + * You should create a class for the Return Node, with the following properties:​ 
-    ​rulerule_name+        * id: return_node 
-    ​itemsitems +        * return_statement:​ the statement that will be parsed in the Visitor  
-  };+ */ 
 + 
 +class MyEx1Visitor extends AbstractParseTreeVisitor<ASTNodeimplements Ex1Visitor<​ASTNode>​ { 
 +    ​defaultResult() ​
 +        ​return new StatementsNode([],​ 0); 
 +    } 
 +    visitMultilineProg(ctx:​ MultilineProgContext):​ StatementsNode { 
 +        let statements = []; 
 +        for(let i = 0; i < ctx.statement().length;​ i++) 
 +            statements[i] = this.visit(ctx.statement(i));​ 
 +        if(statements) { 
 +            return new StatementsNode(statements,​ 1); 
 +        } else { 
 +            throw new Error(); 
 +        } 
 +    } 
 +    visitSinglelineProg(ctx:​ SinglelineProgContext):​ASTNode { 
 +        return new StatementsNode([this.visit(ctx.statement())],​ 1); 
 +    } 
 +    visitVariableDeclaration(ctx:​ VariableDeclarationContext):​ DeclarationNode { 
 +        return new DeclarationNode( 
 +            (this.visit(ctx.type()) as TypeNode).type_name,​ 
 +            ctx.VARIABLE().text,​ 
 +            ctx.EQ().text,​ 
 +            this.visit(ctx.expression()) as Expression,​ 
 +            ctx.VARIABLE().symbol.line 
 +        ); 
 +    } 
 +    visitValueInt(ctx:​ ValueIntContext):​ ValueNode { 
 +        return new ValueNode( 
 +            parseInt(ctx.INT_NUMBER().text),​ 
 +            ctx.INT_NUMBER().symbol.line 
 +        ); 
 +    } 
 +    visitValueVariable(ctx:​ ValueVariableContext):​ ValueNode { 
 +        return new ValueNode( 
 +            ctx.VARIABLE().text,​ 
 +            ctx.VARIABLE().symbol.line 
 +        ); 
 +    } 
 +    visitValueFloat(ctx:​ ValueFloatContext):​ ValueNode { 
 +        return new ValueNode( 
 +            parseFloat(ctx.FLOAT_NUMBER().text),​ 
 +            ctx.FLOAT_NUMBER().symbol.line 
 +        ); 
 +    } 
 +    visitValueString(ctx:​ ValueStringContext):​ ValueNode { 
 +        return new ValueNode( 
 +            ctx.STRING_TEXT().text,​ 
 +            ctx.STRING_TEXT().symbol.line 
 +        ); 
 +    } 
 +    ​/** TODO 1: Visit the boolean value *
 +     
 +    visitTypeInt(ctx: TypeIntContext):​ TypeNode { 
 +        return new TypeNode( 
 +            ctx.INT().text, 
 +            ctx.INT().symbol.line 
 +        ) 
 +    } 
 +    visitTypeString(ctx:​ TypeStringContext):​ TypeNode ​
 +        return ​new TypeNode( 
 +            ctx.STRING().text,​ 
 +            ctx.STRING().symbol.line 
 +        ) 
 +    } 
 +    visitTypeFloat(ctx:​ TypeFloatContext):​ TypeNode ​{ 
 +        return new TypeNode( 
 +            ctx.FLOAT().text,​ 
 +            ctx.FLOAT().symbol.line 
 +        ) 
 +    ​
 +    /** TODO 1Visit the boolean type */ 
 + 
 +    visitExpressionMultiply(ctx:​ ExpressionMultiplyContext):​ Expression { 
 + const left = this.visit(ctx.expression(0));​ 
 + const right = this.visit(ctx.expression(1));​ 
 + const op = ctx._op; 
 + 
 + if(op.text) { 
 + return new Expression(op.textleft as Expression, right as Expression, ctx._op.line);​ 
 + } else throw new Error(); 
 + } 
 +    ​visitExpressionDivision(ctxExpressionDivisionContext):​ Expression { 
 + const left = this.visit(ctx.expression(0));​ 
 + const right = this.visit(ctx.expression(1));​ 
 + const op = ctx._op; 
 + 
 + if(op.text) { 
 + return new Expression(op.text,​ left as Expression, right as Expression, ctx._op.line);​ 
 + else throw new Error(); 
 +
 +    visitExpressionRem(ctx:​ ExpressionRemContext):​ Expression { 
 + const left = this.visit(ctx.expression(0));​ 
 + const right = this.visit(ctx.expression(1));​ 
 + const op = ctx._op; 
 + 
 + if(op.text) { 
 + return new Expression(op.text,​ left as Expression, right as Expression, ctx._op.line);​ 
 + } else throw new Error(); 
 +
 +    visitExpressionAddition(ctx:​ ExpressionAdditionContext):​ Expression { 
 + const left = this.visit(ctx.expression(0));​ 
 + const right = this.visit(ctx.expression(1));​ 
 + const op = ctx._op; 
 + 
 + if(op.text) { 
 + return new Expression(op.text,​ left as Expression, right as Expression, ctx._op.line);​ 
 + } else throw new Error(); 
 +
 +    visitExpressionSubtraction(ctx:​ ExpressionSubtractionContext):​ Expression { 
 + const left = this.visit(ctx.expression(0));​ 
 + const right = this.visit(ctx.expression(1));​ 
 + const op = ctx._op; 
 + 
 + if(op.text) { 
 + return new Expression(op.text,​ left as Expression, right as Expression, ctx._op.line);​ 
 + } else throw new Error(); 
 +
 +    visitExpressionParanthesis(ctx:​ ExpressionParanthesisContext) { 
 +        return this.visit(ctx.expression());​ 
 +    } 
 +    visitExpressionValue(ctx:​ ExpressionValueContext):​ ValueNode { 
 +        let value = this.visit(ctx.value());​ 
 +        if(value !== undefined) { 
 +     return new ValueNode((this.visit(ctx.value()) as ValueNode).value,​ ctx.value()._start.line);​ 
 +        } else throw new Error(); 
 +
 +     
 +    /**TODO 1: Visit every type of boolean expression */ 
 + 
 + 
 +    /**TODO 4: Visit list declaration */ 
 +    visitVariableAttribution(ctx:​ VariableAttributionContext):​ AttributionNode { 
 +        return new AttributionNode( 
 +            ctx.VARIABLE().text,​ 
 +            this.visit(ctx.expression()) as Expression,​ 
 +            ctx.VARIABLE().symbol.line 
 +        ); 
 +    } 
 + 
 +    /**TODO 5: Visit function declaration and return node */ 
 +    ​
 } }
-  +const visitor = new MyEx1Visitor();​ 
-// function for token +console.log(JSON.stringify(visitor.visit(tree)null, 4)); 
-function token (token_namevalue)+ 
 + 
 + 
 +</​code>​ 
 + 
 +Le résultat généré aura le format suivant: 
 + 
 +<code javascript>​
 { {
-  return { +    "​id":​ "​statements",​ 
-    ​tokentoken_name+    ​"​statements"​
-    value: value +        { 
-  };+            "​id":​ "​declaration"​
 +            "​variable_type":​ "​int",​ 
 +            "​variable":​ "​_var1",​ 
 +            "value"
 +                "​id":​ "​expression",​ 
 +                "​left":​ { 
 +                    "​id":​ "​expression",​ 
 +                    "​left":​ { 
 +                        "​id":​ "value", 
 +                        "​value":​ 2 
 +                    ​}
 +                    "​right":​ { 
 +                        "​id":​ "​value",​ 
 +                        "​value":​ 5 
 +                    }, 
 +                    "​op":​ "​+"​ 
 +                }, 
 +                "​right":​ { 
 +                    "​id":​ "​expression",​ 
 +                    "​left":​ { 
 +                        "​id":​ "​value",​ 
 +                        "​value":​ 7 
 +                    }, 
 +                    "​right":​ { 
 +                        "​id":​ "​value",​ 
 +                        "​value":​ 3 
 +                    }, 
 +                    "​op":​ "​*"​ 
 +                }, 
 +                "​op":​ "/"​ 
 +            } 
 +        } 
 +    ]
 } }
-%} 
-  
-%%  
-  
-start: variable ​ 
- { 
- return $1; 
- }; 
-  
-  
-variable:​ VAR variables 
- { 
- $$ = rule ('​variable',​ [token ('​VAR',​ $1), $2]); 
- }; 
-  
-variables:​ IDENTIFIER ','​ variables ​   
- { 
- $$ = rule ('​variables', ​ 
-            [ 
-               token ('​IDENTIFIER',​ $1),  
-               token (',',​ ','​), ​ 
-               $3 
-            ] 
-           ); 
- } 
-         | IDENTIFIER ​ 
- { 
- $$ = token ('​IDENTIFIER',​ $1); 
- }; 
  
 </​code>​ </​code>​
  
 +===== Erreurs =====
 +Au niveau de l'​anayse on peut retrouver 2 types d'​erreurs:​
 +   * **Erreurs lexicales** - le Parser trouve des jetons qu'il ne peut pas identifier dans le Lexer
 +   * **Erreurs syntaxiques** - le texte ne respecte pas les règles indiquées dans la grammaire
  
-===== Exercises ===== 
  
-Pour vérifier la corectitude de la grammaire des, exercises accédez à [[https://​nolanlawson.github.io/​jison-debugger/​|Jison Debugger]]. +Pour pouvoir traiter ces erreurs, on doit tout d'abord éliminer les écouteurs ​d'erreurs par défaut d'​ANTLR ​(ErrorListeners) 
-Dans l'​exemple présenté, on réalise la génération ​d'un arbre d'analyse ​(//parse tree//pour la déclaration des variables, en utilisant les fonctions ''​rule''​ et ''​token''​.+<code javascript>​ 
 +lexer.removeErrorListeners (); 
 +parser.removeErrorListeners (); 
 +</​code>​
  
-  - (**3p**) Clonez/​téléchargez [[https://​github.com/​UPB-FILS/​alf/​tree/​master/​TP/​TP6| la structure]] du TP. Ajoutez à la grammaire décrite dans l'​exemple les règles nécessaires pour l'​utilisation des expressions (plusieurs expressions) du laboratoire précédent. Un programme peut contenir aussi des déclarations des variables, que l'​emploi des expressions,​ donc la nouvelle grammaire doit accepter plusieurs instructions (//​statements//​). Le delimitateur des instructions est ';'​.  +Ensuite, il faut créer un nouvel outil qui puisse attraper et afficher les erreursPour celaon peut définir une nouvelle classe:
-  - (**2p**) Ajouter des règles pour l'​attribution d'une valeur à une variable. La règle pour cela est <​code>​variable = value</​code>​La valeur est un nombre (entier ou réel). Pour pouvoir utiliser une variable dans une expression, il faut vérifier avant qu'​elle a été déjà définie. <​code>​ a = 4; 2 + 3 * a; </​code>​ Si on essaie d'​utiliser une variable ​qui n'a pas une valeur prédéfinie,​ on va afficher ​le message //"​Undefined variable variable_name"//​. +
-  - (**1p**) Ajouter des règles pour que les variables puissent prendre des valeurs qui sont des expressions +
-  - (**4p**) Ajouter des règles à la grammaire pour qu'​elle accèpte les appels de fonctions. Un appel de fonction ressemble à <​code>​function_name (parameter1parameter2, parameter3, ...)</​code>​ Les paramètres de la fonction peuvent etre des variables (définies avant), des nombres (entiers ou réels) ou des expressions.+
  
 +<code javascript>​
 +class ErrorPrinter implements ANTLRErrorListener<​any>​ {
 +    syntaxError (recognizer:​ Recognizer<​any,​ any>, offendingSymbol:​ any | undefined, line: number, charPositionInLine:​ number, msg: string, e: RecognitionException | undefined) {
 +        if (e) {   
 +            console.log ("​line:​ "​+line+"​ positon: "​+charPositionInLine+"​ message: "​+msg);​
  
-==== Solutions ==== +        } 
-[[https://​github.com/​UPB-FILS/​alf/​tree/​master/​TP/TP6|Solutions]]+    }  
 +
 +</code>
  
 +Finalament, on doit indiquer au ''​parser''​ et au ''​lexer''​ quels sont les nouveaux écouteurs:
  
 +<code javascript>​
 +lexer.addErrorListener (new ErrorPrinter());​
 +parser.addErrorListener (new ErrorPrinter());​
 +</​code>​
 +
 +===== Exercices ======
 +
 +   - Téléchargez la [[https://​github.com/​UPB-FILS-ALF/​TP/​tree/​main/​TP6|structure du TP]] et utilisez la grammaire **Ex1.g4** comme support pour les exercices. En suivant les lignes marquées par TODO 1, ajoutez les règles de grammaire, les classes et les méthodes nécessaires pour pouvoir déclarer aussi des variables et des expressions booléennes. Testez la fonctionnalité du programme pour l'​exemple suivant: **(2p)** <​code>​ bool _var1 = _var2 ||_var3 && !_var4; </​code>​
 +   - Apportez les modifications nécessaires de sorte que chaque noeud de l'AST comprend aussi le numéro de la ligne ou il a été trouvé. **(1.5p)**
 +   - Faites que la grammaire accepte aussi la concaténation des chaines de caracteres. Vérifiez pour l'​exemple suivant: **(1.5p)** <​code>​ string _var2 = "FILS " + "​ALF";​ </​code>​
 +   - En suivant les lignes marquées par TODO 4, ajoutez à la grammaire les règles, classes et méthodes nécessaires pour que vous puissiez déclarer des listes. Les listes peuvent inclure n'​importe quel type de données . Vérifiez pour la déclaration suivante: **(1.5p)** <​code>​ list _var1 = [10, 5.5, '​alf',​ true, _var2]; </​code>​
 +   - En suivant les lignes marquées par TODO 5, ajoutez les règles, les classes et les méthodes necessaires pour la déclaration des fonctions. Une fonction peut avoir un ou plusieurs paramètres et son contenu peut inclure une seule ou plusieurs instructions. Vérifiez la correctitude de votre programme pour l'​exemple suivant: **(3.5p)** <​code>​function _functionName (int _var1=0, string _var2="​alf",​ bool _var3=true)
 +{
 +    _var1 = _var2 + "​2021";​
 +    _var4 = false;
  
 +    return 3+5/7;
 +};</​code>​
 +   - **BONUS**: Traitez les erreurs de lexer et de syntaxe pour votre arbre et affichez les messages nécessaires. **(1.5p)** ​
alf/laboratoare/06.1585208962.txt.gz · Last modified: 2020/03/26 09:49 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