This is an old revision of the document!
Selectez channel TP 4 - Lexer et appuyez sur le boutton Join.
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:
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) |
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]+/;
Pour plus de fonctions, lisez la documentation RegEx complète.
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 */
Pour en savoir plus, lisez la documentation String complète.
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.
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.
Nous devons d'abord installer Jison globalement
npm install -g jison-gho
/* .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); }
/* .y example file */ %% start:;
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.
"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);
var films = [ 'The Shawshank Redemption,1994,9.2', 'The Dark Knight,2008,9.0', 'Pulp Fiction,1994,8.9', 'Fight Club,1999,8.8' ];
Pour chaque film de la liste, affichez les informations sous la forme suivante: Nom: <nom du film>, Année: <année d'apparition>, Note: <note>. Utilisez des expressions régulières pour résoudre cet exercice.