LANGAGE C-L’analyse Syntaxique Encadré par : - Pr ELGHAZI Souhail Groupe de travail : - Assafi Issam Settai Yassine Jazouli Othmane Zouaid Omar I. Introduction Dans la phase de l’analyse syntaxique, on cherche à dire si un texte source appartient à un langage donné, c’est-à-dire s’il respecte la grammaire de langage. L’analyse syntaxique consiste à expliciter la structure du programme sous forme d'un arbre, appelé arbre de syntaxe, chaque nœud de cet arbre correspond à un opérateur et ses fils aux opérandes sur lesquels il agit. II. La grammaire du langage C-La première règle est OK, vu que c’est un seul choix. La deuxième règle : <liste-declarations> :<liste-declarations> <declaration> | epsilon est récursive à gauche, après élimination de la récursivité, on a deux nouvelle règles : - <liste-declarations> : <liste-declarations’> qui est OK - <liste-declarations’> : <declaration><liste-declarations’> | epsilon qui n’est pas de tout LL(1), vu que INT appartient à Premier(<liste-declarations>’ ) et à Suivant(<liste-declarations>’ ) La solution qu’on a abordé est de reformuler l’ensemble des première règles afin de former une grammaire déterministe. Grammaire finale R1) <Programme> : < int-declarateurs> < liste-fonctions’> R2) < int-declarateurs> : int identificateur <declaration> | epsilon R3) <declaration> : <liste-declarateurs> ; < int-dectarateurs> | <fonction> <liste-fonctions> R4) <liste-declarateurs> : <declarateur> <liste-declarateurs’> R5) <liste-declarateurs’> : , <declarateur> <liste-declarateurs’> | epsilon R6) <declarateur> : [constante] <declarateur’> | epsilon R7) <declarateur’> : [constante] | epsilon R8) <fonction> : ( <liste-parms> ) { <liste-declarations> < liste-instructions>} R9) <prototype> : extern <type> identificateur ( <liste-parms> ) ; R10) <type> : void I int R11) <liste-fonctions> : int identificateur <fonction> <liste-fonctions> | <liste-fonctions’> | epsilon R12) <liste-fonctions’> : void identificateur <fonction> <liste-fonctions> |<prototype> <listefonctions> <liste-parms> : <liste-parms’> <liste-parms’> : , <parm> <liste-parms’> <parm> : int identificateur <liste-instructions> : <liste-instructions'> <liste-instructions'> : < instructions ><liste-instructions’>| epsilon <instruction> : identificateur<instruction’>| <iteration> I <selection> | <saut> | <bloc> <instruction’> : ( <liste-expressions> ) ; | <variable’> = <expression> <iteration> : for ( < affectation> ; <condition> ; <affectation> ) <instruction> | while( <condition> ) <instruction> <selection> :if ( <condition> ) <instruction><selection’> <selection’> :else<instruction> | epsilon <saut> :return <saut’> <saut’> : ; |<expression>; <affecation> : <variable> = <expression> <bloc> : { <liste-expressions>} <appel> : identificateur ( <liste-expressions> ) ; <variable> : identificateur <variable’> <variable’> :[<expression>] <variable’'> |epsilon <variable’'> :[<expression>] | epsilon <bloc> : { <liste-instructions> } <expression> : ( <expression> ) <expression’> | -<expression><expression’> | identificateur <expression’’> | <constante> <expression’> <expression’’> : <variable’> <expression’> | (<liste-expressions>) <expression’> <expression’> : <binary-op> <expression><expression’> | episolon <liste-expressions> : <liste-expressions’> <liste-expressions’> : , <expression> <liste-expressions’>| epsilon <condition> : !(<condition>) <condition’> | (<condition >) <condition’> | <expression><binary-comp><expression><condition’> <condition’> : <condition><binary-rel><condition’> | epsilon Justifications/Explications Règle 1 : <Programme> : < int-declarateurs> < liste-fonctions’> La règle 1 est bonne car il ne présente qu’un seul choix. Règle 2 : < int-declarateurs> : int identificateur <declaration> | epsilon On a premier(int identificateur <declaration>) ∩ { epsilon } = ∅ . D’autre part, int identificateur <declaration> est non annulable avec premier(< int-declarateurs>) = {int, epsilon} et suivant(< int-declarateurs>) = {void, extern} d’où premier(< int-declarateurs>) ∩ suivant(< int-declarateurs>) = ∅. Alors la règle 2 est bonne. Règle 3 : On a premier(<liste-declarateurs>) = { ‘[‘ , ‘,’ } et premier(<fonction>)= { ‘(‘ } et donc premier(<listedeclarateurs>) ∩ premier(<fonction>)∅. Et comme les deux sont non annulables alors le règle 3 est bonne. Règle 4: <liste-declarateurs> : <declarateur> <liste-declarateurs’> La règle 4 est bonne car il représente qu’un seul choix. Règle 5: <liste-declarateurs’> : , <declarateur> <liste-declarateurs’> | epsilon On l’intersection des premiers des deux sous-règles de <liste-declarateurs’> est l’ensemble vide ; et comme une seule est non annulable, on a : Premier(<liste-declarateurs’>) = {‘,’, epsilon} et suivant(<liste-declarateurs’>) = {void, extern} d’où l’intersection est l’ensemble vide. Alors la règle 5 est bonne. Règle 6: On l’intersection des premiers des deux sous-règles de <liste-declarateurs’> est l’ensemble vide ; et comme une seule est non annulable, on a : Premier(<declarateur>) = {‘[’, epsilon} et suivant(<declarateur>) = {void, extern, ‘,’} d’où l’intersection est l’ensemble vide. Alors règle 6 est bonne. Règle 7: On l’intersection des premiers des deux sous-règles de <liste-declarateurs’> est l’ensemble vide ; et comme une seule est non annulable, on a : Premier(<declarateur’>) = {‘[’, epsilon} et suivant(<declarateur’>) = suivant(<declarateur>) = {void, extern, ‘,’} d’où l’intersection est l’ensemble vide. Alors règle 7 est bonne. Règle 8: <fonction> : ( <liste-parms> ) { <liste-declarations> < liste-instructions>} La règle 8 est bonne car il ne présente qu’un seul choix. Règle 9: <prototype> : extern <type> identificateur ( <liste-parms> ) ; La règle 9 est bonne car il ne présente qu’un seul choix. Règle 10: <type> : void I int La règle 10 est bonne car il présente deux choix différents et non annulables. Règle 11: <liste-fonctions> : int identificateur <fonction> <liste-fonctions> | <liste-fonctions’> | epsilon Premier(<liste-fonctions’>) = {void, extern} l’intersection avec {int} et {epsilon} est l’ensemble vide. Premier(<liste-fonctions>) = {int, void, extern} et suivant (<liste-fonctions>) = {$}, donc l’intersection est vide ce qui signifie que la règle 11 est bonne. Règle 12: <liste-fonctions’> : void identificateur <fonction> <liste-fonctions> |<prototype> <listefonctions> On a premier(<protocole>) = {extern} l’intersection avec {void} est vide. Et comme les deux sont non annulables alors la règle 12 est bonne. (On utilise maintenant le numérotage des règles de la grammaire proposée sur l’énonncé ) Règle 9 : <liste-parms> : <liste-parms> , <parm> | epsilon X : Récursivité à gauche. Elimination de la récursivité à gauche : R091. <liste-parms> : <liste-parms’> / OK : Un seul choix R092. <liste-parms’> : , <parm> <liste-parms’> | epsilon /OK Règle 10 : <parm> : int identificateur Ok : Un seul choix Règle 11 : <liste-instructions> : <liste-instructions>< instructions > | epsilon X : Récursivité à gauche. Elimination de la récursivité à gauche : R111.<liste-instructions> : <liste-instructions'> Ok : Un seul choix R112.<liste-instructions'> : < instructions ><liste-instructions’>| epsilon Premier(< instructions ><liste-instructions’>)= {for,while,if,return,{,identificateur} et Premier(epsilon ) = { epsilon } sont disjoints. La deuxième production est annulable et : Premier(<liste-instructions’>)={for,while,if,return,{,identificateur, epsilon} et Suivant(<liste-instructions’>)={ } } sont disjoints. /OK Règle 12 : <instruction> : <iteration> I <selection> | <saut> | <affectation> ; | <bloc> I <appel> Premier(appel)∩ Premier(affectation) = {identificateur} Factorisation à gauche : R121. <instruction> : identificateur<instruction’>| <iteration> I <selection> | <saut> | <bloc> Les premiers des productions sont respectivement : {identificateur} , {for,while} , {if} , {return} et { { } sont tous disjoints Toutes les productions sont non annulables. /OK R122. <instruction’> : ( <liste-expressions> ) ; | <variable’> = <expression> Les premiers respectifs sont { ( } et {epsilon, [ } ils sont disjoint. Les deux productions sont non annulables . /OK Règle 13 : <iteration> : for ( < affectation> ; <condition> ; <affectation> ) <instruction> | while( <condition> ) <instruction> Les premiers successifs sont {for} et {while}, ils sont disjoints. Les deux productions sont non annulables. /Ok Règle 14 : <selection> :if ( <condition> ) <instruction> | if ( <condition> ) <instruction>else<instruction> X : Récursivité à gauche. Factorisation à gauche : R141. <selection> :if ( <condition> ) <instruction><selection’> Un seul choix /OK R142. <selection’> :else<instruction> | epsilon Les premiers successifs sont {else} et {epsilon} sont disjoints. Premier(<selection’>)={else,epsilon} et suivant(<selection’>)={ } } sont disjoints. /OK Règle 15 : <saut> : return ; | return <expression>; X : Factorisation à gauche. Factorisation à gauche : R151. <saut> :return <saut’> Un seul choix /OK R152. <saut’> : ; |<expression>; Les premiers successifs sont {;} et { ( , - , identidicateur, 0,1,..,9} sont disjoints Aucune des productions n'est annulable /OK Règle 16 : <affecation> : <variable> = <expression> un seul choix /OK Règle 17 : <bloc> : { <liste-expressions>} un seul choix /OK Règle 18 : <appel> : identificateur ( <liste-expressions> ) ; un seul choix /OK Règle 19 : <variable> : identificateur | identificateur [<expression>] |identificateur[<expression>][<expression>] Factorisation à gauche : R191. <variable> identificateur <variable’> un seul choix /OK R192. <variable'> : [<expression>] | [<expression>][<expression>] |epsilon Factorisation à gauche : R193. <variable’> :[<expression>] <variable’'> |epsilon Les premiers respectifs sont { [ } et {epsilon} sont disjoints. Premier(<variable'> )= { epsilon , [} et Suivant(<variable'> )= {=, ) , , , & , | , +, -, * , / , < , > , ; ] } sont disjoints /OK R194. <variable’'> :[<expression>] | epsilon Les premiers respectifs sont { [ } et {epsilon} sont disjoints. Premier(<variable''> )={ epsilon , [} et Suivant(<variable''> )= {=, ) , , , & , | , +, -, * , / , < , > , ; ] } sont disjoints /OK Règle 20 : <expression> : ( < expression > ) | <expression> <binary-op> <expression>|- <expression> | <variable> | <constante> | identificateur (<liste-expressions>) X : Recursivité à gauche. Elimination de la récursivité à gauche : R201. <expression> : ( <expression> ) <expression’> | -<expression><expression’> | <Identificateur><variable’> <expression’> | identificateur (<liste-expressions>) <expression’> | <constante> <expression’> OK R2011 : <expression> : ( <expression> ) <expression’> | identificateur <expression’’> /OK R2012 : <expression’’> : <variable> <expression’> | (<liste-expressions>) <expression’> /OK Les premiers des deux membres disjoints et ils sont non annulables R202. <expression’> : <binary-op> <expression><expression’> | episolon /OK Un membre annulable, on a Premier(<expression’>) = { <binary-op>,epsiolon } Alors que Suivant(<expression’> )= { ; , ] } Les deux sont disjoints ! Règle 21 : <liste-expressions> : <liste-expressions>,<expression> | epsilon X : Recursivité à gauche. Elimination de la récursivité à gauche : R211. <liste-expressions> : <liste-expressions’> /OK R212. <liste-expressions’> : , <expression> <liste-expressions’>| epsilon /OK Car on a un membre annulable. et Premier(<liste-expressions’> ) = {, , epsilon} Suivant (<liste-expressions’> )={ <binary-op>,)} Règle 22 : <condition> : !(<condition>) | <condition><binary-rel><condition> | (<condition >) | <expression><binary-comp><expression> Elimination de la récursivité à gauche : R221. <condition> : !(<condition>) <condition’> | (<condition >) <condition’> | <expression><binary-comp><expression><condition’> OK Les premiers disjoincts et non annulables R222. <condition’> : <condition><binary-rel><condition’> | epsilon OK Un member annullable, alors : - Premier(<condition’>)={!,(,identificateur,constante} - Suivant(<condition’>)={<binary-rel>,),;} Les deux sont disjoints !