décomposer une ligne de code dans un tableau

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
Micoute
Messages : 2584
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

décomposer une ligne de code dans un tableau

Message par Micoute »

Bonjour à tous j'aimerais lire un fichier texte et entrer chaque données dans un tableau

Voici un exemple:
Si Abc<24|Abc=32&Abc<>Def FinSi
Si,Abc<24|Abc=32&Abc<>Def,FinSi
Si,Abc;<:24;|,Abc:=;32,&;Abc:<>;Def,FinSi
Si Abc < 24 | Abc = 32 & Abc <> Def FinSi
Si A = 24 Tableau[125, 65] Et Limiteur{145} >= 32 Et " Ceci est une chaînes de caractères "
Si C <= Commande(A, (10), , {25}, C, 60) et D = 64 ' Si A = 24 Et B >= 32
A B C D E F = 1
A, B, C, D, E, F = 1
Si A, B, C, D, E, F = 1, 2, 3 Ou 4 à 10
Sinon Si A = 125.258
Sinon
Abc = " Ceci est une " + chaîne + "de caractères "
Abc = " Ceci est une ""chaîne"" de caractères "
' Ceci est un commentaire
Fin Si

Merci pour vos réponses.
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 6.20 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Marc56
Messages : 2198
Inscription : sam. 08/févr./2014 15:19

Re: décomposer une ligne de code dans un tableau

Message par Marc56 »

Bonjour Micoute,

Qu'appelles-tu ici une "donnée" ? (un mot ? une expression ?)
Faut-il se baser sur un/des séparateur(s) ou sur des mots-clés ?
Faut-il un tableau à une ou plusieurs dimensions ?

Un exemple de ce que tu souhaites en entrée et en sortie serait un plus.

:wink:
Avatar de l’utilisateur
Micoute
Messages : 2584
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: décomposer une ligne de code dans un tableau

Message par Micoute »

Merci Marc56, en fait j'essaie de faire un petit langage interprété et je voudrais faire un truc du genre et je souhaiterais que le programme sépare les instructions et les mette dans un tableau, par exemple à une dimension :
Si A=24&B>=Tableau[125, 65]|Limiteur{145}>=32&C<=50&D=64"Une ""chaînes"" de caractères avec guillemets"A=24&B>=32|C<=50&D=64 A=24"Une chaîne de caractères sans guillemet"&B>=Tableau[125, 65]|Limiteur{145}>=32&C<=50&D=64'A=24&B>=Tableau[125, 65]|Limiteur{145}>=32&C<=50&D=60
et je voudrais que ça sorte :
Si
A
=
24
&
B
>=
Tableau[125, 65]
|
Limiteur{145}
>=
32
&
C
<=
50
&
D
=
64
"Une ""chaînes"" de caractères avec guillemets"
A
=
24
&
B
>=
32
|
C
<=
50
&
D
=
64
A
=
24
"Une chaîne de caractères sans guillemet"
&
B
>=
Tableau[125, 65]
|
Limiteur{145}
>=
32
&
C
<=
50
&
D
=
64
dès que le programme trouve un apostrophe qui n'est pas dans une chaine de caractère, qu'il ignore le restant de la ligne.
Quand le programme trouve une chaine de caractères et qu'il voit deux chaînes à la suite, ça veux dire qu'il faudra afficher un guillemet dans la chaîne lors de l'affichage ou l'enregistrement de la chaîne.
Je pense que pour débuguer un code se sera beaucoup plus simple de séparer une ligne de code ainsi, vous en pensez quoi ?
Merci encore.
Dernière modification par Micoute le mar. 02/juin/2015 18:04, modifié 1 fois.
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 6.20 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Patrick88
Messages : 1564
Inscription : mer. 21/janv./2004 18:24

Re: décomposer une ligne de code dans un tableau

Message par Patrick88 »

C'est pas pour ce genre de truc, les expressions régulières ?
Ollivier
Messages : 4197
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: décomposer une ligne de code dans un tableau

Message par Ollivier »

Salut Micoute,

Fais des boucles "For I = 1 To LChaine" soit:

- pour faire une analyse/transformation globale;
- pour faire une succession
d'analyses/transformations de chaînes

semblant de code: (je suis sur mobile)

Code : Tout sélectionner

B.S
LChaine = Len(Chaine$)
PeC = 1 ; Niveau de prise en charge
             ; Utile pour la gestion des parenthèses
For I = 1 To LChaine
   ; Ici (commenté), on shunte l'index de boucle I
   ;   pour déterminer où se trouve telle ou telle
   ;   ponctuation.

   ;   Ponctuation$ = "."
   ;   I = FindString(Chaine$, Ponctuation$, I)

     A = Asc(Mid(Chaine$, I, 1) )
    If A = Asc("'")
       PeC ! 1
    Endif

   if A = 60 ; à vérif caractère ASCII de la parenthèse gauche 
       PeC + 2
   endif

   If A = 62 ; à vérif caractère ASCII de la parenthèse droite 
       PeC - 2
   endif

   If PeC & 1
     B + Chr(A)
   EndIf

Next
Chaine$ : c'est le fichier à charger et à stocker dans Chaine$
I : c'est l'index d'une boucle qui entoure ta base A définie ci-dessus.

PeC : Variable de profondeur de prise en charge
Bit 0 (bit de parité) : normalement non commenté
(0, PeC est pair) sinon commenté (1, PeC impair)
Bit 1 à 30 : numéro de couche de parenthèse

Entrée: (Chaine$)

'pif commenté'def(var(x))int

Sortie: (B)

def(var(x))int

avec def et int en couche 0
var en couche 1
et x en couche 2

couche est récupérable comme suit:
coucheNo = PeC >> 1

(note : il peut y avoir des superpositions entre une
paire d'apostrophe)

Bon courage à toi!
Marc56
Messages : 2198
Inscription : sam. 08/févr./2014 15:19

Re: décomposer une ligne de code dans un tableau

Message par Marc56 »

Bonjour Micoute,

Gros projet, mais intéressant dans lequel tu te lances là. Comme toujours en info, ce qui parait simple au premier abord l'est beaucoup moins en pratique (et inversement) :P 8O

Au premier abord, il faut commencer par une analyse lexicale.
Un lien intéressant: http://fr.wikipedia.org/wiki/Analyse_lexicale

La première phase va donc consister à lister tous les mots-clés que ton analyseur devra isoler.
Tu devrais trouver des exemples et idées dans les outils de coloration syntaxique des différents éditeurs.

Ce n'est pas si évident que cela, car il faut par exemple voir dans quel cas un caractère est un caractère neutre.
Exemple:

Cos(a)
Cos( a )
Cos (a)
Cos (a)

Puis gérer l'encapsulation d'une commande dans une autre

int (cos (a))

etc

J'ai cru en lisant ton premier post, que ça allait être simple, mais en y réfléchissant ça l'est beaucoup moins 8O

:wink:
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: décomposer une ligne de code dans un tableau

Message par G-Rom »

J'ai créer un compilateur ASM il y a 2 ou 3 ans en PureBasic pour les puces Microchip (pic)
https://code.google.com/p/purepicbasic-compiler/
Le code est très propre , je me suis occupé de la partie ASM -> binaire , dans le dossier basic/include , il y a pas mal de fichier auquel tu pourras t'appuyer dessus.

Le principe est simple , je sépare chaque mot de mon source code ( jeton ) , je leur donne une valeur "jeton_inconnu" à tous dès le départ , ensuite j'analyse tout les jetons , je les identifie , si c'est un nombre, un nom ( une variable, un registre, ou une commande ) , une valeur ( hexa, decimale, binaire , etc... ) , ce qui me donne une liste du genre :
- jeton_variable
- jeton_operateur
- jeton_nombre
- etc...
Pour l'analyse de syntaxe , c'est plus facile à gérer , si deux jeton_variable se suivent par exemple il y a une erreur de syntaxe , si un jeton n'a pas réussi à être identifié , il y a une erreur lexicale.

Bon épluchage ^^

@++
Avatar de l’utilisateur
Micoute
Messages : 2584
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: décomposer une ligne de code dans un tableau

Message par Micoute »

Merci beaucoup pour vos réponses qui je l'espère ne seront pas vaines, en tout cas je vais agir dans ce sens !
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 6.20 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Avatar de l’utilisateur
Micoute
Messages : 2584
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: décomposer une ligne de code dans un tableau

Message par Micoute »

Voici un aperçu du travail accompli, il y a surement des choses à améliorer et je compte sur vous pour me guider, je vous en remercie tous beaucoup par avance.

Code : Tout sélectionner

; -D- 02 - 06 - 2015 -D-

;{ Procédures de détection du type de caractère
Procedure.b RechercheCaractere(Caractere$, GroupeCaractere$)
  
  ; Recherche dans les caracères
  For Index = 1 To Len(GroupeCaractere$)
    
    If Caractere$ = Mid(GroupeCaractere$, Index, 1)
      ProcedureReturn  #True
    EndIf
    
  Next
  
  ProcedureReturn #False
  
EndProcedure

; Le caractère est t-il une lettre quelconque ou un chiffre ?
Procedure.b LettresEtChiffres(Caractere$)
  
  LettresEtChiffres$ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + "àáâãäåçèéêëìíîïñòóôõö" + Chr(154) + "ùúûüýÿ" + Chr(158) + "ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖ" + Chr(138) + "ÙÚÛÜÝ" + Chr(159) + Chr(142) + "0123456789"
  
  If RechercheCaractere(Caractere$, LettresEtChiffres$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; Le caractère est t-il une lettre quelconque ?
Procedure.b Lettres(Caractere$)
  
  Lettres$ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + "àáâãäåçèéêëìíîïñòóôõö" + Chr(154) + "ùúûüýÿ" + Chr(158) + "ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖ" + Chr(138) + "ÙÚÛÜÝ" + Chr(159) + Chr(142)
  
  If RechercheCaractere(Caractere$, Lettres$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; Le caractère est t-il une lettre non Accentuée ?
Procedure.b LettresNonAccentuees(Caractere$)
  
  LettresNonAccentuees$ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  
  If RechercheCaractere(Caractere$, LettresNonAccentuees$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; Le caractère est t-il une lettre Accentuée ?
Procedure.b LettresAccentuees(Caractere$)
  
  LettresAccentuees$ = "àáâãäåçèéêëìíîïñòóôõö" + Chr(154) + "ùúûüýÿ" + Chr(158) + "ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖ" + Chr(138) + "ÙÚÛÜÝ" + Chr(159) + Chr(142)
  
  If RechercheCaractere(Caractere$, LettresAccentuees$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; Le caractère est t-il une Lettre Minuscule Non Accentuée ?
Procedure.b LettresMinusculeNonAccentuees(Caractere$)
  
  LettresMinusculeNonAccentuees$ = "abcdefghijklmnopqrstuvwxyz"
  
  If RechercheCaractere(Caractere$, LettresMinusculeNonAccentuees$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; Le caractère est t-il une Lettre Minuscule Accentuée ?
Procedure.b LettresMinusculeAccentuees(Caractere$)
  
  LettresMinusculeAccentuees$ = "àáâãäåçèéêëìíîïñòóôõö" + Chr(154) + "ùúûüýÿ" + Chr(158) ; šž
  
  If RechercheCaractere(Caractere$, LettresMinusculeAccentuees$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; Le caractère est t-il une Lettre Majuscule Non Accentuée ?
Procedure.b LettresMajusculeNonAccentuees(Caractere$)
  
  LettresMajusculeNonAccentuees$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  
  If RechercheCaractere(Caractere$, LettresMajusculeNonAccentuees$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; Le caractère est t-il une Lettre Majuscule Accentuée ?
Procedure.b LettresMajusculeAccentuees(Caractere$)
  
  LettresMajusculeAccentuees$ = "ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖ" + Chr(138) + "ÙÚÛÜÝ" + Chr(159) + Chr(142) ; ŠŽŸ
  
  If RechercheCaractere(Caractere$, LettresMajusculeAccentuees$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; Le caractère est t-il un Chiffres ?
Procedure.b Chiffres(Caractere$)
  
  Chiffres$ = "0123456789"
  
  If RechercheCaractere(Caractere$, Chiffres$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; Le caractère est t-il un Opérateur ?
Procedure.b Operateur(Caractere$)
  
  Operateurs$ = "+-*/|~&%^=<>!?"
  
  If RechercheCaractere(Caractere$, Operateurs$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; Le caractère est t-il un Symbole ?
Procedure.b Symbole(Caractere$)
  
  Symboles$ = "@#$£µ§²"
  
  If RechercheCaractere(Caractere$, Symboles$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; Le caractère est t-il une Ponctuation ?
Procedure.b Ponctuation(Caractere$)
  
  Ponctuations$ = ".,:;"
  
  If RechercheCaractere(Caractere$, Ponctuations$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; Le caractère est t-il une Parenthese ?
Procedure.b Parenthese(Caractere$)
  
  Parentheses$ = "()"
  
  If RechercheCaractere(Caractere$, Parentheses$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; Le caractère est t-il un Crochet ?
Procedure.b Crochet(Caractere$)
  
  Crochets$ = "[]"
  
  If RechercheCaractere(Caractere$, Crochets$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; Le caractère est t-il une Accolade ?
Procedure.b Accolade(Caractere$)
  
  Accolades$ = "{}"
  
  If RechercheCaractere(Caractere$, Accolades$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; Le caractère est t-il un Caracteres Special ?
Procedure.b CaracteresSpecial(Caractere$)
  
  CaracteresSpeciaux$ = "'`_\°" + Chr(34)
  
  If RechercheCaractere(Caractere$, CaracteresSpeciaux$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure

; Le caractère est t-il un Caractere Invisible ?
Procedure.b CaractereInvisible(Caractere$)
  
  For I = 0 To 32
    CaracteresInvisible$ + Chr(I)
  Next
  
  CaracteresInvisible$ + Chr(129) + Chr(141) + Chr(143) + Chr(144) + Chr(157) + Chr(160)
  
  If RechercheCaractere(Caractere$, CaracteresInvisible$) = #True
    ProcedureReturn #True
  Else
    ProcedureReturn #False
  EndIf
  
EndProcedure
;}

Procedure DecoupeurDeLigneDeCode(LigneDeCode$, Array TableauParametres.s(1))
  
  EnableExplicit
  
  ; Variables de la procédures
  Protected IndexLigne = 0 ; Index dans la ligne de code
  Protected IndexLigneTemps = 0 ; Index secondaire dans la ligne de code
  Protected Mot$ = ""           ; Dernier mot extrait dans la ligne de code
  Protected Caractere$ = ""     ; Caractère actuel extrait dans la ligne de code
  Protected CaractereTemps$ = ""; Caractère secondaire actuel extrait dans la ligne de code
  Protected Operateur$ = ""   ; Opérateurs extrait dans la ligne de code
  Protected ChaineCaracteres$ = "" ; Chaîne de caractères extrait dans la ligne de code
  Protected PositionDebutChaine = 0; Position de détection de début de chaîne de caractères '"' dans la ligne de code
  Protected PositionFinChaine = 0  ; Position de détection de fin de chaîne de caractères '"' dans la ligne de code
  Protected PositionDebutCommande = 0 ; Position de détection de début de Commande '(' dans la ligne de code
  Protected PositionFinCommande = 0   ; Position de détection de fin de Commande ')' dans la ligne de code
  Protected CompteurParentheses = 0   ; Compteur de parenthèse
  Protected Commande$ = ""            ; Commande extrait dans la ligne de code
  Protected PositionDebutTableau = 0  ; Position de détection de début de Tableau '[' dans la ligne de code
  Protected PositionFinTableau = 0    ; Position de détection de fin de Tableau ']' dans la ligne de code
  Protected CompteurCrochet = 0       ; Compteur de crochets
  Protected Tableau$ = ""             ; Tableau extrait dans la ligne de code
  Protected PositionDebutLimiteur = 0 ; Position de détection de début de Limiteur '{' dans la ligne de code
  Protected PositionFinLimiteur = 0   ; Position de détection de fin de Limiteur '}' dans la ligne de code
  Protected CompteurAccolade = 0      ; Compteur d'accolades
  Protected Limiteur$ = ""            ; Limiteur extrait dans la ligne de code
  
  ; Parcours chaque caractere de la ligne de code
  For IndexLigne = 1 To Len(LigneDeCode$) + 1 ; + 1 pour savoir quand on atteint la fin de la ligne de code
    
    ; Extraction du caractère à la position de 'IndexLigne'
    Caractere$ = Mid(LigneDeCode$, IndexLigne, 1) ; Renvera "" si on est à la fin de la ligne de code
    
    ; Si on est pas dans un limiteur
    If PositionDebutLimiteur = 0
      
      ; Si on est pas dans un tableau
      If PositionDebutTableau = 0
        
        ; Si on n'est pas dans une Commande
        If PositionDebutCommande = 0
          
          ; Si on n'est pas dans une chaîne de caractère
          If PositionDebutChaine = 0
            
            ; Si le caractère est vide ou si il est invisible, on considère que le mot est terminé
            If (Caractere$ = "" Or Caractere$ = "," Or Caractere$ = ";" Or Caractere$ = ":" Or Caractere$ = "'" Or Caractere$ = Chr(34) Or CaractereInvisible(Caractere$) = #True Or Operateur(Caractere$) = #True Or Parenthese(Caractere$) = #True Or Crochet(Caractere$) = #True Or Accolade(Caractere$) = #True)
              
              ; On enregistre le mot dans le tableau des paramètres:
              
              ; Si on a enregistrer un mot
              If Mot$ > ""
                
                ; Si le caractère n'est ni une parenthèse, ni un Crochet, ni une accolade
                If (Parenthese(Caractere$) = #False And Crochet(Caractere$) = #False And Accolade(Caractere$) = #False)
                  
                  ; Si le dernier élément du tableau est vide, alors ce dernier reçoit le parametre
                  If TableauParametres.s(ArraySize(TableauParametres.s())) = ""
                    TableauParametres.s(ArraySize(TableauParametres.s())) = Mot$
                    
                  Else ; Sinon Si le dernier élément du tableau n'est pas vide, on augmente la taille du tableau de +1 et ce dernier reçoit le parametre
                    ReDim TableauParametres.s(ArraySize(TableauParametres.s()) + 1)
                    TableauParametres.s(ArraySize(TableauParametres.s())) = Mot$
                    
                  EndIf
                  
                  ; On vide la variable car le paramètre a été enregistré
                  Mot$ = ""
                  
                EndIf
                
              EndIf
              
              ; Si le caractère est un opérateur
              If Operateur(Caractere$) = #True
                
                ; Enregistrement de l'opérateur
                Operateur$ = Caractere$
                
                ; On va extraire tous les autres opérateurs qui se trouvent à la suite s'il en a
                For IndexLigneTemps = IndexLigne + 1 To Len(LigneDeCode$) + 1 ; + 1 car ce caractère est déjà fait, + 1 pour savoir quand on atteint la fin de la ligne de code
                  
                  ; Extraction du prochain caractère de la ligne de code
                  CaractereTemps$ = Mid(LigneDeCode$, IndexLigneTemps, 1)
                  
                  ; Si le caractère est un opérateur
                  If Operateur(CaractereTemps$) = #True
                    
                    ; Enregistrement de l'opérateur
                    Operateur$ + CaractereTemps$
                    
                  Else ; Sinon, on stoppe ici, si le caractère n'est pas un opérateur
                    
                    ; On enregistre le paramètre des opérateurs
                    
                    ; Si le dernier élément du tableau est vide, alors ce dernier reçoit le parametre
                    If TableauParametres.s(ArraySize(TableauParametres.s())) = ""
                      TableauParametres.s(ArraySize(TableauParametres.s())) = Operateur$
                      
                    Else ; Sinon Si le dernier élément du tableau n'est pas vide, on augmente la taille du tableau de +1 et ce dernier reçoit le parametre
                      ReDim TableauParametres.s(ArraySize(TableauParametres.s()) + 1)
                      TableauParametres.s(ArraySize(TableauParametres.s())) = Operateur$
                      
                    EndIf
                    
                    ; On vide la variable car le paramètre a été enregistré
                    Operateur$ = ""
                    
                    ; Le caractère est-il supérieur à rien
                    If CaractereTemps$ > ""
                      
                      ; On enregistre la position dans la ligne de code -1 car il faut refaire le dernier caractère, IndexLigne prendra + 1 à la prochaine itération
                      IndexLigne = IndexLigneTemps - 1
                      Break ; On saute cette boucle et on continue 
                      
                    Else ; Sinon c'est qu'on a atteint la fin de la ligne
                      ProcedureReturn ; On stoppe là, on termine la ligne
                      
                    EndIf
                    
                  EndIf
                  
                Next
                
                ; Sinon Si le caractère est un guillemet '"'
              ElseIf Caractere$ = Chr(34) And PositionDebutChaine = 0 ; '"'
                PositionDebutChaine = IndexLigne                      ; On enregistre la position de début de chaîne
                
                ; Sinon Si le caractère est une parenthèse ouvrante
              ElseIf Caractere$ = "("
                PositionDebutCommande = IndexLigne - Len(Mot$) ; On enregistre la position de début de commande
                CompteurParentheses + 1                        ; On ajoute 1 pour indiquer qu'on à trouvé une parenthèse ouvrante
                
                ; Sinon Si le caractère est un Crochet ouvrant
              ElseIf Caractere$ = "["
                PositionDebutTableau = IndexLigne - Len(Mot$) ; On enregistre la position de début de tableau
                CompteurCrochet + 1                           ; On ajoute 1 pour indiquer qu'ont à trouvé un Crochet ouvrant
                
                ; Sinon Si le caractère est une accolade ouvrante
              ElseIf Caractere$ = "{"
                PositionDebutLimiteur = IndexLigne - Len(Mot$) ; On enregistre la position de début de limiteur
                CompteurAccolade + 1                           ; On ajoute 1 pour indiquer qu'on à trouvé une accolade ouvrante
                
                ; Sinon Si le caractère est une appostrophe, c'est un commentaire
              ElseIf Caractere$ = "'"
                ProcedureReturn ; On stoppe là, on termine la ligne car c'est un commentaire
                
              EndIf
              
              ; Sinon Si c'est n'importe quoi d'autre comme caractère
            Else  
              Mot$ + Caractere$ ; On prend le caractère, peut importe ce que c'est
              
            EndIf
            
            ; Sinon Si on se trouve dans une chaîne de caractère
          ElseIf PositionDebutChaine > 0
            
            ; Si le caractère extrait est un guillemet ou rien
            If Caractere$ = Chr(34) Or Caractere$ = "" ; '"'
              
              ; Extraction du prochain caractère de la ligne de code
              CaractereTemps$ = Mid(LigneDeCode$, IndexLigne + 1, 1)
              
              ; Si c'est encore un '"', alors ce n'est pas une fin de chaîne mais un double guillemet qui indique qu'il faudra afficher un guillemet dans la chaîne de caractères.
              If CaractereTemps$ = Chr(34)
                IndexLigne + 1 ; Car on à déjà vérifié le prochain caractère qui est aussi un '"'
                
              Else ; Par contre si le prochain caractère n'est pas un '"', alors la fin de chaîne est terminée.
                
                ; Enregistrement de la position de la fin de la chaîne de caractères
                PositionFinChaine = IndexLigne
                
                ; Enregistrement de la chaîne de caractères trouvée
                ChaineCaracteres$ = Mid(LigneDeCode$, PositionDebutChaine, ((PositionFinChaine + 1) - PositionDebutChaine))
                
                ; On enregistre le paramètre de la chaîne de caractères
                
                ; Si le dernier élément du tableau est vide, alors ce dernier reçoit le paramètre
                If TableauParametres.s(ArraySize(TableauParametres.s())) = ""
                  TableauParametres.s(ArraySize(TableauParametres.s())) = ChaineCaracteres$
                  
                Else ; Sinon Si le dernier élément du tableau n'est pas vide, on augmente la taille du tableau de +1 et ce dernier reçoit le paramètre
                  ReDim TableauParametres.s(ArraySize(TableauParametres.s()) + 1)
                  TableauParametres.s(ArraySize(TableauParametres.s())) = ChaineCaracteres$
                  
                EndIf
                
                ; On remet la variable à 0 car le paramètre a été enregistré
                PositionDebutChaine = 0
                
              EndIf
              
            EndIf
            
          EndIf
          
          ; Sinon Si on est dans une commande
        ElseIf PositionDebutCommande > 0
          
          ; Si le caractère est une parenthèse ouvrante
          If Caractere$ = "("
            CompteurParentheses + 1 ; On ajoute 1 pour indiquer qu'on à trouvé une parenthèse ouvrante
            
            ; Si le caractère est une parenthèse fermente
          ElseIf Caractere$ = ")"
            CompteurParentheses - 1 ; On enlève 1 pour indiquer qu'on à trouvé une parenthèse fermante
            
          EndIf
          
          ; Si la variable vaut 0, alors il y a autant de parenthèses ouvrantes que de fermantes, commande terminée
          If CompteurParentheses = 0
            
            ; Enregistrement de la position de la fin de la commande
            PositionFinCommande = IndexLigne
            
            ; Enregistrement de la chaîne de caractères trouvée
            Commande$ = Mid(LigneDeCode$, PositionDebutCommande, ((PositionFinCommande + 1) - PositionDebutCommande))
            
            ; On enregistre le paramètre de la commande
            
            ; Si le dernier élément du tableau est vide, alors ce dernier reçoit le parametre
            If TableauParametres.s(ArraySize(TableauParametres.s())) = ""
              TableauParametres.s(ArraySize(TableauParametres.s())) = Commande$
              
            Else ; Sinon Si le dernier élément du tableau n'est pas vide, on augmente la taille du tableau de +1 et ce dernier reçoit le parametre
              ReDim TableauParametres.s(ArraySize(TableauParametres.s()) + 1)
              TableauParametres.s(ArraySize(TableauParametres.s())) = Commande$
              
            EndIf
            
            ; On remet la variable à 0 car le paramètre a été enregistré
            PositionDebutCommande = 0
            
            ; On vide la variable car le paramètre a été enregistré
            Mot$ = ""
            
          EndIf
          
        EndIf
        
        ; Sinon Si on est dans un tableau
      ElseIf PositionDebutTableau > 0
        
        ; Si le caractère est un Crochet ouvrant
        If Caractere$ = "["
          CompteurCrochet + 1 ; On ajoute 1 pour indiquer qu'on à trouvé un Crochet ouvrant
          
          ; Si le caractère est un Crochet fermant
        ElseIf Caractere$ = "]"
          CompteurCrochet - 1 ; On enlève 1 pour indiquer qu'on à trouvé un Crochet fermant
          
        EndIf
        
        ; Si la variable vaut 0, alors il y a autant de Crochets ouvrants que de fermants, tableau terminé
        If CompteurCrochet = 0
          
          ; Enregistrement de la position de la fin du tableau
          PositionFinTableau = IndexLigne
          
          ; Enregistrement du tableau trouvé
          Tableau$ = Mid(LigneDeCode$, PositionDebutTableau, ((PositionFinTableau + 1) - PositionDebutTableau))
          
          ; On enregistre le paramètre du tableau
          
          ; Si le dernier élément du tableau est vide, alors ce dernier reçoit le parametre
          If TableauParametres.s(ArraySize(TableauParametres.s())) = ""
            TableauParametres.s(ArraySize(TableauParametres.s())) = Tableau$
            
          Else ; Sinon Si le dernier élément du tableau n'est pas vide, on augmente la taille du tableau de +1 et ce dernier reçoit le parametre
            ReDim TableauParametres.s(ArraySize(TableauParametres.s()) + 1)
            TableauParametres.s(ArraySize(TableauParametres.s())) = Tableau$
            
          EndIf
          
          ; On remet la variable à 0 car le paramètre a été enregistré
          PositionDebutTableau = 0
          
          ; On vide la variable car le paramètre a été enregistré
          Mot$ = ""
          
        EndIf
        
      EndIf
      
      ; Sinon Si on est dans un limiteur
    ElseIf PositionDebutLimiteur > 0
      
      ; Si le caractère est une accolade ouvrante
      If Caractere$ = "{"
        CompteurAccolade + 1 ; On ajoute 1 pour indiquer qu'on à trouvé une accolade ouvrante
        
        ; Si le caractère est une accolade fermante
      ElseIf Caractere$ = "}"
        CompteurAccolade - 1 ; On enlève 1 pour indiquer qu'on à trouvé une accolade fermante
        
      EndIf
      
      ; Si la variable vaut 0, alors il y a autant d'accolades ouvrantes que de fermantes, tableau terminé
      If CompteurAccolade = 0
        
        ; Enregistrement de la position de la fin du limiteur
        PositionFinLimiteur = IndexLigne
        
        ; Enregistrement du tableau trouvé
        Limiteur$ = Mid(LigneDeCode$, PositionDebutLimiteur, ((PositionFinLimiteur + 1) - PositionDebutLimiteur))
        
        ; On enregistre le paramètre du limiteur
        
        ; Si le dernier élément du tableau est vide, alors ce dernier reçoit le parametre
        If TableauParametres.s(ArraySize(TableauParametres.s())) = ""
          TableauParametres.s(ArraySize(TableauParametres.s())) = Limiteur$
          
        Else ; Sinon Si le dernier élément du tableau n'est pas vide, on augmente la taille du tableau de +1 et ce dernier reçoit le parametre
          ReDim TableauParametres.s(ArraySize(TableauParametres.s()) + 1)
          TableauParametres.s(ArraySize(TableauParametres.s())) = Limiteur$
          
        EndIf
        
        ; On remet la variable à 0 car le paramètre a été enregistré
        PositionDebutLimiteur = 0
        
        ; On vide la variable car le paramètre a été enregistré
        Mot$ = ""
        
      EndIf
      
    EndIf
    
  Next
  
  DisableExplicit
  
EndProcedure

LigneDeCode$ = "Si A=24&B>=Tableau[125, 65]|Limiteur{145}>=32&C<=50&D=64" + Chr(34) + "Une " + Chr(34) + Chr(34) + "chaînes" + Chr(34) + Chr(34) + " de caractères avec guillemets" + Chr(34) + "A=24&B>=32|C<=50&D=64 A=24" + Chr(34) + "Une chaîne de caractères sans guillemets" + Chr(34) + "&B>=Tableau[125, 65]|Limiteur{145}>=32&C<=50&D=64'A=24&B>=Tableau[125, 65]|Limiteur{145}>=32&C<=50&D=60"

Dim TableauParametres.s(0)

;OpenConsole()
DecoupeurDeLigneDeCode(LigneDeCode$, TableauParametres.s())

For Index = 0 To ArraySize(TableauParametres.s())
  Debug TableauParametres.s(Index)
Next

;Input()

; -D- 02 - 06 - 2015 -D-
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 6.20 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
G-Rom
Messages : 3641
Inscription : dim. 10/janv./2010 5:29

Re: décomposer une ligne de code dans un tableau

Message par G-Rom »

le soucis c'est que si ton code a parser comporte des erreurs de syntaxe, tu sera incapable de dire sur quelle ligne , ou , quoi.
Il faut que :

- Tu ignores les commentaire de ton script
- Tu stockes tout tes mots "brut" dans une liste , chaque mot possède 3 attributs important : le mot brut , la ligne ou il écrit , le nom du fichier
- A partir de la liste brute , tu détermine les symbole de chaque mot
- Tu appliques les instruction préprocesseur ( si tu en as ) macro , include , constante , etc...
- Tu créer les différentes table ( variable , nom des fontions , etc... )
- A ce stade , tout les symboles sont identifié ( variable , fonction , nombre , opérateur , etc... )
- Tu fait ton analyse syntaxique ( symbole inconnu = erreur )
- Tu fait ton analyse lexicale ( 2 symbole qui ne doivent pas être contiguë )
- Si il y a une erreur , tu as juste à lire à partir du symbole qui pose problème , ses attributs , et affiché un message d'erreur cohérent.
- Tu peu généré un byte-code maison pour chaque symbole

A ce stade , tu as un byte code (code intermédiaire) propre et sans erreur, c'est ce que l'on appelle une partie arrière d'un compilateur.

Ton byte code peu être de se style pour le code suivant :
MyVarA As integer
MyVarB As integer

MyVarA = 45
MyVarB = MyVarA * 2
le byte code :
;MyVarA = 45
$DD000000 ; Cherche dans table variable
$00000001 ; MyVarA ( position 1 )
$000000FF ; Operateur =
$FF000000 ; Valeur immédiate
$0000002D ; 45
$FFFFFFFF ; Fin instruction

;MyVarB = MyVarA * 2
$DD000000 ; Cherche dans table variable
$00000002 ; MyVarB ( position 2 dans table )
$000000FF ; Operateur =
$DD000000 ; Cherche dans table variable
$00000001 ; MyVarA
$000000FE ; Operateur *
$FF000000 ; Valeur immédiate
$00000002 ; 2


C'est un exemple, mais à partir de ce byte code , tu as une multitude d'options pour la suite :

- convertir ton byte code dans un autre langage
- créer du code pour un os/processeur spécifique
- créer une machine virtuelle ( un interpréteur )

Pour ton cas, c'est la solution numéro 3. ton byte code pourra être dans un fichier , en mémoire , etc...
Si tu as compris le principe du byte code, ce sera du gâteau à interprété , la correction du code à été faite en amont, on part donc du principe que le byte code est correct, l’exécution sera donc proche d'un exécutable natif.
Il ne faut pas se leurré , c'est une tâche difficile surtout l'analyse d'erreur, mais c'est faisable. ;)
Avatar de l’utilisateur
Micoute
Messages : 2584
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: décomposer une ligne de code dans un tableau

Message par Micoute »

Merci beaucoup G-Rom pour cette réponse.
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 6.20 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Répondre