IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

Grammaire : équivalent de token header { '[' <-[ \[\] ]>+ ']' } [perl6]


Sujet :

Langage Perl

  1. #1
    Membre à l'essai
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Octobre 2016
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2016
    Messages : 39
    Points : 23
    Points
    23
    Par défaut Grammaire : équivalent de token header { '[' <-[ \[\] ]>+ ']' }
    Bonjour ,

    J'ai encore une nouvelle question sur la rédaction d'une grammaire en perl6.

    Je souhaiterai faire un token identique à :

    token header { '[' <-[ \[\] ]>+ ']' } ( voir https://docs.perl6.org/language/rege..._and_Capturing )

    mais au lieu de '[' et de ']' , j'aimerai pourvoir donner une chaine complète de caractère. Par exemple, (pas vraiment au hasard), '[' deviendrait 'EXEC SQL' et ']' deviendrait 'END-EXEC'.

    Malgré de nombreuses tentatives, je n'arrive pas à exprimer l'équivalent de <-[ \[\] ]>+ .

    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
      rule  TOP     {[<sqlstart> <sqltext> <sqlend>]}
        token sqlstart  {'EXEC SQL'}
        token sqlend  {'END-EXEC'}
        token sqltext     { <-[<sqlstart><sqlend>]>* }
    ne fonctionne pas et donne comme résultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    TOP
    |  sqlstart
    |  * MATCH "EXEC SQL"
    |  sqltext
    |  * MATCH "INCLUDE SQLCA END-EXEC\n"
    |  sqlend
    |  * FAIL
    * FAIL
    A mon grand regret, le token sqltext prend le END-EXEC ...
    Auriez-vous une idée ?
    Par avance merci.

  2. #2
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    <-[ \[\] ]> est une classe de caractères et reconnaît donc tout caractère autre qu'un crochet ouvrant ou un crochet fermant. Ça ne peut pas marcher avec des chaînes.

    Le plus simple serait peut-être de reconnaître un nombre quelconque de caractères quelconques, avec un quantificateur "frugal" (c'est-à-dire non-gourmand) et une règle de type regex pour permettre le retour arrière.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    rule  TOP     {[<sqlstart> <sqltext> <sqlend>]}
    token sqlstart  {'EXEC SQL'}
    token sqlend  {'END-EXEC'}
    regex sqltext     { .+? }
    A la réflexion, une quantificateur frugal est sans doute inutile dans ce cas précis du moment que tu utilises une règle de type regex, mais c'est sans doute préférable tout de même pour des cas plus généraux.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Octobre 2016
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2016
    Messages : 39
    Points : 23
    Points
    23
    Par défaut
    Merci beaucoup pour cette réponse pertinente et très rapide.

    J'ai donc fait le test :

    1 -- avec le mode frugal :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    #!/opt/rakudo-star-2016.10/bin/perl6
    use v6;
    use Grammar::Tracer;
     
    grammar TEST {
     
    rule  TOP     { \s* [<sqlstart> <sqltext> <sqlend>]}
      token sqlstart  {'EXEC SQL'}
      token sqlend  {'END-EXEC'}
      regex sqltext     { .+? }
    }
     
    my $cbl = q:to/FIN_INI/;
    EXEC SQL include sqlca END-EXEC
    FIN_INI
     
    my $scr = TEST.parse($cbl);
    say $scr;
    Résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    TOP
    |  sqlstart
    |  * MATCH "EXEC SQL"
    |  sqltext
    |  * MATCH "i"
    |  sqlend
    |  * FAIL
    |  sqlend
    |  * FAIL
    |  sqlend
    |  * MATCH "END-EXEC"
    * MATCH "EXEC SQL include sqlca END-EXEC"
    (Any)
    2 - en mode avide :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    #!/opt/rakudo-star-2016.10/bin/perl6
    use v6;
    use Grammar::Tracer;
     
    grammar TEST {
     
    rule  TOP     { \s* [<sqlstart> <sqltext> <sqlend>]}
      token sqlstart  {'EXEC SQL'}
      token sqlend  {'END-EXEC'}
      regex sqltext     { .+ }
     
    }
    my $cbl = q:to/FIN_INI/;
    EXEC SQL include sqlca END-EXEC
    FIN_INI
     
    my $scr = TEST.parse($cbl);
    say $scr;
    C'est donc le mode avide qui correspond à ma problèmatique.

    Ceci dit dans les deux cas la variable $scr n'est pas initialisé par le parse et reste à Any ....
    Si je supprime l'usage de Grammar::Tracer, l'affichage de mon script se limite à
    Snif ...

    Qu'ai-je encore fait ? ...

    Merci encore pour l'aide.
    Bien cordialement,

  4. #4
    Membre à l'essai
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Octobre 2016
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2016
    Messages : 39
    Points : 23
    Points
    23
    Par défaut
    J'ai trouvé une autre syntaxe, totalement par hasard.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    #!/opt/rakudo-star-2016.10/bin/perl6
    use v6;
    use Grammar::Tracer;
    #use Grammar::Debugger;
     
    grammar TEST {
     
    rule  TOP     { \s* [<sqlstart> <sqltext> <sqlend>]}
      token sqlstart  {'EXEC SQL'}
      token sqlend  {'END-EXEC'}
      regex sqltext     { .+ <before 'END-EXEC'> }
    }
    my $cbl = q:to/FIN_INI/;
    EXEC SQL include sqlca END-EXEC
    FIN_INI
     
    my $scr = TEST.parse($cbl);
    say $scr;
    le resultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    TOP
    |  sqlstart
    |  * MATCH "EXEC SQL"
    |  sqltext
    |  * MATCH "include sqlca "
    |  sqlend
    |  * MATCH "END-EXEC"
    * MATCH "EXEC SQL include sqlca END-EXEC"
    (Any)

    mais la variable $scr n'est toujours pas initialisée ...

    re-snif ...

  5. #5
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Voici un test que j'ai fait avec le mode avide:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    use v6;
    grammar SQL {
        rule  TOP     {[<sqlstart> <sqltext> <sqlend>]}
        token sqlstart  {'EXEC SQL'}
        token sqlend  {'END-EXEC'}
        regex sqltext     { .+ }
    }
     
    my $str = "EXEC SQL select toto from tata where titi = titi END-EXEC";
     
    my $matched = SQL.parse($str);
    say $matched;
    Ce qui donne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $ perl6 sql_grammar.pl6
    「EXEC SQL select toto from tata where titi = titi END-EXEC」
     sqlstart => 「EXEC SQL」
     sqltext => 「select toto from tata where titi = titi 」
     sqlend => 「END-EXEC」
    Donc ça marche comme tu le désires (je suppose).

    Et ça marche aussi bien (dans ce cas) avec le mode frugal:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    use v6;
    #use Grammar::Tracer;
     
    grammar SQL {
        rule  TOP     {[<sqlstart> <sqltext> <sqlend>]}
        token sqlstart  {'EXEC SQL'}
        token sqlend  {'END-EXEC'}
        regex sqltext     { .+? }
    }
     
    my $str = "EXEC SQL select toto from tata where titi = titi END-EXEC";
     
    my $matched = SQL.parse($str);
    say $matched;
    Ce qui donne la même chose:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $ perl6 sql_grammar.pl6
    「EXEC SQL select toto from tata where titi = titi END-EXEC」
     sqlstart => 「EXEC SQL」
     sqltext => 「select toto from tata where titi = titi」
     sqlend => 「END-EXEC」
    (Excuse ma requête SQL un peu stupide, ce n'est pas l'objet du test.)

    EDIT: oups, il y a un problème d'UTF8, les guillemets japonais 「 et 」 n'ont pas l'air de passer dans les blocs de code sur le forum. Sans balise de code, ça donne:

    $ perl6 sql_grammar.pl6
    「EXEC SQL select toto from tata where titi = titi END-EXEC」
    sqlstart => 「EXEC SQL」
    sqltext => 「select toto from tata where titi = titi」
    sqlend => 「END-EXEC」

  6. #6
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Je viens d'essayer ton code, le problème provient de l'initialisation de ta variable $cbl, qui contient un retour à la ligne à la fin. Considère le code suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    use v6;
    use Grammar::Tracer;
     
    grammar TEST {
     
    rule  TOP     { \s* [<sqlstart> <sqltext> <sqlend>]}
      token sqlstart  {'EXEC SQL'}
      token sqlend  {'END-EXEC'}
      regex sqltext     { .+ }
     
    }
    my $cbl = q:to/FIN_INI/;
    EXEC SQL include sqlca END-EXEC
    FIN_INI
     
    say "<$cbl>";
    $cbl ~~ s/\n//;
     
    my $scr = TEST.parse($cbl);
    say $scr;
    L'affichage de "<$cbl>" donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    <EXEC SQL include sqlca END-EXEC
    >
    C'est le retour à la ligne après le deuxième EXEC qui fait foirer le test.

    En ajoutant une substitution:
    pour supprimer ce retour, le code fonctionne:

    「EXEC SQL include sqlca END-EXEC」
    sqlstart => 「EXEC SQL」
    sqltext => 「include sqlca 」
    sqlend => 「END-EXEC」

    L'autre solution est bien sûr de modifier la règle TOP pour tenir compte de ce retour chariot (considéré comme un espace dans le code ci-dessous):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    rule  TOP     { \s* [<sqlstart> <sqltext> <sqlend>] \s*}
    Et ça marche sans problème et affiche la même chose que ci-dessus.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Octobre 2016
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2016
    Messages : 39
    Points : 23
    Points
    23
    Par défaut
    C'est exactement cela.... le \n de la fin...

    Mon bout de code fonctionne correctement en rajoutant un espace à la regle TOP.

    Il me reste encore une question. Il peut y avoir plusieurs sequences sql enchainés. Par exemple:

    EXEC SQL select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC

    J'envisageais le code suivant pour en tenir compte.:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    #!/opt/rakudo-star-2016.10/bin/perl6
    use v6;
    use Grammar::Tracer;
    #use Grammar::Debugger;
     
    grammar TEST {
     
    rule  TOP     { <sql>* }
    rule  sql     { \s* [<sqlstart> <sqltext> <sqlend>] }
      token sqlstart  {'EXEC SQL'}
      token sqlend  {'END-EXEC'}
      regex sqltext     { .+ <before 'END-EXEC'> }
    }
    my $cbl = q:to/FIN_INI/;
    EXEC SQL select select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC
    FIN_INI
     
    my $scr = TEST.parse($cbl);
    say $scr;
    mais vu le résultat, je dois encore faire une erreur ....

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    TOP
    |  sql
    |  |  sqlstart
    |  |  * MATCH "EXEC SQL"
    |  |  sqltext
    |  |  * MATCH "select select toto from tata where titi = titi END-EXE"
    |  |  sqlend
    |  |  * MATCH "END-EXEC"
    |  * MATCH "EXEC SQL select select toto from tata where titi = titi E"
    |  sql
    |  |  sqlstart
    |  |  * FAIL
    |  * FAIL
    * MATCH "EXEC SQL select select toto from tata where titi = titi END-"
    「EXEC SQL select select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC
    
     sql => 「EXEC SQL select select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC
    
      sqlstart => 「EXEC SQL」
      sqltext => 「select select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata 」
       before => 「」
      sqlend => 「END-EXEC」
    Après c'est peut être mieux si je crée une autre discussion pour cela.

    Merci beaucoup, beaucoup pour toute l'aide apportée.
    Bien cordialement,

  8. #8
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Bonjour,
    je ne peux tester sur ma tablette, donc je parle sans filet, mais je pense qu'il faudrait sans doute changer cette règle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    rule  sql     { \s* [<sqlstart> <sqltext> <sqlend>] }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    rule  sql     { \s* [<sqlstart> <sqltext> <sqlend>] \s* }
    pour permettre le reconnaissance du saut de ligne entre deux requêtes SQL. De plus, les crochets me paraissent inutiles ici, donc j'essaierais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    rule  sql     { \s* <sqlstart> <sqltext> <sqlend> \s* }

  9. #9
    Membre à l'essai
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Octobre 2016
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2016
    Messages : 39
    Points : 23
    Points
    23
    Par défaut
    Merci beaucoup pour cette réponse.

    Comme je peux tester, je ne me suis pas privé.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    #!/opt/rakudo-star-2016.10/bin/perl6
    use v6;
    use Grammar::Tracer;
    #use Grammar::Debugger;
     
    grammar TEST {
     
    rule  TOP     { <sql>* }
    rule  sql     { \s* <sqlstart> <sqltext> <sqlend> \s* }
      token sqlstart  {'EXEC SQL'}
      token sqlend  {'END-EXEC'}
      regex sqltext     { .+ }
    }
    my $cbl = q:to/FIN_INI/;
    EXEC SQL select select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC
    FIN_INI
     
    my $scr = TEST.parse($cbl);
    say $scr;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    TOP
    |  sql
    |  |  sqlstart
    |  |  * MATCH "EXEC SQL"
    |  |  sqltext
    |  |  * MATCH "select select toto from tata where titi = titi END-EXE"
    |  |  sqlend
    |  |  * FAIL
    |  |  sqlend
    |  |  * FAIL
    |  |  sqlend
    |  |  * FAIL
    |  |  sqlend
    |  |  * FAIL
    |  |  sqlend
    |  |  * MATCH "END-EXEC"
    |  * MATCH "EXEC SQL select select toto from tata where titi = titi E"
    |  sql
    |  |  sqlstart
    |  |  * FAIL
    |  * FAIL
    * MATCH "EXEC SQL select select toto from tata where titi = titi END-"
    「EXEC SQL select select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC
    
     sql => 「EXEC SQL select select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC
    
      sqlstart => 「EXEC SQL」
      sqltext => 「select select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata 」
      sqlend => 「END-EXEC」
    (J'ai egalement essayé en mode frugal ou avec regex sqltext { .+ <before 'END-EXEC'> } mais je ne vois pas de différence)


    Donc l'ajout de \s* ne semble pas suffire. Seul le dernier END-EXEC est bien reconnu...
    Bizarre, bizarre ...

    Encore merci.
    Bien cordialement,

  10. #10
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Bonjour,

    je viens d'essayer le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    grammar TEST {
      rule  TOP     { <sql>* }
      rule  sql     { \s* <sqlstart> <sqltext> <sqlend> \s* }
      token sqlstart  {'EXEC SQL'}
      token sqlend  {'END-EXEC'}
      regex sqltext     { .+ }
    }
    my $cbl = q:to/FIN_INI/;
    EXEC SQL select select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC
    FIN_INI
     
    my $scr = TEST.parse($cbl);
    say $scr;
    sur le site: https://glot.io/new/perl6 permettant de tester du code Perl 6 en ligne.

    A vue de nez, le résultat semble correct et conforme à l'attendu:

    「EXEC SQL select select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC

    sql => 「EXEC SQL select select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC

    sqlstart => 「EXEC SQL」
    sqltext => 「select select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata 」
    sqlend => 「END-EXEC」

  11. #11
    Membre à l'essai
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Octobre 2016
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2016
    Messages : 39
    Points : 23
    Points
    23
    Par défaut
    En fait il faut obtenir :

    「EXEC SQL select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC

    sql => 「EXEC SQL select toto from tata where titi = titi END-EXEC

    sqlstart => 「EXEC SQL」
    sqltext => 「select toto from tata where titi = titi」
    sqlend => 「END-EXEC」
    sql => 「EXEC SQL select 'x' from tata END-EXEC

    sqlstart => 「EXEC SQL」
    sqltext => 「select 'x' from tata」
    sqlend => 「END-EXEC」



    J'y suis arrivé gracé au code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    use v6;
    grammar TEST {
     
    rule  TOP     { <sql>* }
    rule  sql     { \s* <sqlstart> <sqltext> <sqlend> \s* }
      token sqlstart  {^^'EXEC SQL'}
      token sqlend  {'END-EXEC'}
      regex sqltext     { .+? }
    }
    my $cbl = q:to/FIN_INI/;
    EXEC SQL select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC
    FIN_INI
     
    my $scr = TEST.parse($cbl);
    say $scr;
    Je profite du fait que EXEC SQL commence une ligne ...
    Le mode frugal semble indispensable pour ce cas de figure ...

    Il faut maintenant que je regarde comment mixer du code non sql avec mes EXEC SQL ...
    Mais c'est une autre histoire, je créerai certainement une nouvelle discussion pour cela.

    Merci énormément pour l'aide rapide, pertinente et efficace ....
    Bien cordialement,

  12. #12
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Bonsoir,

    en fait, ton exemple (post #9 à 11h00) montre parfaitement la différence entre le quantificateur gourmand et le quantificateur frugal.

    D'abord le gourmand:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    grammar TEST {
    rule  TOP     { <sql>* }
    rule  sql     { \s* <sqlstart> <sqltext> <sqlend> \s*}
      token sqlstart  {'EXEC SQL'}
      token sqlend  {'END-EXEC'}
      regex sqltext     { .+  }
    }
    my $cbl = q:to/FIN_INI/;
    EXEC SQL select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC
    FIN_INI
     
    my $scr = TEST.parse($cbl);
    say $scr;
    Résultat:

    「EXEC SQL select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC

    sql => 「EXEC SQL select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC

    sqlstart => 「EXEC SQL」
    sqltext => 「select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata 」
    before => 「」
    sqlend => 「END-EXEC」


    Ce qui se passe est que la regex "gobe" lors de son premier appel l'ensemble de la chaîne de caractères depuis le premier EXEC SQL jusqu'au dernier END-EXEC, et recupère donc les deux requêtes SQL; du coup, l'appel suivant à la règle <sql> échoue.

    Avec un quantificateur frugal:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    grammar TEST {
    rule  TOP     { <sql>* }
    rule  sql     { \s* <sqlstart> <sqltext> <sqlend> \s*}
      token sqlstart  {'EXEC SQL'}
      token sqlend  {'END-EXEC'}
      regex sqltext     { .+? }
    }
    my $cbl = q:to/FIN_INI/;
    EXEC SQL select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC
    FIN_INI
     
    my $scr = TEST.parse($cbl);
    say $scr;
    On a ceci:

    「EXEC SQL select toto from tata where titi = titi END-EXEC
    EXEC SQL select 'x' from tata END-EXEC

    sql => 「EXEC SQL select toto from tata where titi = titi END-EXEC

    sqlstart => 「EXEC SQL」
    sqltext => 「select toto from tata where titi = titi」
    sqlend => 「END-EXEC」
    sql => 「EXEC SQL select 'x' from tata END-EXEC

    sqlstart => 「EXEC SQL」
    sqltext => 「select 'x' from tata」
    sqlend => 「END-EXEC」


    La reconnaissance s'arrête au premier END-EXEC, ce qui permet à la seconde reconnaissance (deuxième requête SQL) de réussir.

    C'est pour cela que je disais que le quantificateur frugal n'était pas nécessaire dans ton exemple d'origine (avec une seule requête). Mais il est nécessaire dans un cas plus complexe comme ton exemple avec deux requêtes. Avec deux requêtes successives (ou plus), le quantificateur frugal empêche le regex de reconnaître trop de caractères dès la première passe et s'arrête là où il faut, c'est-à-dire à la fin de la première requête.

    Relance éventuellement ces deux exemples en activant Grammar::Tracer, tu devrais mieux comprendre le cheminement de la grammaire.

    L'utilisation d'un quantificateur frugal est ici plus robuste, à mon avis, que l'utilisation d'une ancre de début de ligne comme tu l'a fait.

  13. #13
    Membre à l'essai
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Octobre 2016
    Messages
    39
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2016
    Messages : 39
    Points : 23
    Points
    23
    Par défaut
    Oui, le quantificateur frugal est indispensable pour mon deuxième cas de figure. Je pensais d'ailleurs associé le quantificateur frugal et l'ancre. Mais effectivement, le quantificateur frugal suffit.
    la syntaxe regex -> "sqltext { .+? <before 'END-EXEC'> }" me rassure aussi, même si je ne suis pas sur quelle apporte réellement quelque chose.
    Les Grammar::Tracer et Grammar:: Debugger sont également précieux.

    Encore merci pour toutes ces explications.
    ( Et certainement, à trés bientôt pour une prochaine question. )
    Bien cordialement,

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Faire un équivalent header C
    Par Eagles dans le forum Modules
    Réponses: 0
    Dernier message: 18/12/2009, 11h59
  2. équivalent de header("Location")
    Par persia dans le forum Langage
    Réponses: 2
    Dernier message: 13/01/2009, 04h47
  3. [postgreSQL] équivalent de la function 'instr'
    Par Dra_Gun dans le forum Requêtes
    Réponses: 2
    Dernier message: 17/01/2003, 16h09
  4. Équivalent du #IFDEF
    Par agh dans le forum Langage
    Réponses: 4
    Dernier message: 14/10/2002, 18h44
  5. Réponses: 2
    Dernier message: 21/05/2002, 10h25

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo