=head1 NAME

C<Parse::Lex> - Générateur d'analyseurs lexicaux (Alpha 1.16).

=head1 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->getstring, "<-\n";
	  } else {
	    last TOKEN;
	  }
	}

	__END__
	1+2-5
	"multiline
	string with an embedded \" in it"
	this is an invalid string with an embedded \" in it"

=head1 DESCRIPTION

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

C<Parse::Lex> ne fonctionne qu'avec perl 5.004. Si votre version est
antérieure, utilisez la sous-class C<Parse::CLex>.

Les analyseurs générés par ces deux classes exploitent des stratégies
d'analyse différentes :

=item 1. C<Parse::Lex> utilise C<pos()>, associé à "\\G" pour
effectuer l'analyse,

=item 2. C<Parse::CLex> effectue une analyse avec consommation des
tokens reconnus.

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

Les lexèmes sont des objets de la classe C<Parse::Token>, livré
avec C<Parse::Lex>. La définition d'un lexème comporte ordinairement
deux arguments : un non symbolique (comme C<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 lexème est reconnu.

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 C<new>. Le lexème 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érence 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 lexème est un objet de la classe C<Parse::Token>.

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.  En
fin de flot l'analyseur retourne un objet Token dont le nom est C<EOI>
(End Of Input).

=head2 Méthodes

=item buffer EXPR

=item 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.

=item eoi

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

=item every ANON

Évite de devoir écrire une boucle de lecture pour analyser un flot de
données.  C<ANON> est une fonction anonyme executée après la
reconnaissance de chaque lexème. 

Pour segmenter la chaîne "1+2" on peut par exemple é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]->getstring, "\n";
	});

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

=item from EXPR

C<from> permet d'indiquer la source des données à analyser.
L'argument de cette méthode peut être une référence à un filehandle ou
une liste de chaînes de caractères. Exemples :

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

=item flush

Si la conservation des chaînes consommées est activée, C<flush>
retourne et vide le buffer contenant les chaînes de caractères
reconnues jusqu'ici.

=item hold EXPR

=item hold

Active/desactive la conservation des chaînes consommées.  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 C<flush>
qui a également pour effet de vider le buffer. 

=item less EXPR

La valeur de EXPR est placée au début du flot de données.

=item next

Provoque la recherche du prochain lexème. Retourne l'objet Token
reconnu.  Retourne l'objet C<Token::EOI> en fin de données.

=item new

Crée et retourne un nouvel analyseur lexical. L'argument de la méthode
est une liste de triplets comportant : le nom symbolique du lexème,
l'expression régulière nécessaire à sa reconnaissance et
éventuellement une fonction anonyme exécutée lors de la reconnaissance
du lexème.  Pour chaque triplet, un objet de type
C<Parse::Token> est créé.

L'analyseur lexical construit par C<new> cherche tour à tour à apparier
chaque expression régulière avec le début du flot de données à
analyser. L'ordre examen des expressions régulières est donné par
l'ordre dans lequel elles sont passées en argument à la méthode
C<new>.

C<Parse::Lex> peut reconnaître des lexèmes disposés sur plusieurs
enregistrements. Si le motif du début est trouvé, l'analyseur va en
chercher la fin, et si besoin est, lire de nouveaux
enregistrements. Attention, il n'y a pas de rebroussement en cas
d'échec.


=item newset

Peut être utilisé pour créer un ensemble de lexèmes qui ne sont pas
dans l'automate d'analyse. On pourra pas exemple écrire :

	%keywords = 
	  qw (
	      PROC  undef
	      FUNC  undef
	      RETURN undef
	      IF    undef
	      ELSE  undef
	      WHILE undef
	      PRINT undef
	      READ  undef
	     );
	$lexer->newset(%keywords);

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

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

C<${$name}> est l'objet 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->tokenis((not defined $type) ? $VAR : $type);
	   $_[1];
	 }

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

=item offset

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

=item pos EXPR

=item pos

C<pos EXPR> fixe la position de début du prochain token à reconnaître
dans l'enregistrement courant. C<pos> Retourne le nombre de caractères
déjà consommé dans l'enregistrement courant.

=item readline

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

=item recordno

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

=item reset

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

=item skip EXPR

=item skip

C<EXPR> est une expression régulière définissant le séparateur de
lexème (par défaut C<[ \t]+>). Retourne ce séparateur si C<EXPR> est
omis. Peut être utilisée comme méthode de classe.

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

=item token

Retourne l'objet correspondant au dernier lexème reconnu. En l'absence
de token lu, retourne un token spécial dont le nom est C<default
token.

=item tokenis TOKEN

Force le lexème à C<TOKEN>. Utile pour requalifier un lexème à
l'intérieur de la fonction anonyme associée à ce lexème.

=item trace OUTPUT

=item 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.

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

=head1 EXEMPLES

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

every.pl - Utilisation de la méthode C<every>.

=head1 BUGS

C<Parse::Lex> ne fonctionne qu'avec perl 5.004. Si votre version est
antérieure, utilisez la sous-class C<Parse::CLex>.

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

=head1 AUTEUR

Philippe Verdret

=head1 AVERTISSEMENT

Je considère que la présente version des classes Token.pm/Lex.pm est
expérimentale. Ces classes peuvent évoluer de façon notable, en
particulier en fonction des remarques et des suggestions que vous
voudrez bien m'envoyer.

=head1 REFERENCES

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

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

=head1 COPYRIGHT

Copyright (c) 1995-1997 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.

