Informatique
L3S5 Miage

Analyse Syntaxique – TP5

Initiation à la compilation

Ce TP a pour objectif de créer un compilateur microcobol vers java.

Le microcobol est un dérivé du cobol (COmmon Business Oriented Language). Comme son nom le suggère subtilement, le langage cobol est destiné à la programmation d’applications de gestion.

La création du compilateur microcobol durera sur plusieurs séances de TPs. Conservez votre code !

1  microcobol : création des classes et du parser

1.1  Structure et variables

Un programme microcobol est constitué de 3 divisions, elles-mêmes constituées de sections. Les trois divisions sont les suivantes :

Le programme se termine par END PROGRAM suivi du nom du programme.

Les paragraphes commencent par leur nom suivi d’un point, puis d’une liste de phrases (les instructions) se terminant chacune par un points.

Voici un exemple de programme microcobol.

IDENTIFICATION DIVISION.
  PROGRAM-ID programme-test.
PROCEDURE DIVISION.
  hello-world.
    DISPLAY "Hello World !".
    STOP RUN.
END PROGRAM programme-test.

Ce programme s’appelle programme-test (oui, vous avez bien lu, il y a un tiret - dans le nom du programme !), ne déclare aucune variable (pas de division DATA DIVISION), et définit un unique paragraphe nommé hello-world. Ce paragraphe contient deux phrases. La première affiche le message « Hello World ! », la seconde met fin à l’exécution du programme.

La division DATA DIVISION facultative contient la section WORKING-STORAGE SECTION. Cette section contient la liste des variables utilisées dans le programme sous la forme N nom PIC forme où :

Dans l’exemple suivant, on définit deux variables, qui ne sont pas utilisées.

IDENTIFICATION DIVISION.
  PROGRAM-ID an2000
DATA DIVISION.
  WORKING-STORAGE SECTION.
    77 date PIC 99/99/99.
    77 nom  PIC AAAAAAAAAA.
PROCEDURE DIVISION.         
  main.              
    STOP RUN.               
END PROGRAM an2000. 

La variable date contiendra 6 chiffres, alors que la variable nom contiendra 10 lettres.

1.2  Phrases et instructions

Les instructions en microcobol commencent le plus souvent par un verbe, sinon par un mot-clé. Une phrase est une instruction qui finit par un point.

1.2.1  Affectation

Le verbe MOVE permet d’affecter une valeur littérale ou la valeur d’une variable à une autre variable.

MOVE x TO y.

Cette phrase va réaffecter à la variable y la valeur de x.

1.2.2  Arithmétique

Les verbes ADD, SUBSTRACT, MULTIPLY et DIVIDE permettent respectivement d’additionner, de soustraire, de multiplier et de diviser.

ADD 1 TO x.
SUBSTRACT y FROM x.
MULTIPLY y BY x.
DIVIDE y INTO x.

L’exemple précédent est équivalent au code Java suivant.

x += 1;
x -= y;
x *= y;
x /= y;

1.2.3  Conditions

Les conditions s’écrivent sous la forme x IS [NOT] op y où :

Attention, une condition n’est pas une phrase (elle ne commence pas par un verbe et ne finit pas par un point) !

1.2.4  Branchement conditionnel

Une phrase de branchement s’écrit sous la forme :

IF condition
  THEN instructions
  [ELSE instructions]
END-IF.
IDENTIFICATION DIVISION.
  PROGRAM-ID. ex-condi.
PROCEDURE DIVISION.
  main.
    IF 1 IS < 2
      THEN DISPLAY "1 < 2"
      ELSE DISPLAY "1 >= 2"
    END-IF.
    STOP RUN.
END PROGRAM ex-condi.

1.2.5  Boucle

                                 
PERFORM UNTIL condition                                     
  instructions
END-PERFORM.              
IDENTIFICATION DIVISION.
  PROGRAM-ID. compte-a-rebours.
DATA DIVISION.
  WORKING-STORAGE SECTION.
    77 compteur 99.
PROCEDURE DIVISION.
  main.
    MOVE 10 TO compteur.
    PERFORM UNTIL compteur IS = 0
      DISPLAY compteur
      SUBSTRACT 1 FROM compteur
    END-PERFORM.
    DISPLAY "Boom !"
    STOP RUN.
END PROGRAM compte-a-rebours.

1.2.6  Affichage

Le verbe DISPLAY affiche la valeur des variables ou des littéraux qui le suivent.

DISPLAY "Bonjour " nom-du-sujet " !".
DISPLAY "Vous avez mis moins de " n " minutes pour résoudre le test.".
DISPLAY "Vous devez faire la fierté de " ville-du-sujet ".".

1.3  Création d’un arbre de microcobol

Vous trouverez dans l’archive microcobol.tar les fichiers nécessaires pour ce TP. Vous pouvez compiler les sources en vous plaçant dans le dossier microcobol/src et en lançant la commande make.

mra@geslegen:~/cours/as/tp/microcobol/src $ make
java -jar ../lib/jflex.jar microcobol.lex
Reading "microcobol.lex"
Constructing NFA : 437 states in NFA
Converting NFA to DFA : 
..............................................................................................................................................................................................................................
224 states before minimization, 191 states in minimized DFA
Writing code to "Yylex.java"
java -jar ../lib/java-cup-11b.jar microcobol.cup
Warning : Terminal "FROM" was declared but never used
Warning : Terminal "MULTIPLY" was declared but never used
Warning : Terminal "SUBSTRACT" was declared but never used
Warning : Terminal "VALUE" was declared but never used
Warning : Terminal "GIVING" was declared but never used
Warning : Terminal "BY" was declared but never used
Warning : Terminal "DIVIDE" was declared but never used
Warning : Terminal "DISPLAY" was declared but never used
Warning : *** Production "listeinst ::= instruction " never reduced
Warning : *** Production "listeinst ::= listeinst instruction " never reduced
Warning : *** Production "listeobjets ::= objet " never reduced
Warning : *** Production "listeobjets ::= listeobjets objet " never reduced
------- CUP v0.11b 20150326 (SVN rev 63) Parser Generation Summary -------
  0 errors and 12 warnings
  30 terminals, 19 non-terminals, and 32 productions declared, 
  producing 74 unique parse states.
  8 terminals declared but not used.
  0 non-terminals declared but not used.
  0 productions never reduced.
  0 conflicts detected (0 expected).
  Code written to "parser.java", and "sym.java".
---------------------------------------------------- (CUP v0.11b 20150326 (SVN rev 63))
mkdir -p classes/microcobol
javac -d classes -cp ../lib/jflex.jar:../lib/java-cup-11b.jar Objet.java Variable.java Litteral.java Chaine.java Nombre.java Condition.java Instruction.java Phrase.java Paragraphe.java WorkingSect.java Data.java Programme.java IdDiv.java DataDiv.java ProcDiv.java MoveInst.java AddInst.java SubstractInst.java MultiplyInst.java DivideInst.java DisplayInst.java StopInst.java IfInst.java LexicalException.java Yylex.java sym.java parser.java
jar -cvf microcobol.jar -C classes microcobol
manifeste ajouté
ajout : microcobol/(entrée = 0) (sortie = 0)(stockage : 0 %)
ajout : microcobol/parser.class(entrée = 3168) (sortie = 1384)(compression : 56 %)
ajout : microcobol/StopInst.class(entrée = 300) (sortie = 229)(compression : 23 %)
ajout : microcobol/DisplayInst.class(entrée = 993) (sortie = 582)(compression : 41 %)
ajout : microcobol/Objet.class(entrée = 237) (sortie = 188)(compression : 20 %)
ajout : microcobol/MultiplyInst.class(entrée = 689) (sortie = 410)(compression : 40 %)
ajout : microcobol/WorkingSect.class(entrée = 870) (sortie = 529)(compression : 39 %)
ajout : microcobol/MoveInst.class(entrée = 677) (sortie = 404)(compression : 40 %)
ajout : microcobol/LexicalException.class(entrée = 298) (sortie = 213)(compression : 28 %)
ajout : microcobol/AddInst.class(entrée = 674) (sortie = 400)(compression : 40 %)
ajout : microcobol/Chaine.class(entrée = 607) (sortie = 366)(compression : 39 %)
ajout : microcobol/SubstractInst.class(entrée = 694) (sortie = 413)(compression : 40 %)
ajout : microcobol/ProcDiv.class(entrée = 881) (sortie = 531)(compression : 39 %)
ajout : microcobol/IfInst.class(entrée = 1367) (sortie = 707)(compression : 48 %)
ajout : microcobol/parser$CUP$parser$actions.class(entrée = 8045) (sortie = 3149)(compression : 60 %)
ajout : microcobol/Nombre.class(entrée = 362) (sortie = 251)(compression : 30 %)
ajout : microcobol/DivideInst.class(entrée = 685) (sortie = 410)(compression : 40 %)
ajout : microcobol/DataDiv.class(entrée = 564) (sortie = 355)(compression : 37 %)
ajout : microcobol/Phrase.class(entrée = 549) (sortie = 343)(compression : 37 %)
ajout : microcobol/IdDiv.class(entrée = 598) (sortie = 384)(compression : 35 %)
ajout : microcobol/Programme.class(entrée = 950) (sortie = 539)(compression : 43 %)
ajout : microcobol/Paragraphe.class(entrée = 1069) (sortie = 598)(compression : 44 %)
ajout : microcobol/Instruction.class(entrée = 249) (sortie = 199)(compression : 20 %)
ajout : microcobol/Variable.class(entrée = 360) (sortie = 248)(compression : 31 %)
ajout : microcobol/Condition.class(entrée = 1314) (sortie = 781)(compression : 40 %)
ajout : microcobol/Yylex.class(entrée = 10361) (sortie = 5775)(compression : 44 %)
ajout : microcobol/Litteral.class(entrée = 201) (sortie = 162)(compression : 19 %)
ajout : microcobol/sym.class(entrée = 1495) (sortie = 823)(compression : 44 %)
ajout : microcobol/OpComp.class(entrée = 1108) (sortie = 587)(compression : 47 %)
ajout : microcobol/Data.class(entrée = 579) (sortie = 362)(compression : 37 %)
javac -cp ../lib/jflex.jar:../lib/java-cup-11b.jar:microcobol.jar TestParser.java
Note: TestParser.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
mra@geslegen:~/cours/as/tp/microcobol/src $

Il est possible de tester le parser dans l’état actuel en invoquant la commande :

mra@geslegen:~/cours/as/tp/microcobol/src $ java -cp ../lib/java-cup-11b-runtime.jar:microcobol.jar:. TestParser test1.cb
IDENTIFICATION DIVISION.
  PROGRAM-ID test1.
END PROGRAMME test1.

Question 1   Complétez le code dans microcobol.cup pour ajouter les instruction arithmétiques SUBSTRACT MULTIPLY DIVIDE. Testez alors votre code sur test2.cb.
Question 2   Complétez le code dans microcobol.cup pour ajouter l’instruction conditionnelle IF.
Question 3   Complétez le code dans microcobol.cup et microcobol.lex et rajoutez une classe PerformInst.java pour ajouter l’instruction de boucle PERFORM. Testez alors votre code sur test3.cb.

1.4  Instruction COMPUTE

Nous souhaitons compléter le langage en rajoutant une instruction COMPUTE permettant de calculer des expressions arithméthiques plus simplement.

COMPUTE x = (3 * y + 2) ^ 3 - k / 12
Question 4   Complétez le code en implémentant ce qu’il faut pour utiliser cette instruction. Testez votre code sur test4.cb. Indication : créez une classe Expression, et utilisez le TP précédent.

Ce document a été traduit de LATEX par HEVEA