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 classe Parse::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éthode new()), 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'objet Parse::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éthode new() 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'objet Parse::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'objet Parse::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'objet Parse::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 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" 
			      ;!,
			     );
$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