Langage interprété, les bases.
Publié : mer. 20/sept./2006 23:26
Salut à tous, suite à la demande d'un membre, je post ma façon d'interprété un langage préalablement créé.
Tout dabord nous allons voir le "Parsing" , le parsing , c'est l'analyse du code, Il faut se mettre à la place d'un compilo, comment fait t'il pour séparer les commentaires du code , comment sait il qu'il y a plusieurs commande sur une seule ligne, etc... , en fait le compilo ne fait rien à part compilé, on lui file du code épurer c'est tout, c'est à dire que le code viens d'être "parser" , il n'y a plus de commentaires, ni d'espace inutile, etc...
C'est ce que nous allons faire ici , nous allons ensemble creer notre langage !
Commencons par le parser.
Voila un langage factice, notre but va être donc d'épurer le code
sans meme connaitre d'avance la syntaxe de mot clé, tel "repete" ou "infini" , nous allons donc isolé le code du reste, c'est à dire que l'on va virer les commentaires. les espaces inutiles , etc...
Voici une rapide description du langage :
Voici le parser en PB :
Laisser le debugger, Enregistrer le fichier ci dessus au format Txt, une boite de dialogue vous sera alors demandé.
La prochaine et dernière étape sera l'execution du code.
@++
Tout dabord nous allons voir le "Parsing" , le parsing , c'est l'analyse du code, Il faut se mettre à la place d'un compilo, comment fait t'il pour séparer les commentaires du code , comment sait il qu'il y a plusieurs commande sur une seule ligne, etc... , en fait le compilo ne fait rien à part compilé, on lui file du code épurer c'est tout, c'est à dire que le code viens d'être "parser" , il n'y a plus de commentaires, ni d'espace inutile, etc...
C'est ce que nous allons faire ici , nous allons ensemble creer notre langage !
Commencons par le parser.
Voila un langage factice, notre but va être donc d'épurer le code
sans meme connaitre d'avance la syntaxe de mot clé, tel "repete" ou "infini" , nous allons donc isolé le code du reste, c'est à dire que l'on va virer les commentaires. les espaces inutiles , etc...
Voici une rapide description du langage :
- /* Commentaires */
Si Condition Alors Action , similaire a If - Then
Repete infini Boucle infinie
/* Code D'exemple
D'un langage interpreter
tout simple, pas de boucle imbriqué
du style : If If endif if if endif endif endif .....
Pas d'opération mathématique, juste du code bidon ;D
*/
/* D ailleurs je trouve ce type de commentaire très pratique !
LE CODE EST LA SOURCE DU PROGRAMMEUR, L'INTERPRETEUR DOIT LE PARSER AVANT !
Rien ne vous empêche de faire un Editeur de ce fabuleux langage qu'est le votre!
Avec la syntaxe colorisée etc...
*/
/*Boucle principale :
OuvrirEcran() /*Ouverture de l'écran*/
Repete
EffaceEcran /*On efface l'ecran*/
Affiche "Hello World!" /* On affiche hello world!*/
Si Touche(Echap) : Alors : Quitte /* Si echap,alors on quitte*/
Bip() : Dort(100) : Bip() /* 3 commandes sur une seule ligne !!!!!!!! */
Infini
Voici le parser en PB :
Laisser le debugger, Enregistrer le fichier ci dessus au format Txt, une boite de dialogue vous sera alors demandé.
Code : Tout sélectionner
; PARSING PAR CPL.BATOR
; =====================
#EOL = Chr(13)+Chr(10)
Structure PARSER
CMD$
Ligne.l
EndStructure : Global NewList CodeBrut.PARSER()
Structure FINAL_CODE
CMD$
FichierLigne.l
Ligne.l
JumpTO.l
LastRepeat.l
EndStructure : Global NewList Code.FINAL_CODE()
Global BufferA$ ;Le buffer va souvent nous servir de Tampon pour les modifs
Global BufferB$ ; et les comparaison
Global Brut$ ;On mettra notre fichier a "parser" dedans.
FILE_FOR_PARSING$ = OpenFileRequester("Ouvrir","","*.txt",0)
;-PHASE 1 LECTURE DU FICHIER
; ON STOCKE LE FICHIER A PARSER EN MEMOIRE, ON LE MET DANS : CodeBrute()
OpenFile(0,FILE_FOR_PARSING$)
While Eof(0)=0
Brut$ = Brut$ + ReadString(0) + #EOL ; On lit la ligne et on la stocke
Wend
CloseFile(0)
;Une fois notre fichier stocké dans la liste chainée, on peut commencer le traitement
;On va commencer par supprimer tout les commentaires
;-PHASE 2 SUPPRESSION DES COMMENTAIRES
For i = 1 To Len(Brut$)
If Commentaire=0 : BufferA$ = BufferA$ + Mid(Brut$,i,1) : EndIf
If Commentaire=1 : BufferB$ = BufferB$ + Mid(Brut$,i,1) : EndIf
If FindString(BufferA$,"/*",1) : Commentaire=1 : BufferA$ = RemoveString(BufferA$,"/*") : EndIf
If FindString(BufferB$,"*/",1) : Commentaire=0 : BufferB$ = RemoveString(BufferB$,"*/") : EndIf
Next
Brut$ = BufferA$ ; On passe le Buffer dans le brut, les commentaires sont supprimés ;)
BufferA$ = ""
;-PHASE 3 TROUVER DES COMMANDES QUI SONT SUR UNE SEULE LIGNE
; Il peut y avoir des commandes du style = Bip():Bip():Bip():end
; il va falloir transformer cela en :
;Bip()
;Bip()
;Bip()
;End
For i = 1 To Len(Brut$)
BufferA$ = BufferA$ + Mid(Brut$,i,1)
If FindString(BufferA$,":",1)
BufferA$ = RemoveString(BufferA$,":")
BufferA$ = BufferA$ + #EOL
EndIf
Next
Brut$ = BufferA$
BufferA$ = ""
;-PHASE 4 PREPARATION A L'INTEGRATION DANS UN TABLEAU
;Vu que notre code se trouve dans une variable , il va falloir que l'on sépare les lignes de codes
;Afin de mettre toutes nos commandes dans un tableau ou une liste chainée de préférence.
; Code(1) = Commande N°1
; Code(2) = Commande N°2
; Code(3) = Commande N°3
; Etc....
For i = 1 To Len(Brut$)
BufferA$ = BufferA$ + Mid(Brut$,i,1)
BufferA$=LTrim(BufferA$)
If FindString(BufferA$,#EOL,1)
AddElement(CodeBrut())
CodeBrut()\CMD$ = BufferA$
CodeBrut()\Ligne = ListIndex(CodeBrut()) ; On note la ligne, ca peut servir pour gerer avec précision des erreurs d'interprétation.
BufferA$=""
EndIf
Next
;{
; Notre code est à present nettoyer de tous les commentaires...
; A present il sera plus facile pour nous , de programmer l'interpreteur en lui meme.
; Comme vous avez pu voir en phase 4, on stocke nos commandes dans une liste chainée "Code()"
; Chaque element represente un code qui va être interprété.
; ForEach Code()
;
; Debug "Ligne numéro : " + Str(CodeBrut()\Ligne)
; Debug "CMD$ : " + CodeBrut()\CMD$
; Debug "----------------------------------------"
;
; Next
; Si vous executez ce code , vous pouvez apercevoir les fin de chaines et des lignes vides
; La prochaine étape consiste a stocker uniquement les chaines non nulle
;}
;-PHASE 5 FIN DE L'EPURATION DES CHAINES DE CARACTERERES
; On supprime les charactères de fin de chaines (#EOL)
ForEach CodeBrut() : CodeBrut()\CMD$ = RemoveString(CodeBrut()\CMD$,#EOL) : Next
ForEach CodeBrut() ; On Stocke les chaines non nulle , dans une autre liste qui va nous servir de "main courante" pour l'execution du code.
If CodeBrut()\CMD$<>""
AddElement(Code())
Code()\CMD$ = CodeBrut()\CMD$
Code()\FichierLigne = CodeBrut()\Ligne
Code()\Ligne = ListIndex(Code())
EndIf
Next
; Nous avons isolé nos lignes de commandes, Maintenant on va pouvoir commencer à interpreté.
Debug "PHASE 5 - LIGNE 145"
ForEach Code()
Debug "Commande N°"+ Str(Code()\Ligne) + " = " + Code()\CMD$ + " Ligne n° " +Str( Code()\FichierLigne)
Debug "-------------------------------------------------"
Next
@++