The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Parse::Lex - Générateur d'analyseurs lexicaux (Beta 2.02).

SYNOPSIS

        require 5.004;

        use Parse::Lex;
        @token = (
          qw(
             ADDOP    [-+]
             LEFTP    [\(]
             RIGHTP   [\)]
             INTEGER  [1-9][0-9]*
             NEWLINE  \n
             
            ),
          qw(STRING),   [qw(" (?:[^"]+|"")* ")],
          qw(ERROR  .*), sub {
            die qq!can\'t analyze: "$_[1]"!;
          }
         );

        Parse::Lex->trace;  # Class method
        $lexer = Parse::Lex->new(@token);
        $lexer->from(\*DATA);
        print "Tokenization of DATA:\n";

        TOKEN:while (1) {
          $token = $lexer->next;
          if (not $lexer->eoi) {
            print "Line $.\t";
            print "Type: ", $token->name, "\t";
            print "Content:->", $token->text, "<-\n";
          } else {
            last TOKEN;
          }
        }

        __END__
        1+2-5
        "a multiline
        string with an embedded "" in it"
        an invalid string with a "" in it"

DESCRIPTION

La classe Parse::Lex permet de créer des analyseurs lexicaux. Un analyseur lexical est spécifié au moyen d'un liste de tokens passée en argument à la méthode new().

Parse::Lex ne fonctionne qu'avec perl 5.004. Si votre version est antérieure, utilisez la sous-classe Parse::CLex. Les analyseurs générés par ces deux classes exploitent des techniques d'analyse différentes :

1. Parse::Lex utilise pos(), associé à \G,

2. Parse::CLex utilise s/// et donc consomme le flot de caractères à analyser.

Les analyseurs de la classe Parse::CLex ne permettent pas d'utiliser des expressions régulières avec ancrage.

Les tokens sont des objets de la classe Parse::Token, livré avec Parse::Lex. La définition d'un token comporte ordinairement deux arguments : un nom symbolique (comme INTEGER), suivi d'une expression régulière. Si une fonction anonyme est donnée en troisième argument, elle est exécutée lorsque le token est reconnu. Elle reçoit en argument l'objet Parse::Token, suivi de la chaîne reconnue par l'expression régulière. Le scalaire retourné par la fonction anonyme définit la chaîne de caractères placée dans l'objet Parse::Token.

L'ordre dans lequel l'analyseur lexical examine les expressions régulières est déterminé par l'ordre dans lequel ces expressions sont passées en argument à la méthode new(). Le token retourné par l'analyseur lexical correspond à la première expression qui s'apparie avec le début du flot de caractères à analyser (la stratégie est différente de celle adoptée par l'analyseur lexical LEX qui retourne la plus longue chaîne de toutes celles qu'il est possible de reconnaître). Le token est un objet de la classe Parse::Token.

Les analyseurs lexicaux peuvent reconnaître des tokens disposés sur plusieurs enregistrements. Si la définition du token comporte plusieurs expressions régulières, et est placée dans un tableau anonyme, l'analyseur lit autant d'enregistrements que nécessaire pour reconnaître le token (voir la documentation de la classe Parse::Token). Lorsque que le motif du début est trouvé, l'analyseur en cherche la fin, et si besoin est, lit de nouveaux enregistrements. Il n'y a pas de rebroussement en cas d'échec.

L'analyseur peut être utilisé pour analyser une chaîne de caractères isolée ou un flot de données provenant d'une entrée quelconque. Lorsque l'analyseur a épuisé les données il retourne un objet Parse::Token dont le nom est EOI (End Of Input).

Conditions

Il est possible d'associer des conditions de déclenchement aux règles de reconnaissance de tokens qui composent votre analyseur lexical (à la manière de ce l'on trouve dans FLEX). Grâce aux conditions la règle qui réussit n'est plus obligatoirement la première qui s'apparie.

Toute désignation de symbole peut être précédée par la spécification de conditions d'activation de la règle de reconnaissance associée. Par exemple :

        qw(C1:TERMINAL_1  REGEXP), sub { # associated action },
        qw(TERMINAL_2  REGEXP), sub { # associated action },

Le symbole TERMINAL_1 ne sera reconnu que si la condition C1 est active. L'activation/désactivation s'opère respectivement aux moyens des méthodes start(NOM_CONDITION) et end(NOM_CONDITION).

start('INITIAL') permet de remettre à zéro l'automate d'analyse.

Les conditions peuvent être combinées aux moyens d'opérateurs ET/OU comme suit :

        C1:SYMBOL      condition C1

        C1:C2:SYMBOL   condition C1 ET condition C2

        C1,C2:SYMBOL   condition C1 OU condition C2

Il existe deux types de conditions : les conditions inclusives et les conditions exclusives, respectivement déclarées par les méthodes de classe inclusive() et exclusive(). Avec une condition inclusive les règles actives sont celles qui comportent la condition, ainsi que celles qui n'en comportent pas du tout. Avec une condition exclusive, seules les règles qui comportent cette condition sont actives. Toutes les autres sont désactivées.

Exemple (emprunté à la documentation de FLEX).

 use Parse::Lex;
 @token = (
          'EXPECT', 'expect-floats', sub {
            $lexer->start('expect'); 
            $_[1] 
          },
          'expect:FLOAT', '\d+\.\d+', sub { 
            print "found a float: $_[1]\n";
            $_[1] 
          },
          'expect:NEWLINE', '\n', sub { 
            $lexer->end('expect') ;
            $_[1] 
          },
          'NEWLINE2', '\n',
          'INT', '\d+', sub {
            print "found an integer: $_[1] \n";
            $_[1] 
          },
          'DOT', '\.', sub {
            print "found a dot\n";
            $_[1] 
          },
         );

 Parse::Lex->exclusive('expect');
 $lexer = Parse::Lex->new(@token);

La condition spéciale ALL est toujours vérifiée.

Méthodes

analyze EXPR

Analyze EXPR et retourne une liste de couples composés d'un nom de token suivi du texte reconnu. EXPR peut être une chaîne de caractères ou une référence à un filehandle.

Exemples.

 @tokens = Parse::Lex->new(qw(PLUS [+] NUMBER \d+))->analyze("3+3+3");
 @tokens = Parse::Lex->new(qw(PLUS [+] NUMBER \d+))->analyze(\*STREAM);
buffer EXPR
buffer

Retourne le contenu du buffer interne à l'analyseur lexical. Avec une expression en argument, place le résultat de l'expression dans le buffer.

Il n'est pas conseillé de changer directement le contenu du buffer sans changer la position du pointeur qui suit l'analyse (pos()) et la valeur de la longueur du buffer (length()).

end EXPR

Désactive la condition EXPR.

eoi

Retourne VRAI lorsqu'il n'y a plus de données à analyser.

every SUB

Évite de devoir écrire une boucle de lecture pour analyser un flot de données. SUB est une fonction anonyme exécutée après la reconnaissance de chaque token. Par exemple, pour analyser la chaîne "1+2" vous pouvez écrire :

        use Parse::Lex;

        $lexer = Parse::Lex->new(
          qw(
             ADDOP [-+]
             INTEGER \d+
            ));

        $lexer->from("1+2");
        $lexer->every (sub { 
          print $_[0]->name, "\t";
          print $_[0]->text, "\n"; 
        });

Le premier argument de la fonction anonyme est l'objet Token reconnu.

exclusive LISTE

Méthode de classe déclarant comme exclusives les conditions présentes dans LISTE.

flush

Si la conservation des chaînes consommées est activée, flush() retourne et vide le buffer contenant les chaînes de caractères reconnues jusqu'ici. Utile seulement si vous êtes dans le mode activé par hold().

from EXPR
from

from(EXPR) permet d'indiquer les données à analyser ou la source des données à analyser. L'argument de cette méthode est donc, soit une chaîne de caractère (ou une liste), soit une référence à un filehandle. Avec un argument retourne l'objet receveur. Sans argument retourne le filehandle s'il est défini, sinon undef.

Par défaut on suppose que les données sont lues sur STDIN.

Exemple.

        $lexer->from(\*DATA);
        $lexer->from('les données à analyser');
getSub

getSub() retourne la fonction anonyme réalisant l'analyse lexicale.

Exemple.

        my $token = '';
        my $sub = $lexer->getSub;
        while (($token = &$sub()) ne $Token::EOI) {
          print $token->name, "\t";
          print $token->text, "\n";
        }
    
   # or 
        
        my $token = '';
        local *tokenizer = $lexer->getSub;
        while (($token = tokenizer()) ne $Token::EOI) {
          print $token->name, "\t";
          print $token->text, "\n";
        }
getToken

Synonyme de la méthode token().

hold EXPR
hold

Active/désactive la conservation des chaînes analysées (et consommées dans le cas de Parse::CLex). Retourne la valeur courante. Peut être utilisée comme méthode de classe.

On peut obtenir le contenu du buffer au moyen de la méthode flush() qui a également pour effet de vider le buffer.

inclusive LISTE

Méthode de classe déclarant comme inclusives les conditions présentes dans LISTE.

length EXPR
length

length() Retourne la longueur de l'enregistrement courant. length EXPR fixe la longueur de cet enregistrement.

line EXPR
line

line retourne le numéro de l'enregistrement courant. line EXPR permet de fixer ce numéro. Retourne toujours 1 si on analyse une chaîne de caractères. La méthode readline() incrémente le numéro de ligne.

name EXPR
name

Permet de donner un nom à un analyseur lexical. name() permet de connaître ce nom.

next

Provoque la recherche du prochain token. Retourne l'objet Token reconnu. Retourne l'objet Token::EOI en fin de données.

Exemples.

        $lexer = Parse::Lex->new(@token);
        print $lexer->next->name;   # print the token type
        print $lexer->next->text;   # print the token content
new LISTE

Crée et retourne un nouvel analyseur lexical. L'argument de la méthode est une liste d'objets de la classe Parse::Token ou de triplets permettant de les créer. Ces triplets sont constitués du nom symbolique du token, de l'expression régulière nécessaire à sa reconnaissance et éventuellement d'une fonction anonyme exécutée lors de la reconnaissance du token. Pour chaque triplet, un objet de type Parse::Token est créé dans le package appelant.

offset

Retourne le nombre de caractères déjà consommé depuis le début du flot de données analysé.

pos EXPR
pos

pos EXPR fixe la position de début du prochain token à reconnaître dans l'enregistrement courant (ne fonctionne pas avec les analyseurs de la classe Parse::CLex). pos() retourne le nombre de caractères déjà consommés dans l'enregistrement courant.

readline

Effectue la lecture des données sur l'entrée spécifiée par la méthode from(). Retourne le résultat de la lecture.

Exemple.

        use Parse::Lex;

        print STDERR "read and print one line\n";
        $lexer = Parse::Lex->new();
        while (not $lexer->eoi) {
          print $lexer->readline()
        }
reset

Vide le buffer interne à l'analyseur lexical et efface tout token déjà reconnu.

restart

Réinitialise l'automate d'analyse. La seule condition active devient la condition INITIAL.

setToken TOKEN

Force le token à TOKEN. Utile pour requalifier un token à l'intérieur de la fonction anonyme associée à ce token.

skip EXPR
skip

EXPR est une expression régulière définissant un motif inter-token (par défaut [ \t]+). skip('') permet de supprimer ce motif. skip() retourne la valeur du motif. skip() peut être utilisée comme méthode de classe.

Le changement du motif à "sauter" provoque une recompilation de l'analyseur lexical.

start EXPR

Active la condition EXPR.

state EXPR

state EXPR permet de connaître l'état de la condition représentée par EXPR.

token

Retourne l'objet correspondant au dernier token reconnu. En l'absence de token lu, retourne un token spécial dont le nom est DEFAULT.

tokenClass EXPR
tokenClass

Indique quelle est la classe des tokens à créer à partir de la liste passée en argument à la méthode new(). Sans argument retourne le nom de cette classe. Par défaut la classe est Parse::Token.

trace OUTPUT
trace

Méthode de classe qui active le mode trace. L'activation du mode trace doit avoir lieu avant la création de l'analyseur lexical. Le mode peut être ensuite désactivé par un nouvel appel de la méthode.

OUTPUT peut être un nom de fichier ou une référence à un filehandle vers laquelle la trace va être dirigée.

EXEMPLES

ctokenizer.pl - Segmentation d'un flot de données au moyen de la classe Parse::CLex.

tokenizer.pl - Segmentation d'un flot de données au moyen de la classe Parse::Lex.

every.pl - Utilisation de la méthode every().

sexp.pl - Interprète d'expressions arithmétiques préfixées.

sexpcond.pl - Interprète d'expressions arithmétiques préfixées avec utilisation des conditions.

BUGS

Parse::Lex ne fonctionne qu'avec perl 5.004. Si votre version de Perl est antérieure, utilisez la classe Parse::CLex.

Les analyseurs de la classe Parse::CLex ne permettent pas d'utiliser des expressions régulières avec ancrage.

VOIR EGALEMENT

La classe Parse::YYLex qui interface Parse::Lex avec le parseur byacc.

AUTEUR

Philippe Verdret

REMERCIEMENTS

La version 2.0 doit beaucoup aux suggestions de Vladimir Alexiev. Ocrat a largement contribué à l'amélioration de cette documentation.

REFERENCES

Friedl, J.E.F. Mastering Regular Expressions. O'Reilly & Associates 1996.

Mason, T. & Brown, D. - Lex & Yacc. O'Reilly & Associates, Inc. 1990.

FLEX - A Scanner generator (voir par exemple ftp://ftp.ee.lbl.gov/)

COPYRIGHT

Copyright (c) 1995-1998 Philippe Verdret. All rights reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 3:

Non-ASCII character seen before =encoding in 'Générateur'. Assuming CP1252