This is an old revision of the document!


TP 4 - Lexer

Microsoft Teams: TP 4

  • username: votre username de fils.curs.pub.ro (username@stud.fils.upb.ro)
  • password: votre mot de passe de fils.curs.pub.ro

Selectez channel TP 4 - Lexer et appuyez sur le boutton Join.

Les archives avec les exercices seront envoyées à l'adresse diana.ghindaoanu@stud.fils.upb.ro

Un lexer est un logiciel qui transforme un texte en jetons (tokens). On peut associer cette transformation à la division d'un paragraphe dans des mots. Ce traitement est réalisé en utilisant des expressions régulières.

Vous pouvez construire un lexer de deux façons:

  • Ecrire un programme qui utilise des expressions régulières et faire correspondre ces expressions régulières à aux jetons
  • Utilisez un générateur de lexer qui reçoit les expressions régulières et écrit le lexer pour vous

Expressions régulières

Mathematique

Character Description Exemple
* Zéro ou plusieurs fois a*, (ab)*
+ Une ou plusieurs fois a+, (ab)+
? Zéro ou une fois a?, (ab)?
^ début de string ^ab*
$ fin de string b*a$
. tout symbole .
[ ] Ensemble [abc]
\s Espace blanc a\sb
[^ ] ensemble complémentaire [^abc]
( ) groupe (abc)+
| Ou a | b, (ab) | (ba)

JavaScript

Character Description Exemple
{n} n fois a{3}
{n,m} minimum n, maximum m a{3,7}
\w alphanumérique et _ \w
\t TAB a\ta*
\n fin de ligne a\nb
\r retour chariot a\rb
a(?!b) a seulement si non suivi par b a(?!b)
a(?=b) a seulement si suivi par b a(?=b)
( ) group a(ab)a

Pour déclarer des expressions régulières, on a 2 possibilités:

// making a new RexEx object the standard way
var regex = new RegEx ("[0-9]+");
 
// making a new RegEx object using a shortcut
var regex = /[0-9]+/;

Fonctions

RegEx

  • regex.exec(str) - Recherche dans un string un sous-string qui suit l'expression régulière
  • regex.test(str) - Recherche dans une chaîne une sous-chaîne qui suit l'expression régulière et renvoie true ou false

Pour plus de fonctions, lisez la documentation RegEx complète.

String

var regex = /([0-9]+);([A-Za-z-\. ]+);([0-9]{3,4}[A-Za-z]+)/;
 
var match = regex.exec ('1;ANDRONIE S. Manuela - Bianca;1220F extra text');
 
/*
match:
[ '1;ANDRONIE S. Manuela - Bianca;1220F', // the full match
  '1', // the first group
  'ANDRONIE S. Manuela - Bianca', // the second group
  '1220F', // the third group
  index: 0, // the position
  input: '1;ANDRONIE S. Manuela - Bianca;1220F extra text' ] // the full string
*/
  • str.search(regex) - Recherche un sous-string en str qui correspond à l'expression régulière et renvoie l'index de celle-ci ou -1.

Pour en savoir plus, lisez la documentation String complète.

Exemple de création d'un lexer

Le lexer général ressemblerait à

var number = /^[0-9]+(\.?[0-9]*)/;
var whitespace = /^\s+/;
var identifier = /^[A-Za-z_][A-Za-z0-9_]*/;
 
var str = "the text you want to lex is this one";
 
var error = false;
 
var tokens = [];
 
while (str.length > 0 && error === false)
{
   // take each regular expression and try to match it
   var match = [];
   // try to match the first regular expression
   // match number
   match = number.exec (str);
   if (match.length > 0) // we matched something
   {
     // delete the matched part from the string
     str = str.substring (0, match[0].length);
     // add the token
     tokens.push ({type: 'NUMBER', value: match[0]});
     // go to the next while iteration
     continue;
   }
   // match whitespace
   match = whitespace.exec (str);
   if (match.length > 0) // we matched something
   {
     // delete the matched part from the string
     str = str.substring (0, match[0].length);
     // ignore whitespace, don;t add it to the tokens
     // go to the next while iteration
     continue;
   }
   // match idetifier
   match = identifier.exec (str);
   if (match.length > 0) // we matched something
   {
     // delete the matched part from the string
     str = str.substring (0, match[0].length);
     // add the token
     tokens.push ({type: 'IDENTIFIER', value: match[0]});
     // go to the next while iteration
     continue;
   }
}
 
console.log (tokens);

Comme vous pouvez le voir, le code est assez long pour seulement trois expressions régulières. Les langages de programmation ont un contenu plus complexe, alors c'est pourquoi nous voulons utiliser un générateur de lexer.

Jison

Jason est un générateur de parser qui comprend un générateur de lexer. Pour ce TP, nous n'utiliserons que le fichier fichier.l - la partie génératrice lexer. Pour plus de documentation, vous pouvez accéder au site web de Jison.

Installation

Nous devons d'abord installer Jison globalement

npm install -g jison-gho

Fichiers de jetons (tokens) et grammaire

Dans les fichier .l et .y, le caractère échappant peut être fait avec ”” ou \

example.l
/* .l example file */
 
 
Letter [A-Za-z]
WS     \s+
 
%%
 
{Letter}+   { print(yytext, yylineno); return 'Letter'}
 
{WS}+ {/* whitespace separates tokens */}
 
%%
 
function print(text, line) {
    console.log('token ' + text + ' line ' + line);
}
example.y
/* .y example file */
 
%%
 
start:;

Générer le lexer

Pour générer le lexer, exécutez jison en utilisant les deux fichiers (example.l et example.y)

jison example.y example.l

Cela générera un fichier JavaScript (example.js) que vous pouvez utiliser pour diviser un texte en jetons et pour parser ce texte en utilisant les jetons et la grammaire décrits dans le fichier jison.

Utilisation du lexer généré

main.js
"use strict";
 
// import the generated Parser
var Parser = require ('./example.js').Parser;
 
// use the lexer from the generated Parser
var lexer = new Parser ().lexer;
 
// add a text to the lexer
lexer.setInput ('alf text example');
 
var s = null;
 
var tokens = [];
 
// repeat while you get an EOF token
do 
{
    try
    {
        // get the next token
        s = lexer.next ();
    }
    catch (e)
    {
        // if there is an error
        // print the line number (lexer.yylineno+1)
        // print the error position (lexer.showPosition ())
        console.log ('Error line '+(lexer.yylineno+1)+'\n'+lexer.showPosition());
        process.exit (-1);
    }
    if (s && s!== lexer.EOF)
    {
        // print the token (s)
        // print the token text (lexer.yytext)
        console.log (s+' '+lexer.yytext);
        // add them to an array
        tokens.push ({type: s, value: lexer.yytext});
    }
} while (s !== lexer.EOF); 
 
console.log (tokens);

Exercices

  1. Soit le tableau suivant: (1p)
        var movies = [
                      'The Shawshank Redemption,1994,9.2',
                      'Titanic,1997,7.8',
                      'Pulp Fiction,1994,8.9',
                      'The Revenant,2015,8.0'
                    ];
     

    Pour chaque film de la liste, affichez les informations sous la forme suivante: Titre: <nom du film>, Année: <année d'apparition>, NoteIMDb: <note>. Utilisez des expressions régulières pour résoudre cet exercice.

  2. Clonez le depot git (git repository). Entrez dans TP/TP4 et utilisez les fichiers qui sont deja la pour les exercices suivantes. Générez un lexer qui reconnaît les jetons suivants: NUMBER - nombres, WORD - tout texte contenant uniquement des lettres, PUNCTUATION - signes de ponctuation (2p)
    1. Installez Jison (0.5p)
    2. Ecrivez le fichier alf.l de façon qu'il reconnaisse les jetons mentionnés ci-dessus.(1p)
    3. Générez le lexer décrit dans les fichiers alf.l et alf.y à l'aide de la commande jison. (0.5p)
  3. Utilisez le lexer de l'exercice no.2 pour le texte Bonjour! Le TP d'ALF est de 12 a 14.. (1p)
  4. Utilisez le lexer de l'exercice no.2 pour le fichier text_and_numbers.txt. Affichez chaque type de jeton (token), la ligne où le jeton est trouvé (yylineno) et le texte correspondant (yytext). (1p)
  5. Ecrivez un lexer qui reconnaît un sous-ensemble du langage PHP. Pour chaque point de cet exercice, utilisez comme exemple une chaîne quelconque correspondant au langage PHP, pour voir si votre programme peut: (3p)
    1. Reconnaître les mots-clés suivants: for, if, while, else, function, break, switch, case, default
    2. Reconnaître les noms des fonctions: ils commencent par une lettre ou _ et sont suivis de n'importe quelle lettre ou chiffre ou _.
    3. Reconnaître les nombres entiers
    4. Reconnaître les nombres à virgule flottante
    5. Reconnaître les variables: elles commencent par un $ suivi de n'importe quelle lettre ou chiffre.
    6. Reconnaître les opérateurs: ( ) , ; : + - * / = % { } [ ]
  6. Utilisez le lexer de l'exercice no.5 pour le fichier program.php. Ecrire chaque type de jeton, le texte qui lui correspond et la ligne où il a été trouvé. (1p)
  7. Ajoutez les jetons de l'exercice 6 à un tableau d'objets. Chaque objet contiendra le type de jeton, le texte et le numéro de ligne. Écrivez ce tableau dans un fichier JSON. (indice: JSON.stringify). (1p)
  8. Bonus Modifiez l'exercice 5 pour qu'il reconnaisse les chaînes de caractères (texte encapsulé entre ” ou '). (1p)

Solutions

alf/laboratoare/04.1616668242.txt.gz · Last modified: 2021/03/25 12:30 by alexandru.radovici
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0