The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Parse::Token - Définition des tokens utilisés par Parse::Lex

SYNOPSIS

        require 5.005;

        use Parse::Lex;
        @token = qw(
            ADDOP    [-+]
            INTEGER  [1-9][0-9]*
           );

        $lexer = Parse::Lex->new(@token);
        $lexer->from(\*DATA);

        $content = $INTEGER->next;
        if ($INTEGER->status) {
          print "$content\n";
        }
        $content = $ADDOP->next;
        if ($ADDOP->status) {
          print "$content\n";
        }
        if ($INTEGER->isnext(\$content)) {
          print "$content\n";
        }
        __END__
        1+2

DESCRIPTION

La classe Parse::Token et ses dérivées permettent de définir les tokens utilisés par Parse::Lex ou Parse::LexEvent.

La création des tokens peut se faire au moyen des méthodes new() ou factory(). La méthode Lex::new() du package Parse::Lex crée indirectement des instances des tokens à reconnaître.

Les méthodes next() ou isnext() du package Parse::Token permettent d'interfacer l'analyseur lexical avec un analyseur syntaxique de type récursif descendant. Pour un interfaçage avec byacc voir le package Parse::YYLex.

L'inclusion de Parse::Token se fait indirectement par un use Parse::Lex ou use Parse::LexEvent.

Méthodes

action

Retourne la fonction anonyme définie dans l'objet Parse::Token.

factory LIST
factory ARRAY_REF

La méthode factory(LIST) crée et retourne une liste de tokens à partir d'une liste de spécifications incluant par token : un nom, une expression régulière et éventuellement une fonction anonyme. La liste peut inclure des objets de la classe Parse::Token ou d'une classe qui en dérive.

factory(ARRAY_REF) permet de créer des tokens à partir de spécifications de type attribut-valeur :

        Parse::Token->factory([Type => 'Simple', 
                               Name => 'EXAMPLE', 
                               Regex => '.+']);

Type indique le type de chaque token à créer (le préfixe de package n'est pas indiqué).

factory() crée une série de tokens mais n'importe pas ces tokens dans le package d'appel.

On pourra pas exemple écrire :

        %keywords = 
          qw (
              PROC  undef
              FUNC  undef
              RETURN undef
              IF    undef
              ELSE  undef
              WHILE undef
              PRINT undef
              READ  undef
             );
        @tokens = Parse::Token->factory(%keywords);

et installer ces tokens dans une table des symboles de la manière suivante :

        foreach $name (keys %keywords) {
          ${$name} = pop @tokens;
          $symbol{"\L$name"} = [${$name}, ''];
        }

${$name} est l'instance token.

Lors de la phase d'analyse lexicale on pourra utiliser les tokens de la manière suivante :

        qw(IDENT [a-zA-Z][a-zA-Z0-9_]*),  sub {               
           $symbol{$_[1]} = [] unless defined $symbol{$_[1]};
           my $type = $symbol{$_[1]}[0];
           $lexer->setToken((not defined $type) ? $VAR : $type);
           $_[1];  # THE TOKEN TEXT
         }

Ce qui permet d'indiquer que tout symbole dont le type est inconnu est une variable.

Dans cet exemple nous avons utilisé $_[1] qui correspond au texte reconnu par l'expression régulière. Ce texte associé au token doit être retourné par la fonction anonyme.

get EXPR

Permet d'obtenir la valeur de l'attribut résultant de l'évaluation d'EXPR. Il est également possible d'utiliser le nom de l'attribut comme nom de méthode.

getText

Retourne la chaîne de caractères reconnue au moyen de l'objet Parse::Token.

Synonyme de la méthode text().

isnext EXPR
isnext

Retourne le statut du token. La chaîne consommée est disponible dans EXPR s'il s'agit d'une référence à un scalaire.

name

Retourne le nom du token.

next

Active la recherche du token défini par l'expression régulière contenue dans l'objet. Si ce token est reconnu sur le flot de caractère à analyser alors next() retourne la chaîne trouvée et met le statut de l'objet à vrai.

new SYMBOL_NAME, REGEXP, SUB
new SYMBOL_NAME, REGEXP

Crée un objet de type Parse::Token::Simple ou Parse::Token::Segmented. Les arguments de la méthode new() sont dans l'ordre : un nom symbolique, une expression régulière et éventuellement une fonction anonyme. Les sous-classes de Parse::Token permettent une spécification des tokens au moyen d'une liste d'attribut-valeurs.

REGEXP est soit une expression régulière simple, soit une référence à un tableau contenant de une à trois expressions régulières. Dans le permier cas l'instance appartient à la classe Parse::Token::Simple Dans le second cas l'instance appartient à la classe Parse::Token::Segmented. Les tokens de ce type permettent de reconnaître des structures de type chaîne de caractères délimitée par des guillemets, des commentaires d'un programme C, etc. Les expressions régulières sont utilisées pour reconnaître :

1. le début du token,

2. le "corps" du token, si cette seconde expression est absente Parse::Lex utilise (?:.*?),

3. la fin du token, si cette dernière expression est absente on utilise la première. La fin du token ne peut être à cheval sur plusieurs enregistrements.

Exemple.

          qw(STRING), [qw(" (?:[^"\\\\]+|\\\\(?:.|\n))* ")],

Les expressions régulières peuvent reconnaître des chaînes multilignes délimitées par des guillemets, sachant que le contre-oblique est utilisé pour littéraliser les guillemets qui apparaissent au sein de la chaîne. Remarquez le quadruplement du contre-oblique.

Voici une variante de l'exemple précédent qui utilise l'option s pour inclure la nouvelle-ligne dans les caractères reconnus par "." :

          qw(STRING), [qw(" (?s:[^"\\\\]+|\\\\.)* ")],

(Remarques. Il est possible d'écrire des expressions régulières plus performantes en terme de temps d'exécution, mais ce n'est pas notre objectif ici, voir Mastering Regular Expressions.)

La fonction anonyme est exécutée au moment ou le token est reconnu par l'analyseur lexical. Cette fonction possède deux arguments : $_[0] contient l'instance de token, $_[1] contient 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'instance token.

Dans la fonction anonyme vous pouvez utiliser les variables positionnelles $1, $2, ... qui correspondent aux parenthèses placées dans l'expression régulière.

regexp

Retourne l'expression régulière définie dans l'objet Parse::Token.

set LISTE

Permet de décorer un token au moyen d'une liste d'attribut-valeurs.

Un nom d'attribut peut être utilisé comme nom de méthode.

setText EXPR

La valeur de EXPR définit la chaîne de caractères associée au token.

Synonyme de la méthode text(EXPR).

status EXPR
status

Indique si la dernière recherche du token a réussie ou échouée. status EXPR permet de forcer le statut à la valeur dénotée par EXPR.

text EXPR
text

text() Retourne la chaîne de caractères reconnue au moyen du token. La valeur de EXPR permet de définir la chaîne de caractères associée au token.

trace OUTPUT
trace

Méthode de classe qui active/désactive une trace de l'analyse lexicale.

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

Sous-classes de Parse::Token

Des sous-classes de la classe Parse::Token sont en cours de définition. Elles permettent de reconnaître des structures particulières comme, par exemple, les chaînes de caractères entre guillemets, les commentaires C, etc. Voici les sous-classes sur lesquelles je travaille actuellement :

Parse::Token::Action : permet d'insérer des expressions Perl entre deux tokens de l'analyseur lexical.

Parse::Token::Simple : les tokens de cette classe sont définis au moyen d'une seule expression régulière.

Parse::Token::Segmented : les tokens de cette classe sont définis au moyen de trois expressions régulières. La lecture de nouvelles données est automatique.

Parse::Token::Delimited : permet de reconnaître, par exemple, des commentaires C.

Parse::Token::Quoted : permet de reconnaître, par exemple, des chaînes de caractères entre guillemets.

Parse::Token::Nested : permet de reconnaître des structures imbriquées, telles que les expressions parenthésées. NON DéFINIE.

La création de ces classes est récente et comporte sans aucun doute des bugs.

Parse::Token::Action

Les tokens de la classe Parse::Token::Action permettent d'insérer des expressions Perl quelconque au sein d'un analyseur lexical. Une expression peut être utilisée par exemple pour imprimer des variables internes à l'analyseur :

  • $LEX_BUFFER : contenu du buffer à analyser

  • $LEX_LENGTH : longueur de la chaîne de caractères en cours d'analyse

  • $LEX_RECORD : numéro de l'enregistrement en cours d'analyse

  • $LEX_OFFSET : nombre de caractère déjà consommés depuis le début de l'analyse

  • $LEX_POS : position atteinte par l'analyse en nombre de caractères depuis le début du buffer.

Le constructeur de la classe accepte les attributs suivants :

  • Name : le nom du token

  • Expr : une expression Perl

Exemple :

        $ACTION = new Parse::Token::Action(
                                      Name => 'ACTION',
                                      Expr => q!print "LEX_POS: $LEX_POS\n" .
                                      "LEX_BUFFER: $LEX_BUFFER\n" .
                                      "LEX_LENGTH: $LEX_LENGTH\n" .
                                      "LEX_RECORD: $LEX_RECORD\n" .
                                      "LEX_OFFSET: $LEX_OFFSET\n" 
                                      ;!,
                                     );

Parse::Token::Simple

Le constructeur de la classe accepte les attributs suivants :

  • Handler : la valeur indique un nom fonction à appeler lors d'une analyse conduite par un analyseur de la classe Parse::LexEvent.

  • Name : la valeur associée est le nom du token.

  • Regex : La valeur associée est une expression régulière correspondant au motif à reconnaître.

  • ReadMore : si la valeur associée est 1, la reconnaissance du token se poursuit après la lecture d'un nouvel enregistrement. Les chaînes reconnues sont concaténées. Cet attribut n'a d'effet que lors de l'analyse d'un flot de caractères.

  • Sub : la valeur associée doit être une fonction anonyme à exécuter à l'issue de la reconnaissance du token. Cette fonction n'est utilisée qu'avec les analyseurs de la classe Parse::Lex ou Parse::CLex.

Exemple. new Parse::Token::Simple(Name => 'remainder', Regex => '[^/\'\"]+', ReadMore => 1);

Parse::Token::Segmented

La définition de ces tokens comporte trois expressions régulières. Lors de l'analyse d'un flot de données, de nouvelles données sont lues tant que la fin du token n'est pas atteinte.

Le constructeur de la classe accepte les attributs suivants :

  • Handler : la valeur indique un nom fonction à appeler lors d'une analyse conduite par un analyseur de la classe Parse::LexEvent.

  • Name : la valeur associée est le nom du token.

  • Regex : La valeur associée doit être une référence à un tableau qui contient trois expressions régulières.

  • Sub : la valeur associée doit être une fonction anonyme à exécuter à l'issue de la reconnaissance du token. Cette fonction n'est utilisée avec les analyseurs de la classe Parse::Lex ou Parse::CLex.

Parse::Token::Quoted

Parse::Token::Quoted est une sous-classe de Parse::Token::Segmented. Elle permet de reconnaître des chaînes de caractères entre guillemets ou apostrophes.

Exemples.

      ---------------------------------------------------------
        Début   Fin     Littéralisation
      ---------------------------------------------------------
        '       '       ''              
        "       "       ""              
        "       "       \               
      ---------------------------------------------------------

Le constructeur de la classe accepte les attributs suivants :

  • End : La valeur associée est une expression régulière permettant de reconnaître la fin du token.

  • Escape : La valeur associée indique le caractère utilisé pour littéralisater le délimiteur. Par défaut on considère qu'un doublement du caractère de fin littéralise ce caractère.

  • Handler : la valeur indique un nom fonction à appeler lors d'une analyse conduite par un analyseur de la classe Parse::LexEvent.

  • Name : la valeur associée est le nom du token.

  • Start : La valeur associée est une expression régulière permettant de reconnaître le début du token.

  • Sub : la valeur associée doit être une fonction anonyme à exécuter à l'issue de la reconnaissance du token. Cette fonction n'est utilisée avec les analyseurs de la classe Parse::Lex ou Parse::CLex.

Exemple. new Parse::Token::Quoted(Name => 'squotes', Handler => 'string', Escape => '\\', Quote => qq!\'!, );

Parse::Token::Delimited

Parse::Token::Delimited est une sous-classe de Parse::Token::Segmented. Elle permet, par exemple, de reconnaître des commentaires C.

Exemples.

      ---------------------------------------------------------
        Début   Fin     Contrainte
                        Sur le contenu  
      ---------------------------------------------------------
        /*      */                      Commentaire C
        <!--    -->     Pas de '--'     Commentaire XML
        <!--    -->                     Commentaire SGML
        <?  ?>                          Processing instruction
                                        en SGML/XML
      ---------------------------------------------------------

Le constructeur de la classe accepte les attributs suivants :

  • End : La valeur associée est une expression régulière permettant de reconnaître la fin du token.

  • Handler : la valeur indique un nom fonction à appeler lors d'une analyse conduite par un analyseur de la classe Parse::LexEvent.

  • Name : la valeur associée est le nom du token.

  • Start : La valeur associée est une expression régulière permettant de reconnaître le début du token.

  • Sub : la valeur associée doit être une fonction anonyme à exécuter à l'issue de la reconnaissance du token. Cette fonction n'est utilisée avec les analyseurs de la classe Parse::Lex ou Parse::CLex.

Exemple. new Parse::Token::Delimited(Name => 'comment', Start => '/[*]', End => '[*]/' );

Parse::Token::Nested - Non définie

Exemples.

      ----------------------------------------------------------
        Début   Fin     Contrainte
                        Sur le contenu  
      ----------------------------------------------------------
        (       )                       Symbolic Expressions
        {       }                       Rich Text Format Groups
      ----------------------------------------------------------

BUGS

L'implémentation des sous-classes de tokens n'est pas complète pour les analyseurs de la classe Parse::CLex. Je n'ai d'ailleurs pas trop envi de le faire, sachant qu'une implémentation pour les classes Parse::Lex et Parse::LexEvent ne paraît tout à fait suffisante.

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. Merci également aux nombreuses personnes qui m'ont fait des remarques et parfois envoyés des corrections de bugs.

REFERENCES

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

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

COPYRIGHT

Copyright (c) 1995-1999 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 'Définition'. Assuming CP1252