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
Le package Token
permet de définir les tokens utilisés par Parse::Lex
ou par Parse::CLex
. La méthode Lex::new()
du package Parse::Lex
crée indirectement une instance Parse::Token
par token à reconnaître. Les méthodes next()
ou isnext()
du package 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 ce package est faite indirectement par un use Parse::Lex
.
Méthodes
- action
-
Retourne la fonction anonyme définie dans l'objet
Parse::Token
. - factory LISTE
-
Créer une liste d'objets
Parse::Token
à partir d'une liste de spécifications de tokens. La liste peut également inclure des objets de la classeParse::Token
ou d'une classe qui en dérive. Peut s'utiliser comme méthode de classe ou d'instance.La méthode
factory(LISTE)
peut être utilisée pour créer un ensemble de tokens qui ne sont pas dans l'automate d'analyse. Cette méthode effectue deux opérations : 1) elle crée les objets en fonction des spécifications figurant dans LISTE (voir la méthodenew()
), 2) elle importe les objets créés 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 ); Parse::Token->factory(%keywords);
et installer ces tokens dans une table des symboles de la manière suivante :
foreach $name (keys %keywords) { $symbol{"\L$name"} = [${$name}, '']; }
${$name}
est l'objetParse::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 constitue le retour de 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 symbolique de l'objet
Parse::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
-
Crée un objet de type
Parse::Token
. Les arguments de la méthodenew()
sont dans l'ordre : un nom symbolique, une expression régulière et une fonction anonyme.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 ce dernier cas le token peut être réparti sur plusieurs enregistrements. Ce peut être par exemple une 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'objetParse::Token
,$_[1]
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'objetParse::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 objet 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 de l'objetParse::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.
GESTION DES ERREURS
Pour traiter les cas de non reconnaissance de token vous pouvez définir un token spécifique en fin de la liste des tokens composant notre analyseur lexical. Si la recherche de ce token réussie il est alors possible d'appeler une fonction dévolue au traitement des erreurs :
qw(ERROR (?s:.*)), sub {
print STDERR "ERROR: buffer content->", $_[0]->lexer->buffer, "<-\n";
die qq!can\'t analyze: "$_[1]"!;
}
Sous-classes de Parse::Token
Des sous-classes de la classe Parse::Token
sont en cours de définition. Elles permettent ou permettrons 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 que j'ai l'intention de créer :
Parse::Token::Action
: permet d'insérer des expressions Perl entre deux tokens de l'analyseur lexical.
Parse::Token::Simple
: pour définir les tokens qui ne nécessitent pas le lecture de nouvelles données.
Parse::Token::Multiline
: pour définir des tokens pouvant nécessiter la lecture de données complémentaires.
Parse::Token::Nested
: pour reconnaître des structures imbriquées, tels que des expressions parenthésées.
Parse::Token::Delimited
: pour reconnaître, par exemple, des chaînes de caractères entre guillemets.
Le nom de ces classes a valeur de proposition. Vous pouvez me faire des suggestions.
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
: position en nombre de caractères depuis le début de l'analyse$LEX_POS
: position en nombre de caractères indiquant l'avancée de l'analyse
Le constructeur de la classe accepte les attributs suivants :
Name
: le nom du tokenExpr
: 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"
;!,
);
$lexer = Parse::Lex->new(
$ACTION,
qw(LETTER [a-z]),
qw(ERROR (?s:.*)), sub {
print STDERR "ERROR buffer content:->",
$_[0]->lexer->buffer, "<-\n";
die qq!can\'t analyze: "$_[1]"!;
}
);
Parse::Token::Simple
Parse::Token::Multiline
Parse::Token::Quoted
Exemples.
---------------------------------------------------------
Début Fin Littéralisation
---------------------------------------------------------
' ' ''
" " ""
" " \
---------------------------------------------------------
Parse::Token::Delimited - Non définie
Exemples.
---------------------------------------------------------
Début Fin Contrainte
Sur le contenu
---------------------------------------------------------
/* */ Commentaire C
<!-- --> Pas de '--' Commentaire XML
<!-- --> Commentaire SGML
<? ?> Processing instruction
en SGML/XML
---------------------------------------------------------
Parse::Token::Nested - Non définie
Exemples.
----------------------------------------------------------
Début Fin Contrainte
Sur le contenu
----------------------------------------------------------
( ) Symbolic Expressions
{ } Rich Text Format Groups
----------------------------------------------------------
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 (Stefan Becker, Rashid Karimov, Larry W. Virden ...).
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