<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Jawher's characters depot</title><link href="https://jawher.me/" rel="alternate"></link><link href="https://jawher.me/atom-fr.xml" rel="self"></link><id>https://jawher.me/</id><updated>2012-11-10T00:00:00+01:00</updated><entry><title>Une génération de "select * =&gt; tableau"</title><link href="https://jawher.me/2012/11/10/generation-select-tableau/" rel="alternate"></link><updated>2012-11-10T00:00:00+01:00</updated><author><name>Jawher Moussa</name></author><id>tag:jawher.me,2012-11-10:2012/11/10/generation-select-tableau/</id><summary type="html">&lt;p&gt;Nous sommes des développeurs.
Du moins, si vous lisez ce blog, vous l'êtes très probablement.
On est des millions dans le monde.
Certains d'entre nous sommes passionnés.
On lit des blogs, on fait de la veille techno, on télécharge et teste les nouveaux frameworks dès leur alpha.
On peut s'appeler des consultants, développeurs artisans, développeurs passionnés, des &lt;em&gt;ninjas&lt;/em&gt;, des &lt;em&gt;rockstars&lt;/em&gt;, tout ce que vous voulez.
La majorité du temps, ce qu'on fait à longueur de journée se résume à:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;select * from uneTable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;dessiner un tableau qui liste les résultats, avec des liens/boutons pour voir les détails, modifier ou supprimer ces entrées&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Après, en pratique, on gère effectivement beaucoup plus de choses, comme par exemple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Séparer ça en 3 &lt;em&gt;(ou plus)&lt;/em&gt; couches: isoler le code d'accès à la base de données de la couche métier de la partie web&lt;/li&gt;
&lt;li&gt;Ajouter peut être quelques façades. Sait-t-on jamais !&lt;/li&gt;
&lt;li&gt;Se battre avec le &lt;em&gt;DBA&lt;/em&gt; pour qu'il ajoute une colonne à telle table&lt;/li&gt;
&lt;li&gt;Décider si on va utiliser un &lt;em&gt;ORM&lt;/em&gt; (&lt;em&gt;Hibernate&lt;/em&gt;) ou pas&lt;/li&gt;
&lt;li&gt;Faire le choix entre &lt;em&gt;Spring&lt;/em&gt; et &lt;em&gt;JavaEE&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Quelques uns iront même jusqu'à s'inquiéter de comment leur appli de gestion va &lt;em&gt;scaler&lt;/em&gt;. L'appli en question sera utilisée par 10 utilisateurs qui sont habitués à des temps de réponse de 50 secondes. Soit, mais que se passera t'il le jour où l'o aura à gérer 1000 utilisateurs ? Ne devrait-t-on pas héberger notre appli sur le &lt;em&gt;cloud&lt;/em&gt; et passer au &lt;em&gt;nosql&lt;/em&gt;, avec un zeste de &lt;em&gt;realtime&lt;/em&gt; ?&lt;/li&gt;
&lt;li&gt;Le tableau qui affiche les résultats du &lt;em&gt;select&lt;/em&gt; devrait être triable sur n'importe quelle colonne, filtrable, paginé, et joli.&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On fait que ça.
Oui, des fois, il y'a de la logique métier à implémenter.
Quelques &lt;code&gt;if&lt;/code&gt; par si et par là.
Ou des fois, c'est de l'&lt;strong&gt;illogique&lt;/strong&gt; métier qu'il faut gérer.
Mais on reste toujours dans le &lt;em&gt;workflow&lt;/em&gt; &lt;code&gt;select * from table =&amp;gt; afficher dans un tableau&lt;/code&gt;.
Bienvenue dans le monde des applications de gestion.&lt;/p&gt;
&lt;p&gt;C'est une conséquence inévitable du succès de l'informatique.
C'est devenu un outil indispensable dans tous les domaines.
Du bancaire à la GED en passant par la gestion de stock, tout le monde veut automatiser et informatiser leur &lt;em&gt;process&lt;/em&gt;.
Je m'en plains pas, c'est ce qui fait qu'il y ait si peu de chômeurs parmi les développeurs.&lt;/p&gt;
&lt;p&gt;Mais je n'en suis pas complètement satisfait.
Je dis pas complètement parce que je prend un eu de plaisir à bien implémenter une &lt;em&gt;feature&lt;/em&gt; qui je sais va simplifier la vie aux utilisateurs de l'application.
Mais ça ne me fait plus rêver.&lt;/p&gt;
&lt;p&gt;Je ne suis pas le seul à ressentir ça.
Mais ce que je constate c'est que la majorité de ceux qui veulent s'en sortir vont vers des &lt;em&gt;startups&lt;/em&gt; pour travailler sur des variantes d'un réseau social.
Des développeurs, qui pour la majorité sont très doués, qui passent des milliers d'heures à créer des produits mort-nés qui se résument à une zone de texte qui permet de publier un &lt;em&gt;statut/tweet/update/post&lt;/em&gt; et que les &lt;em&gt;amis/followers&lt;/em&gt; peuvent &lt;em&gt;liker/retweeter/reblogger/favoriser&lt;/em&gt;.
Quel gâchis !&lt;/p&gt;
&lt;p&gt;D'un autre côté, il y'a des développeurs qui travaillent sur des sujets, qui pour moi, sont beaucoup plus intéressants et passionnants:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Les gens qui créent et optimisent les outils qu'on utilise tous les jours: l'os, la base de données, l'éditeur/IDE, etc. Récemment, le toplink sur &lt;a href="http://news.ycombinator.com/item?id=4763879"&gt;HackerNews&lt;/a&gt; parle de &lt;a href="http://www.rethinkdb.com/"&gt;RethinkDb&lt;/a&gt;: une bande de passionnés&lt;sup id="fnref:1"&gt;&lt;a class="footnote-ref" href="#fn:1" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt; qui travaillent pendant des années pour résoudre des problèmes très durs, comme comment ne pas bloquer la base pendant que l'on exécute du &lt;em&gt;map/reduce&lt;/em&gt; là-dessus par exemple.&lt;br /&gt;
  Ou même les gens qui bossent sur les systèmes moins &lt;em&gt;sexy&lt;/em&gt;, comme l'optimisateur de requêtes de Postgres ou Oracle par exemple.&lt;/li&gt;
&lt;li&gt;Les gens qui créent les langages qu'on utilise pour développer nos applis.
  Surtout de nos jours où il ne se passe pas une semaine sans que l'on annonce la sortie d'un nouveau langage: &lt;a href="https://mail.mozilla.org/pipermail/rust-dev/2012-October/002489.html"&gt;Rust&lt;/a&gt;, Go, ou même les petits langages jouets dont parlent les gens sur des sites spécialisés comme &lt;a href="http://lambda-the-ultimate.org/"&gt;λ the ultimate&lt;/a&gt;
  Je suis jaloux de ces gens qui passent leurs journées à réfléchir sur la syntaxe à choisir, la sémantique derrière, l'interaction entre les différents &lt;em&gt;constructs&lt;/em&gt; du langage, puis aux détails d'implémentation: comment inférer et vérifier des types, générer du code optimisé, implémenter le &lt;em&gt;garbage collector&lt;/em&gt;, etc.&lt;/li&gt;
&lt;li&gt;Les gens qui travaillent sur l'intelligence artificielle par exemple, ou le &lt;em&gt;machine-learning&lt;/em&gt; avec les différentes applications tel que l'analyse et compréhension du langage naturel (&lt;em&gt;Siri&lt;/em&gt; et Google), &lt;a href="http://www.youtube.com/watch?feature=player_embedded&amp;amp;v=i3ernrkZ91E"&gt;collaboration entre plusieurs robots &lt;em&gt;(vid)&lt;/em&gt;&lt;/a&gt;, etc.&lt;/li&gt;
&lt;li&gt;Les gens qui ont écrit &lt;a href="http://compass.informatik.rwth-aachen.de/ws-slides/havelund.pdf"&gt;le soft &lt;em&gt;(pdf)&lt;/em&gt;&lt;/a&gt; qui pilote le &lt;em&gt;rover Curiosity&lt;/em&gt;.
  Ou ceux qui ont &lt;a href="http://www.jpl.nasa.gov/news/news.php?release=2010-151"&gt;diagnostiqué et corrigé un problème software sur la sonde voyager&lt;/a&gt; alors qu'elle était à plus de 13 milliards de Km de la terre.&lt;/li&gt;
&lt;li&gt;Les gens qui créent les algorithmes de compression (jpeg, mp3, lzw, etc.), les moteurs de recherche capable de retourner le bon résultat parmi des milliards de pages indexées en quelques millisecondes, les softs de pilotage automatique d'avions ou les voitures sans conducteur, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Je suis jaloux.
J'aimerais travailler sur des sujets qui auront un impact positif sur l'humanité.
Mais ce n'est pas le cas.
J'arrive à survivre en m'intéressant à l'aspect technique du métier.&lt;/p&gt;
&lt;p&gt;Dans mon temps libre, j'essaie de travailler sur &lt;a href="https://github.com/jawher"&gt;des projets&lt;/a&gt; qui n'ont rien à voir avec les applications de gestion.
Je travaille surtout sur des projets de types "socle technique" (bibliothèque, framework).
Je passe aussi beaucoup de temps à lire d'obscurs papiers de recherche sur la théorie de compilation et l'inférence de types et à travailler sur mon &lt;a href="http://jawher.me/2012/06/04/creation-langage-programmation-litil-1/"&gt;&lt;em&gt;toy-language&lt;/em&gt;&lt;/a&gt;.
J'essaie aussi de ne pas me cantonner au sphère Java en allant souvent sur des sites comme HackerNews et Reddit et à me forcer à élargir mes lectures pour inclure d'autres langages/technos comme Python, ML, Haskell, Clojure, Ruby, Erlang, etc.&lt;/p&gt;
&lt;p&gt;Mais pendant mes journées, je continue à faire du &lt;code&gt;select * =&amp;gt; tableau&lt;/code&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;C'est cette couverture du &lt;em&gt;MIT Technology Review&lt;/em&gt; du mois de Novembre qui a motivé ce post:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://images.digital.technologyreview.com/rvimageserver/Technology%20Review/Technology%20Review/November%20December%202012/page0000001.jpg" alt="Damn" width="500" /&gt;&lt;/p&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Dont Salava Akhmechet, qui tient un &lt;a href="http://www.defmacro.org/"&gt;excellent blog&lt;/a&gt; que je vous conseillerais de prendre le temps de lire.&amp;#160;&lt;a class="footnote-backref" href="#fnref:1" rev="footnote" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</summary></entry><entry><title>Le conte de Litil - Chapitre 2, Le dépeceur du texte, aka Lexer</title><link href="https://jawher.me/2012/06/27/creation-langage-programmation-litil-2-lexer/" rel="alternate"></link><updated>2012-06-27T00:00:00+02:00</updated><author><name>Jawher Moussa</name></author><id>tag:jawher.me,2012-06-27:2012/06/27/creation-langage-programmation-litil-2-lexer/</id><summary type="html">&lt;p&gt;Dans ce deuxième post du conte de Litil, je vais parler de la phase de lexing. C'est généralement la première étape dans la construction d'un compilateur (ou évaluateur) d'un langage donné. Cette phase sert à transformer le texte du code source (séquence de caractères) vers une séquence de &lt;code&gt;tokens&lt;/code&gt;, qui seront consommés par le parseur à l'étape suivante.&lt;/p&gt;
&lt;p&gt;Les règles suivant lesquelles le texte est découpé en tokens varient d'un langage à un autre, mais en général (avec les langages conventionnels de la famille Algol par exemple), on peut définir les familles de tokens suivants:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;symboles: les opérateurs (&lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;, etc.), les signes de ponctuation (&lt;code&gt;,&lt;/code&gt;, &lt;code&gt;;&lt;/code&gt;, &lt;code&gt;(&lt;/code&gt;, &lt;code&gt;[&lt;/code&gt;, etc.).&lt;/li&gt;
&lt;li&gt;les littéraux: nombres (&lt;code&gt;42&lt;/code&gt;, &lt;code&gt;3.14&lt;/code&gt;, etc.), chaînes de caractères (&lt;code&gt;"kthxbye"&lt;/code&gt;), booléens (&lt;code&gt;true&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;les mots clés: &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;les identifiants: cela dépend du langage, mais généralement un identifiant commence par une lettre ou un tiret-bas (&lt;code&gt;_&lt;/code&gt;), puis optionnellement une séquence de lettres, chiffres et quelques autres symboles.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On peut donc voir un token comme un couple &lt;strong&gt;type&lt;/strong&gt; (symbole, mot clé, littéral, etc.) et &lt;strong&gt;valeur&lt;/strong&gt; (le contenu textuel de ce token). Optionnellement, on peut enrichir un token pour qu'il contienne aussi le numéro de la ligne et de la colonne où il apparait dans le texte source, ce qui peut s'avérer utile pour signaler l'emplacement d'une erreur.&lt;/p&gt;
&lt;p&gt;Enfin, le lexer se charge de cacher ou ignorer le contenu inutile dans le fichier source, comme les blancs, retours à la ligne et autres.&lt;/p&gt;
&lt;h2 id="gestion-des-blancs"&gt;Gestion des blancs&lt;/h2&gt;
&lt;p&gt;Dans le langage que nous allons implémenter, et à l'encontre de la majorité des autres langages, les blancs sont importants car il servent à démarquer le début et la fin des blocs comme dans Python (et Haskell) par exemple. Le début d'un bloc est signalé par une augmentation du niveau de l'indentation tandis que sa fin est marquée par une dé-indentation.&lt;/p&gt;
&lt;p&gt;Exemple:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
  &lt;span class="n"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Ohai&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;L'équivalent Java serait:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Ohai&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Bien que les corps des branches &lt;code&gt;then&lt;/code&gt; et &lt;code&gt;else&lt;/code&gt; du code java sont bien indentés, cette indentation est optionnelle et est carrément ignorée par le lexer. Ce sont les accolades ouvrantes et fermantes qui démarquent le début et la fin d'un bloc. On aurait pu obtenir le même résultat avec:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Ohai&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;ou encore:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;print&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Ohai&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;();}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;La lisibilité du code en souffre, mais cela ne change rien du point de vue du compilateur. Ce n'est pas le cas avec Litil, où comme dit plus haut, l'indentation du code n'est pas optionnelle car elle sert à définir sa structure. De plus, là où dans Java on utilisait le &lt;code&gt;;&lt;/code&gt; pour séparer les instructions d'un même bloc, Litil utilise plutôt les retours à la ligne. Les &lt;code&gt;;&lt;/code&gt; ne sont pas optionnels, ils ne sont pas reconnues. Mon but était de s'inspirer des langages comme Haskell et Python pour créer une syntaxe épurée avec un minimum de bruit et de décorum autour du code utile. Je reveniendrai la dessus dans le&lt;em&gt;(s)&lt;/em&gt; post&lt;em&gt;(s)&lt;/em&gt; à venir quand je vais détailler la syntaxe de Litil, mais pour vous donner quelques exemples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pas d'accolades pour délimiter les blocs&lt;/li&gt;
&lt;li&gt;Pas de &lt;code&gt;;&lt;/code&gt; pour séparer les instructions&lt;/li&gt;
&lt;li&gt;Pas de parenthèse pour les arguments d'une fonction: &lt;code&gt;sin 5&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Pas de parenthèse pour les conditions des &lt;code&gt;if&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Donc, pour résumer, le lexer que nous allons développer ne va pas complètement ignorer les blancs. Plus précisément, le lexer devra produire des tokens pour signaler les retours à la ligne (pour indiquer la fin d'une instruction) et les espaces (ou leur absence) en début de lignes (pour indiquer le début ou la fin d'un bloc).&lt;/p&gt;
&lt;h2 id="implementation"&gt;Implémentation&lt;/h2&gt;
&lt;p&gt;Pour commencer, voici la définition d'un Token:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Token&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;NEWLINE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;INDENT&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DEINDENT&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NAME&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NUM&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;STRING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CHAR&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SYM&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BOOL&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;KEYWORD&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EOF&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;col&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Un token est composé de:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;type&lt;/code&gt;: le type du token:&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NEWLINE&lt;/code&gt;: pour indiquer un retour à la ligne&lt;/li&gt;
&lt;li&gt;&lt;code&gt;INDENT&lt;/code&gt;: pour indiquer que le niveau d'indentation a augmenté par rapport à la ligne précédente, et donc qu'on entre dans un nouveau bloc&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DEINDENT&lt;/code&gt;: pour indiquer que le niveau d'indentation a diminué par rapport à a ligne précédente, et donc qu'on sort d'un bloc&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NAME&lt;/code&gt;: une clé pour indiquer qu'il s'agit d'un identifiant&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NUM&lt;/code&gt;, &lt;code&gt;STRING&lt;/code&gt;, &lt;code&gt;CHAR&lt;/code&gt;, &lt;code&gt;BOOL&lt;/code&gt;: une clé pour indiquer qu'il s'agit d'un littéral&lt;/li&gt;
&lt;li&gt;&lt;code&gt;KEYWORD&lt;/code&gt;: une clé pour indiquer qu'il s'agit d'un mot clé&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EOF&lt;/code&gt;: produit quand on a atteint la fin du texte source&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;text&lt;/code&gt;: une chaîne qui contient le texte correspondant à ce token&lt;/li&gt;
&lt;li&gt;&lt;code&gt;row&lt;/code&gt; et &lt;code&gt;col&lt;/code&gt;: indique la position du token dans le texte source&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Voici maintenant l'interface qui décrit le lexer:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Lexer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Token&lt;/span&gt; &lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="n"&gt;LexingException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getCurrentLine&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Cette interface définit les 2 méthodes suivantes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pop&lt;/code&gt;: retourne le token suivant&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getCurrentLine&lt;/code&gt;: retourne la ligne courante dans le texte source&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Notez l'absence d'une méthode qui indique la présence ou pas d'un token suivant. En effet, quand le lexer atteint la fin du fichier, il se place en un mode où tous les appels à &lt;code&gt;pop&lt;/code&gt; retournent un token de type &lt;code&gt;EOF&lt;/code&gt;. J'ai donc estimé inutile d'alourdir l'interface pour ajouter une méthode à la &lt;code&gt;hasNext&lt;/code&gt; d'un itérateur par exemple.&lt;/p&gt;
&lt;p&gt;Notez aussi que si j'ai défini une interface pour le lexer, c'est parce qu'il y aurait plusieurs implémentations que nous allons voir par la suite.&lt;/p&gt;
&lt;h3 id="comment-ca-fonctionne"&gt;Comment ça fonctionne&lt;/h3&gt;
&lt;p&gt;Voici une présentation rapide du fonctionnement de l'implémentation de base du lexer (&lt;a href="https://github.com/jawher/litil/blob/master/src/main/java/litil/lexer/BaseLexer.java"&gt;Code source de &lt;code&gt;BaseLexer.java&lt;/code&gt; (sur Github) pour ceux qui voudront suivre avec le code sous les yeux&lt;/a&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Le constructeur du lexer prend en paramètre un &lt;code&gt;java.io.Reader&lt;/code&gt; qui pointe vers le texte source&lt;/li&gt;
&lt;li&gt;Le lexer définit un champ &lt;code&gt;currentLine&lt;/code&gt; qui contient la ligne courante et 2 autres champs &lt;code&gt;row&lt;/code&gt; et &lt;code&gt;col&lt;/code&gt; pour la position&lt;/li&gt;
&lt;li&gt;Quand &lt;code&gt;pop&lt;/code&gt; est appelée, on teste si la ligne courante est renseignée ou pas. Si elle ne l'est pas, on essaie de lire une ligne complète du &lt;code&gt;Reader&lt;/code&gt;. Si la méthode retourne &lt;code&gt;null&lt;/code&gt;, c'est que la fin du texte source est atteinte, et dans ce cas le lexer se place en un mode où il retourne toujours un token de type &lt;code&gt;EOF&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Sinon, et après avoir traité les indentations au début de la ligne (je vais revenir là dessus plus tard), le lexer examine la première lettre de la ligne pour choisir la branche à suivre&lt;/li&gt;
&lt;li&gt;Si c'est une lettre, alors il continue à consommer la ligne un caractère à la fois jusqu'à ce qu'il trouve autre chose qu'une lettre ou un chiffre, en accumulant les caractères lus dans une chaîne&lt;ul&gt;
&lt;li&gt;Si cette chaîne est égale à &lt;code&gt;true&lt;/code&gt; ou &lt;code&gt;false&lt;/code&gt;, il retourne un token de type &lt;code&gt;BOOL&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Si cette chaîne figure dans la liste des mots clés, il retourne un token de type &lt;code&gt;KEYWORD&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Sinon, c'est que c'est un identifiant. Il retourne alors un token de type &lt;code&gt;NAME&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Si le premier caractère est un chiffre, le lexer continue de consommer les caractères tant qu'il trouve des chiffres, puis il retourne un token de type &lt;code&gt;NUM&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Si c'est plutôt &lt;code&gt;"&lt;/code&gt; ou &lt;code&gt;'&lt;/code&gt;, le lexer lit la chaîne ou le caractère et retourne un token de type &lt;code&gt;STRING&lt;/code&gt; ou &lt;code&gt;CHAR&lt;/code&gt;. Ce n'est pas très compliqué comme traitement, si ce n'est pour gérer les échappements (&lt;code&gt;\"&lt;/code&gt; ou &lt;code&gt;\n&lt;/code&gt; par exemple)&lt;/li&gt;
&lt;li&gt;Le lexer tente ensuite de lire un symbole parmi la liste des symboles qu'il reconnait. Je vais revenir sur cette partie plus tard, mais l'idée est d'utiliser un automate en essayant de matcher le symbole le plus long (par exemple, matcher un seul token avec la valeur &lt;code&gt;-&amp;gt;&lt;/code&gt; plutôt que 2 tokens &lt;code&gt;-&lt;/code&gt; et &lt;code&gt;&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Enfin, si on a atteint la fin de la ligne, on remet &lt;code&gt;currentLine&lt;/code&gt; à &lt;code&gt;null&lt;/code&gt;. De cette manière, le prochain appel à &lt;code&gt;pop&lt;/code&gt; va passer à la ligne suivante. Sinon, on lance une erreur car on est face à une entrée non reconnue&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="gestion-des-blancs_1"&gt;Gestion des blancs&lt;/h3&gt;
&lt;p&gt;A lecture d'une nouvelle ligne, et avant d'exécuter l'algorithme décrit dans la section précédente, le lexer consomme les espaces en début de la ligne en calculant leur nombre, ce qui définit le niveau d'indentation de la ligne. Il compare ensuite cette valeur au niveau d'indentation de la ligne précédente (qu'il maintient dans un champ initialisé à 0):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Si les 2 valeurs sont égales, il retourne un token de type &lt;code&gt;NEWLINE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Si le niveau d'indentation de la ligne courante est supérieur à celui de la ligne précédente, il retourne un token de type &lt;code&gt;INDENT&lt;/code&gt; mais il se met aussi dans un mode où le prochain appel à &lt;code&gt;pop&lt;/code&gt; retourne &lt;code&gt;NEWLINE&lt;/code&gt;. Dans une première version du lexer de Litil, je générais uniquement &lt;code&gt;INDENT&lt;/code&gt; ou &lt;code&gt;DEINDENT&lt;/code&gt; quand le niveau d'indentation changeait, &lt;code&gt;NEWLINE&lt;/code&gt; sinon. Mais cela posait plein de problèmes dans la phase suivante (le parseur) pour délimiter correctement les blocs, jusqu'à ce que je tombe sur &lt;a href="http://stackoverflow.com/questions/232682/how-would-you-go-about-implementing-off-side-rule/946398#946398"&gt;cette réponse sur Stackoverflow&lt;/a&gt;. En suivant la méthode décrite dans cette réponse, j'ai fini avec une implémentation beaucoup plus simple et surtout solide du parseur. Je reviendrai là-dessus dans le post qui va traiter du parsing.&lt;/li&gt;
&lt;li&gt;Sinon, il retourne un token de type &lt;code&gt;DEINDENT&lt;/code&gt; et se met en un mode pour retourner &lt;code&gt;NEWLINE&lt;/code&gt; à l'appel suivant&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Un exemple pour clarifier un peu les choses. Etant donné ce texte en entrée:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;
  &lt;span class="n"&gt;b&lt;/span&gt;
  &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Le lexer est censé générer les tokens suivants:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;NEWLINE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NAME(a)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;INDENT&lt;/code&gt;: le niveau d'indentation a augmenté à la 2ième ligne&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NEWLINE&lt;/code&gt;: toujours produit pour une nouvelle ligne&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NAME(b)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NEWLINE&lt;/code&gt;: le niveau d'indentation n'a pas changé entre les 2ième et 3ième lignes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NAME(c)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DEINDENT&lt;/code&gt;: le niveau d'indentation a diminué&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NEWLINE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NAME(d)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EOF&lt;/code&gt;: fin de l'entrée&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Seulement, l'algorithme décrit jusqu'ici n'est pas suffisant pour que le parseur arrive à gérer proprement l'indentation. En effet, avec l'exemple suivant:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;
  &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Le lexer ne va pas produire un token de type &lt;code&gt;DEINDENT&lt;/code&gt; après le &lt;code&gt;NAME(b)&lt;/code&gt; mais plutôt un &lt;code&gt;EOF&lt;/code&gt; car il n'y a pas de nouvelle ligne après le &lt;code&gt;b&lt;/code&gt;. On pourrait imaginer une solution où le parseur utilise &lt;code&gt;EOF&lt;/code&gt; en plus de &lt;code&gt;DEINDENT&lt;/code&gt; pour détecter la fin d'un bloc, mais ce n'est pas suffisant. En effet, avec l'exemple suivant:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;
  &lt;span class="n"&gt;b&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;L'implémentation décrite ici va générer un seul token &lt;code&gt;DEINDENT&lt;/code&gt;après &lt;code&gt;NAME(c)&lt;/code&gt; alors que cette position dans le source marque la fin de 2 blocs et non pas un seul.&lt;/p&gt;
&lt;p&gt;Pour gérer ce type de situations, et ne voulant pas complexifier encore le code du lexer de base, j'ai décidé de gérer ça dans une autre implémentation de l'interface &lt;code&gt;Lexer&lt;/code&gt;, &lt;code&gt;StructuredLexer&lt;/code&gt;. Cette dernière implémente le pattern décorateur en délégant à &lt;code&gt;BaseLexer&lt;/code&gt; pour générer les tokens du texte source, mais en l'enrichissant avec les traitements suivants:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;On maintient le niveau courant d'indentation dans un champ. Le niveau d'indentation est calculé en divisant le nombre d'espaces en début d'une ligne par une taille d'unité d'indentation, fixée à *&lt;em&gt;2 espaces&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Dans &lt;code&gt;pop&lt;/code&gt;, si le lexer de base retourne un &lt;code&gt;INDENT&lt;/code&gt;:&lt;ul&gt;
&lt;li&gt;Vérifier que le nombre d'espaces est un multiple de l'unité. Si ce n'est pas le cas, retourner une erreur&lt;/li&gt;
&lt;li&gt;S'assurer aussi que le niveau d'indentation n'augmente qu'avec des pas de &lt;strong&gt;1&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Mettre à jour le champ niveau d'indentation&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Toujours dans &lt;code&gt;pop&lt;/code&gt;, et quand le lexer de base retourne un &lt;code&gt;DEINDENT&lt;/code&gt;:&lt;ul&gt;
&lt;li&gt;Idem que pour &lt;code&gt;INDENT&lt;/code&gt;, s'assurer que le nombre de blancs est un multiple de l'unité d'indentation&lt;/li&gt;
&lt;li&gt;Si le niveau d'indentation a diminué de plus d'une unité (comme dans l'exemple précédent), générer autant de tokens &lt;code&gt;DEINDENT&lt;/code&gt; virtuels que nécessaires, tout en mettant à jour le champ niveau d'indentation&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Si dans &lt;code&gt;pop&lt;/code&gt; le lexer de base retourne &lt;code&gt;EOF&lt;/code&gt;, produire des &lt;code&gt;DEINDENT&lt;/code&gt; virtuels jusqu'à ce que le niveau d'indentation atteigne 0, puis retourner &lt;code&gt;EOF&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ainsi, avec l'exemple suivant:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;
  &lt;span class="n"&gt;b&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Le lexer structuré génère 1 &lt;code&gt;DEINDENT&lt;/code&gt; virtuel, en plus du &lt;code&gt;DEINDENT&lt;/code&gt; généré par le lexer de base entre &lt;code&gt;c&lt;/code&gt; et &lt;code&gt;d&lt;/code&gt;. Comme ça, le parseur au dessus pourra détecter la fin de 2 blocs et détecter correctement que &lt;code&gt;d&lt;/code&gt; a le même niveau que &lt;code&gt;a&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Enfin, &lt;a href="https://github.com/jawher/litil/blob/master/src/main/java/litil/lexer/StructuredLexer.java"&gt;le code source&lt;/a&gt; qui implémente cet algorithme est disponible dans le repo Github de Litil pour les intéressés.&lt;/p&gt;
&lt;h3 id="gestion-des-commentaires"&gt;Gestion des commentaires&lt;/h3&gt;
&lt;p&gt;Dans Litil, les commentaires sont préfixés par &lt;code&gt;--&lt;/code&gt; (double &lt;code&gt;-&lt;/code&gt;) et s'étendent sur une seule ligne uniquement. J'ai &lt;em&gt;(arbitrairement)&lt;/em&gt; choisi de les gérer au niveau du lexer en les ignorant complètement. Mais j'aurais aussi pu produire des tokens de type &lt;code&gt;COMMENT&lt;/code&gt; et les ignorer &lt;em&gt;(ou pas)&lt;/em&gt; dans le parseur.&lt;/p&gt;
&lt;p&gt;Les commentaires sont gérés à 2 endroits dans le lexer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dans le code qui lit une ligne du texte source. Si elle commence par &lt;code&gt;--&lt;/code&gt;, on ignore la ligne entière et on passe à la ligne suivante (pour gérer les commentaires en début d'une ligne)&lt;/li&gt;
&lt;li&gt;Dans le code qui gère les symboles. Si le symbole &lt;em&gt;matché&lt;/em&gt; correspond à &lt;code&gt;--&lt;/code&gt;, on passe à la ligne suivante (pour gérer les commentaires à la fin d'une ligne)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Exemples:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c"&gt;-- compute max x y … NOT !&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="c"&gt;-- It is a well known fact that x always wins ! &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3 id="gestion-des-symboles"&gt;Gestion des symboles&lt;/h3&gt;
&lt;p&gt;Avec la gestion des indentations, c'est la partie la plus intéressante &lt;em&gt;(amha)&lt;/em&gt; dans le code du lexer.&lt;/p&gt;
&lt;p&gt;Avant de rentrer dans les détails d'implémentation, je vais d'abord parler un peu d'&lt;a href="http://fr.wikipedia.org/wiki/Automate_fini"&gt;automates finis&lt;/a&gt;, qui sont une notion centrale dans la théorie des langages et la compilation.&lt;/p&gt;
&lt;p&gt;Un automate fini est un ensemble d'états et de transitions. On peut le voir comme un système de classification: étant donnée une séquence en entrée, il consomme ses éléments un à un en suivant les transitions adaptés (et donc en passant d'un état à un autre) jusqu'à ce qu'il ait consommé toute l'entrée ou encore qu'il arrive dans un état sans aucune transition  possible. Quelques états peuvent être marqués comme terminaux ou finals, une façon de dire que ça représente un succès. Donc étant donnée un automate et une entrée, si le traitement s'arrête dans un état terminal, on peut dire qu'on a prouvé une propriété donnée sur l'entrée. Cette propriété va dépendre de l'automate.&lt;/p&gt;
&lt;p&gt;Ok, j'explique comme un pied. Un exemple concrêt:&lt;/p&gt;
&lt;p&gt;&lt;img alt="litil-lexer-dfa0.png" src="/images/graphviz/litil-lexer-dfa0.png" /&gt;&lt;/p&gt;
&lt;p&gt;L'automate présenté dans la figure précédente se compose de:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Un état initial (conventionnellement appelé &lt;code&gt;S0&lt;/code&gt;). C'est l'unique point d'entrée de l'automate&lt;/li&gt;
&lt;li&gt;3 autres états &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt; et &lt;code&gt;C&lt;/code&gt;. Notez le double contour de ces états. Ca sert à indiquer que ce sont des états terminaux ou d'acceptation&lt;/li&gt;
&lt;li&gt;Des transitions entre ces états qui sont annotées par des caractères&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Maintenant, appliquons cet automate à la séquence de caractères &lt;code&gt;-&amp;gt;a&lt;/code&gt;.
Comme dit plus haut, on se positionne initialement au point d'entrée &lt;code&gt;S0&lt;/code&gt;. On examine le premier caractère de la séquence d'entrée (&lt;code&gt;-&amp;gt;a&lt;/code&gt;) et on cherche une transition qui part de cet état et qui est étiquetée avec ce caractère. Ca tombe bien, le premier caractère &lt;code&gt;-&lt;/code&gt; correspond bien à une transition entre &lt;code&gt;S0&lt;/code&gt; et &lt;code&gt;A&lt;/code&gt;. On suit donc cette transition pour arriver à l'état &lt;code&gt;A&lt;/code&gt; et on passe au caractère suivant (&lt;code&gt;&amp;gt;&lt;/code&gt;). L'état &lt;code&gt;A&lt;/code&gt; est terminal. On pourrait donc interrompre le traitement et dire et qu'on a réussi à matcher le caractère &lt;code&gt;-&lt;/code&gt;. Cependant, dans Litil et presque tous les autres langages, le lexer essai plutôt de matcher la séquence la plus longue. L'alternative est qu'il ne faut jamais avoir plusieurs opérateurs qui commencent par le même caractère, ce qui serait trop contraignant.&lt;/p&gt;
&lt;p&gt;On continue donc le traitement. &lt;code&gt;A&lt;/code&gt; dispose bien d'une transition étiquetée avec &lt;code&gt;&amp;gt;&lt;/code&gt;. On suit donc cette transition et on arrive à l'état &lt;code&gt;C&lt;/code&gt; qui est aussi terminal. Mais par la même logique, on n'abandonne pas tout de suite et on tente de voir s'il est possible de matcher une séquence plus longue. Ce n'est pas le cas ici car l'état &lt;code&gt;A&lt;/code&gt; n'a aucune transition étiquetée avec le caractère &lt;code&gt;a&lt;/code&gt;. Le traitement s'arrête donc ici, et comme c'est un état terminal, on retourne un succès avec la chaîne &lt;em&gt;matchée&lt;/em&gt; qui ici est &lt;code&gt;-&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Notez que l'algorithme que je viens de décrire (et qui est utilisé par l'implémentation actuelle du lexer de Litil) est plutôt simpliste et incomplet par rapport à l'état de l'art car il ne gère pas le &lt;em&gt;backtracking&lt;/em&gt;. Par exemple, cet algorithme échoue avec l'automate suivante (censé reconnaitre les symboles &lt;code&gt;-&lt;/code&gt; et &lt;code&gt;--&amp;gt;&lt;/code&gt;) avec la chaîne &lt;code&gt;--a&lt;/code&gt; comme entrée alors qu'il devrait réussir à retourner deux fois le symbole &lt;code&gt;-&lt;/code&gt; (le pourquoi est laissé comme exercice au lecteur):&lt;/p&gt;
&lt;p&gt;&lt;img alt="litil-lexer-dfa1.png" src="/images/graphviz/litil-lexer-dfa1.png" /&gt;&lt;/p&gt;
&lt;p&gt;Dans sa version actuelle, les symboles reconnus par Litil sont: &lt;code&gt;-&amp;gt;&lt;/code&gt;, &lt;code&gt;.&lt;/code&gt;, &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;(&lt;/code&gt;, &lt;code&gt;)&lt;/code&gt;, &lt;code&gt;=&lt;/code&gt;, &lt;code&gt;%&lt;/code&gt;, &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;=&lt;/code&gt;, &lt;code&gt;&amp;gt;=&lt;/code&gt;, &lt;code&gt;:&lt;/code&gt;, &lt;code&gt;,&lt;/code&gt;, &lt;code&gt;[&lt;/code&gt;, &lt;code&gt;]&lt;/code&gt;, &lt;code&gt;|&lt;/code&gt;, &lt;code&gt;_&lt;/code&gt;, &lt;code&gt;=&amp;gt;&lt;/code&gt;, &lt;code&gt;\\&lt;/code&gt;, &lt;code&gt;--&lt;/code&gt;, &lt;code&gt;::&lt;/code&gt;, &lt;code&gt;{&lt;/code&gt; et &lt;code&gt;}&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Maintenant, juste pour la science, voici l'automate fini correspondant à ces symboles:&lt;/p&gt;
&lt;p&gt;&lt;img alt="litil-lexer-dfa-litil.png" src="/images/graphviz/litil-lexer-dfa-litil.png" /&gt;&lt;/p&gt;
&lt;p&gt;L'implémentation de cet automate dans Litil est dynamique, dans la mesure où l'automate est construit au &lt;em&gt;runtime&lt;/em&gt; à partir d'une liste des symboles à reconnaitre. Aussi, cette implémentation ne gère pas le &lt;em&gt;backtracking&lt;/em&gt;, qui est inutile pour le moment car, et à moins que je ne dise de bêtises, le problème décrit plus haut n'arrive que si on a des symboles à 3 caractères (et qui ont le même préfixe qu'un symbole à un caractère), ce qui n'est pas le cas dans Litil (ce n'est pas Scala tout de même. Enfin, pas encore). Par contre, l'implémentation tient en 50 lignes de code Java, et si on ignore le décorum de Java (les imports, les &lt;em&gt;getters&lt;/em&gt;, le &lt;code&gt;toString&lt;/code&gt;, le constructeur, etc.), l'essence de l'algorithme tient juste dans une douzaine de lignes. &lt;a href="https://github.com/jawher/litil/blob/master/src/main/java/litil/lexer/LexerStage.java"&gt;Voici son code source sur Github&lt;/a&gt; pour les intéressés.&lt;/p&gt;
&lt;h3 id="lookahead"&gt;Lookahead&lt;/h3&gt;
&lt;p&gt;Une fonctionnalité utile à avoir dans le lexer est le &lt;code&gt;lookahead&lt;/code&gt;, i.e. la possibilité de voir les tokens suivants sans pour autant les consommer (comme c'est le cas avec &lt;code&gt;pop&lt;/code&gt;). On va revenir la dessus dans le(s) post(s) à propos du parseur.&lt;/p&gt;
&lt;p&gt;Tout comme &lt;code&gt;StructuredLexer&lt;/code&gt;, j'ai décidé d'implémenter cette fonctionnalité dans un décorateur autour d'un lexer concrêt, pour ne pas complexifier le code de ce dernier. Il s'agit de la classe &lt;code&gt;LookaheadLexerWrapper&lt;/code&gt; (&lt;a href="https://github.com/jawher/litil/blob/master/src/main/java/litil/lexer/LookaheadLexerWrapper.java"&gt;dont voici le code source&lt;/a&gt;). L'implémentation derrière est plutôt simple. En effet, l'astuce est juste de maintenir une liste de tokens (en plus du lexer concrêt). Quand la méthode &lt;code&gt;lookahead&lt;/code&gt; est appelé (avec un paramètre qui indique le niveau du lookahead: 1 pour le token suivant, etc.), on récupère autant de tokens que nécessaire du lexer et on les stocke dans cette liste. Quand &lt;code&gt;pop&lt;/code&gt; est appelée, et avant de déléger au lexer concrêt, on vérifie si la liste de tokens n'est pas vide. Si c'est le cas, on retourne le premier élément de cette liste et en prenant soin de l'enlever, comme ça, l'appel suivant à &lt;code&gt;pop&lt;/code&gt; va retourner le token suivant. Si cette liste est vide, alors on délègue au lexer.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Dans ce post, j'avais présenté rapidement et sans trop entrer dans les détails quelques techniques de lexing que j'ai utilisé dans Litil. Ce n'est en aucune façon la meilleure façon de faire ni la plus performante. C'était plus une implémentation relativement facile à coder et à étendre tout en restant raisonnable pour tout ce qui est consommation mémoire (le fait de ne pas lire la totalité du fichier dans une seule &lt;code&gt;String&lt;/code&gt; d'un coup par exemple).&lt;/p&gt;
&lt;p&gt;Il faut aussi noter que c'est la partie la moins &lt;em&gt;marrante&lt;/em&gt; à coder dans un langage. J'ai même été tenté de la faire générer par un outil comme AntLR ou SableCC, mais au final j'ai décidé de rester fidèle à ma vision de vraiment tout coder à la main &lt;em&gt;(sauf les parties que je ne coderai pas à la main, NDLR)&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Maintenant que cette partie est derrière nous, nous allons enfin pouvoir attaquer les sujets intéressants, e.g. &lt;a href="http://jawher.me/2013/08/11/creation-langage-programmation-litil-3-1-introduction-parsing/"&gt;le parseur&lt;/a&gt; et l'évaluateur, dans les posts suivants.&lt;/p&gt;</summary></entry><entry><title>Le conte de Litil - Chapitre 1, Génèse d'un langage de programmation</title><link href="https://jawher.me/2012/06/04/creation-langage-programmation-litil-1/" rel="alternate"></link><updated>2012-06-04T00:00:00+02:00</updated><author><name>Jawher Moussa</name></author><id>tag:jawher.me,2012-06-04:2012/06/04/creation-langage-programmation-litil-1/</id><summary type="html">&lt;p&gt;Comme beaucoup d'autres passionnés d'informatique, j'ai toujours été fasciné par les compilateurs et les langages de programmation, et ce depuis que j'ai appris à programmer. Mais ma fascination ne s'arrêtait pas au fait que je pouvais commander ma machine en écrivant des programmes pour produire des résultats &lt;em&gt;(parfois)&lt;/em&gt; utiles. En effet, j'étais encore plus fasciné par les compilateurs eux-mêmes. Je trouvais magique qu'un programme réussisse à &lt;em&gt;"lire"&lt;/em&gt; et à exécuter ce que je venais de saisir.&lt;/p&gt;
&lt;p&gt;Je me rappelle encore de ma première tentative d'écrire un parseur. A l'époque (j'étais encore au lycée), je ne savais même pas que c'est comme ça que ça s'appelait. Je venais à peine d'apprendre Pascal sur un Commodore, et je voulais absolument écrire un &lt;em&gt;truc&lt;/em&gt; qui évaluerait une expression arithmétique sous forme d'une chaine de caractères, sans le moindre &lt;em&gt;background&lt;/em&gt; théorique sur le sujet, ni même d'accès aux internets®. Je ne me rappelle plus si j'avais réussi à le faire ou pas, mais je n'ai pas oublié quelques rustines que j'avais pondu à l'époque, comme par exemple le fait d'évaluer en priorité les expressions parenthésées. Ma solution était de chercher la première parenthèse fermante, puis de partir dans l'autre sens jusqu'à la première parenthèse ouvrante pour délimiter le bout à évaluer en premier, puis répéter le processus jusqu'à ce qu'il ne reste plus de parenthèses &lt;em&gt;(Non, ce n'est pas comme ça qu'il faut faire ;)&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Depuis, j'en ai pas mal appris sur le sujet lors de mes études universitaires, mais surtout dans un cadre professionnel, où j'ai eu la chance de travailler sur 2 projets nécéssitant l'écriture d'un parseur pour un DSL métier. J'essayais aussi d'en apprendre un peu plus en lisant l'occasionnel papier de recherche, ou en fréquentant des sites comme &lt;a href="http://lambda-the-ultimate.org/"&gt;LtU&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Récemment, j'ai décidé que, comme tout le monde, je vais créer mon langage de programmation, aka JavaSlayer™, et pour rendre l'exercice encore plus stimulant, j'ai décidé de ne pas utiliser un générateur de parseurs (à la ANTLR) mais plutôt de tout faire à la main et à l'ancienne sans la moindre bibliothèque ni framework. Le but était de vraiment comprendre comment fonctionnait un compilateur. J'avais aussi été influencé par &lt;a href="http://en.wikipedia.org/wiki/Niklaus_Wirth"&gt;Niklaus Wirth&lt;/a&gt; (le créateur de Pascal, Modula et Oberon) qui a écrit tous ses compilateurs à la main.&lt;/p&gt;
&lt;p&gt;Et je ne sais pas comment, mais après 2 ou 3 mois de travail occasionnel, je me suis retrouvé avec un parseur et évaluateur pour langage plutôt puissant, dites bonjour à &lt;code&gt;Litil&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;Comme je n'avais plus envie de blogger sur "Comment créer une application &lt;code&gt;&amp;lt;framework web #1&amp;gt;&lt;/code&gt; avec &lt;code&gt;&amp;lt;orm #2&amp;gt;&lt;/code&gt; et &lt;code&gt;&amp;lt;framework js #3&amp;gt;&lt;/code&gt; sur &lt;code&gt;&amp;lt;un ide&amp;gt;&lt;/code&gt; pour gérer &lt;code&gt;&amp;lt;sujet hip du moment&amp;gt;&lt;/code&gt; et l'héberger sur &lt;code&gt;&amp;lt;fournisseur PaaS|SaaS|IaaS&amp;gt;&lt;/code&gt;", je me lance dans une série (enfin j'espère) de billets sur le sujet de parsing, sans plan particulier, quoi que j'essairais de maintenir une semblance d'ordre logique, où j'exposerais les techniques que j'utilise (au fur et à mesure que je les apprenne).&lt;/p&gt;
&lt;p&gt;Il faut préciser que bien qu'il existe pleins d'outils qui permettent de générer &lt;strong&gt;facilement&lt;/strong&gt; des parseurs, comme SableCC, ANTLR, JavaCC, lex/yacc, flex/bison, etc., mais le but ici est justement de tout faire à la main, l'objectif étant de comprendre comment ça fonctionne à l'intérieur(™).&lt;/p&gt;
&lt;h1 id="litil"&gt;Litil&lt;/h1&gt;
&lt;p&gt;Comme dit plus haut, ce post entame une série où je présenterai et expliquerai les différentes techniques que j'avais utilisées pour créer un parseur et un évaluateur pour un langage de programmation, Litil™, le tout en Java avec toutefois quelques notices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;C'est du &lt;em&gt;work in progress&lt;/em&gt;. On n'arrête pas de nous le dire: &lt;em&gt;release early, release often&lt;/em&gt;, mais je tenais à le préciser quand même: j'avançais en tatonnant, en apprenant au fur et à mesure, et donc, inévitablement, il y'aurait plusieurs coquilles.&lt;/li&gt;
&lt;li&gt;J'en ai parlé dans le point précédent: je ne prétends pas être une autorité dans ce sujet. J'ai eu un début de formation théorique dessus et j'ai lu pas mal de littérature.&lt;/li&gt;
&lt;li&gt;J'ai récemment commencé à travaillé sur la compilation vers du bytecode. Il se peut que j'en parle dans un futur post, mais c'est encore assez tôt et je ne promet rien.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Une présentation rapide de Litil en quelques points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;langage fonctionnel fortement inspiré de ML, (O)Caml et Haskell et &lt;a href="http://roy.brianmckenna.org/"&gt;Roy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;inférence de types totale avec &lt;a href="http://en.wikipedia.org/wiki/Hindley-Milner_type_inference"&gt;Hindley Milner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Off-side_rule"&gt;les blocs sont délimités avec l'indentation (à la Python)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;types supportés: entiers, chaines, booléens, caractères, &lt;a href="http://en.wikipedia.org/wiki/Tuple"&gt;tuples&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Record_(computer_science)"&gt;records&lt;/a&gt; et &lt;a href="http://en.wikipedia.org/wiki/Algebraic_data_type"&gt;ADTs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Pattern_matching"&gt;pattern matching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;a href="http://en.wikipedia.org/wiki/Currying"&gt;curried functions&lt;/a&gt;&lt;/em&gt; par défaut&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Closure_(computer_science)"&gt;closures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;exceptions (try/catch/throw)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Voilà. Maintenant un petit &lt;em&gt;teaser&lt;/em&gt; pour vous donner une idée sur à quoi ressemble le langage qu'on va créer.&lt;/p&gt;
&lt;h2 id="affectations-expressions-et-fonctions"&gt;affectations, expressions et fonctions&lt;/h2&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;fact&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;fact&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;f5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fact&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id="tuples-et-records"&gt;tuples et records&lt;/h2&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;lpe&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id="destructuring"&gt;destructuring&lt;/h2&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;d&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;true&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bool&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id="types-algebriques"&gt;types algebriques&lt;/h2&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;data&lt;/span&gt; &lt;span class="nc"&gt;Option&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;None&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Some&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;thing&amp;quot;&lt;/span&gt;

&lt;span class="k"&gt;data&lt;/span&gt; &lt;span class="nc"&gt;List&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Cons&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Nil&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Cons&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Cons&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="nc"&gt;Nil&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;data&lt;/span&gt; &lt;span class="nc"&gt;Tree&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Null&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Leaf&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Tree&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Tree&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Node&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Leaf&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Leaf&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id="pattern-matching"&gt;pattern matching&lt;/h2&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;
    &lt;span class="bp"&gt;[]&lt;/span&gt;     &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;

&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id="application-partielle"&gt;application partielle&lt;/h2&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;inc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;three&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inc&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h2 id="closures-et-higher-order-functions"&gt;closures et higher-order functions&lt;/h2&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;xs&lt;/span&gt;
    &lt;span class="bp"&gt;[]&lt;/span&gt;     &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Nil&lt;/span&gt;
    &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;double&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;

&lt;span class="c"&gt;-- pass a function by name&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;l2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="n"&gt;double&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;

&lt;span class="c"&gt;-- or simply a lambda&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;l2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="o"&gt;(\&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;

&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;\&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="c"&gt;-- f capture la valeur lexicale de a, i.e. 4&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h1 id="les-themes-qui-seront-abordes"&gt;Les thèmes qui seront abordés&lt;/h1&gt;
&lt;p&gt;La création d'un langage de programmation en général, et de Litil en particulier, nécessite d'aborder les thèmes suivants:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://jawher.me/2012/06/27/creation-langage-programmation-litil-2-lexer/"&gt;Lexing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Parsing&lt;ul&gt;
&lt;li&gt;&lt;a href="http://jawher.me/2013/08/11/creation-langage-programmation-litil-3-1-introduction-parsing/"&gt;BNF/EBNF&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="http://jawher.me/2013/08/19/creation-langage-programmation-litil-3-2-recursive-descent-parsing/"&gt;Parsing à descente récursive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Pratt_parser"&gt;Pratt parsing&lt;/a&gt; pour les expressions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Inférence et vérification des types (Hindley Milner)&lt;/li&gt;
&lt;li&gt;Evaluation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour les posts qui vont suivre, je ne vais pas forcément traiter de ces sujets dans l'ordre, le but étant d'implémenter graduellement les différentes composantes du langage du parsing jusqu'à l'évaluation. Du coup, la suite va consister à faire des allers-retours sur ces différents thèmes au fur et à mesure de l'avancement du développement du langage.&lt;/p&gt;</summary></entry></feed>