{"id":24704,"date":"2026-09-16T16:57:06","date_gmt":"2026-09-16T16:57:06","guid":{"rendered":"https:\/\/www.mailgun.com\/blog\/comment-nous-avons-cree-analyseur-inspire-lucene-go\/"},"modified":"2026-09-16T16:57:06","modified_gmt":"2026-09-16T16:57:06","slug":"comment-nous-avons-cree-analyseur-inspire-lucene-go","status":"publish","type":"blog","link":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/comment-nous-avons-cree-analyseur-inspire-lucene-go\/","title":{"rendered":"Comment nous avons cr\u00e9\u00e9 un analyseur inspir\u00e9 de Lucene en Go"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Chez Mailgun, nous avons de nombreux syst\u00e8mes qui g\u00e9n\u00e8rent une tonne d&rsquo;\u00e9v\u00e9nements \u00e0 chaque heure de la journ\u00e9e. C&rsquo;est un nombre si important qu&rsquo;il est impossible pour une \u00e9quipe de trier les r\u00e9sultats ElasticSearch et d&rsquo;esp\u00e9rer obtenir des r\u00e9sultats coh\u00e9rents, ou m\u00eame de garder toute sa t\u00eate.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Comme beaucoup d&rsquo;entreprises, <b>nous devons tout de m\u00eame trouver un moyen de g\u00e9rer toutes ces donn\u00e9es<\/b>. Cela repr\u00e9sente une t\u00e2che consid\u00e9rable\u00a0: cr\u00e9er un syst\u00e8me qui permet \u00e0 nos clients internes de r\u00e9agir aux \u00e9v\u00e9nements en temps r\u00e9el.<\/p>\n\n\n\r\n    <nav data-content-type=\"longform\" class=\"toc-block longform-spacings px-5 py-6 px-md-6 px-lg-7 py-md-7 bg-light fs-sm rounded-lg\" aria-labelledby=\"toc-title-5899\"><p class=\"h5 m-0\" id=\"toc-title-5899\">Table des mati\u00e8res<\/p><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">01<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#reflexion\">R\u00e9flexion<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">02<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#passons-a-la-grammaire\">Passons \u00e0 la grammaire<\/a><a class=\"scrollme link-body-color\" href=\"#grammaires-non-contextuelles-et-grammaires-dexpression-danalyse\">Grammaires non contextuelles et grammaires d&rsquo;expression d&rsquo;analyse<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">03<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#prendre-son-envol\">Prendre son envol<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">04<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#comme-une-feuille-au-vent\">Comme une feuille au vent<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">05<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#genial-et-maintenant\">G\u00e9nial, et maintenant\u00a0?<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">06<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#considerations\">Consid\u00e9rations<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">07<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#prochaines-etapes\">Prochaines \u00e9tapes<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">08<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#avantages-et-inconvenients\">Avantages et inconv\u00e9nients<\/a><a class=\"scrollme link-body-color\" href=\"#avantages\">Avantages\u00a0:<\/a><a class=\"scrollme link-body-color\" href=\"#inconvenients\">Inconv\u00e9nients\u00a0:<\/a><\/div><\/div><div class=\"d-flex mt-3\"><div class=\"w-auto fw-bold text-accent d-flex me-2\">09<\/div><div class=\"d-flex flex-column\"><a class=\"fw-bold scrollme link-body-color text-accent\" href=\"#la-fin-enfin\">La fin, enfin<\/a><\/div><\/div><\/nav>\n\n\n<p class=\"wp-block-paragraph\">G\u00e9n\u00e9ralement, les options pour r\u00e9soudre un tel probl\u00e8me incluent\u00a0:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>L&rsquo;int\u00e9gration des donn\u00e9es dans une base de donn\u00e9es, puis l&rsquo;ex\u00e9cution de requ\u00eates, souvent \u00e0 intervalles r\u00e9guliers<\/li>\n\n\n\n<li>Les solutions MapReduce comme Hadoop<\/li>\n\n\n\n<li>Mechanical Turk \u00a0<\/li>\n\n\n\n<li>Les filtres en temps r\u00e9el.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Nous sommes fiers de faire beaucoup avec tr\u00e8s peu, nous avons donc cherch\u00e9 \u00e0 voir comment les filtres en temps r\u00e9el pouvaient fonctionner pour nous. Nous nous sommes concentr\u00e9s sur la cr\u00e9ation d&rsquo;un syst\u00e8me permettant \u00e0 n&rsquo;importe quel membre des \u00e9quipes d&rsquo;ing\u00e9nierie et de support d&rsquo;<b>\u00e9crire des r\u00e8gles qui r\u00e9agissent et ex\u00e9cutent des actions en leur nom.<\/b><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">R\u00e9flexion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Lors de la conception de ce syst\u00e8me, nous avons essay\u00e9 de cr\u00e9er quelque chose qui donnerait \u00e0 chacun les outils n\u00e9cessaires pour it\u00e9rer rapidement et r\u00e9pondre aux menaces pesant sur notre syst\u00e8me, tout en devant se conformer aux r\u00e8gles suivantes\u00a0:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Les utilisateurs doivent pouvoir ajouter leurs propres r\u00e8gles \u00e0 volont\u00e9<\/li>\n\n\n\n<li>Le langage d\u00e9di\u00e9, ci-apr\u00e8s appel\u00e9 DSL, doit \u00eatre aussi simple que possible et ressembler id\u00e9alement \u00e0 quelque chose qu&rsquo;ils connaissent d\u00e9j\u00e0.<\/li>\n\n\n\n<li>Les membres de l&rsquo;\u00e9quipe doivent pouvoir tester leurs r\u00e8gles sur les donn\u00e9es historiques avant de les appliquer.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Nous utilisons Kibana en interne, <b>donc quelque chose qui pourrait \u00eatre test\u00e9 avec cet outil pour remplir le point num\u00e9ro 3 \u00e9tait id\u00e9al<\/b>. Cela nous a conduits \u00e0 une conclusion \u00e9vidente\u00a0: nous devions \u00e9crire un analyseur DSL inspir\u00e9 de Lucene\u00a0!\u00a0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La premi\u00e8re it\u00e9ration du syst\u00e8me s&rsquo;appuyait sur des expressions r\u00e9guli\u00e8res et beaucoup d&rsquo;analyses caract\u00e8re par caract\u00e8re. Cela faisait l&rsquo;affaire, mais les it\u00e9rations suivantes ont rapidement gagn\u00e9 en complexit\u00e9. Si vous avez d\u00e9j\u00e0 travaill\u00e9 sur un vaste projet d&rsquo;analyse de cha\u00eenes de caract\u00e8res, vous voyez ce que nous voulons dire.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pour aller plus loin, <b>nous savions que nous devions cr\u00e9er quelque chose qui pourrait \u00eatre it\u00e9r\u00e9 rapidement<\/b>, et id\u00e9alement, conforme \u00e0 une norme connue.<\/p>\n\n\n\r\n    <aside data-content-type=\"longform\"  class=\"banner-block longform-spacings rounded-lg shadow-lg px-5 py-6 px-md-6 py-md-7 p-lg-7 bg-light\" data-theme=\"dark\" aria-labelledby=\"banner-block-block_91436b1e60ccbb2f99a53ea291672375\">\r\n                    <p class=\"text-uppercase section-caption text-body-color\">\r\n                S&rsquo;inscrire            <\/p>\r\n                            <p class=\"h4 text-accent fw-bold\" id=\"banner-block-block_91436b1e60ccbb2f99a53ea291672375\">\r\n                Lancez-vous, c&rsquo;est facile ! Et c&rsquo;est gratuit.            <\/p>\r\n                            <div class=\"mb-0 text-body-color\">\r\n                                    <div class=\"content-body mb-0 text-body-color\">D\u00e9couvrez ce que vous pouvez accomplir avec la meilleure plateforme de livraison d\u2019emails au monde.<\/div>\r\n                            <\/div>\r\n        \r\n        <div class=\"text-start mt-5\"><a href=\"https:\/\/signup.mailgun.com\/new\/signup\"  class=\"btn btn-secondary\" >Get started<\/a><\/div>\r\n    <\/aside>\r\n\r\n\n\n\n<h2 class=\"wp-block-heading\">Passons \u00e0 la grammaire<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ceux d&rsquo;entre nous qui ont suivi des cours universitaires sur la th\u00e9orie des automates ou similaires se souviennent probablement des grammaires dans le contexte des langages de programmation. Par ailleurs, il est certain que certains lecteurs auront bien plus d&rsquo;expertise que votre humble auteur en la mati\u00e8re. Pour toute explication approfondie, nous vous renvoyons donc \u00e0 votre moteur de recherche pr\u00e9f\u00e9r\u00e9.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Il est tout de m\u00eame utile de parler bri\u00e8vement de ce qui constitue une grammaire et de la raison pour laquelle elles sont utiles. Pour citer Wikip\u00e9dia, une <a href=\"https:\/\/en.wikipedia.org\/wiki\/Formal_grammar\" target=\"_tabs\" rel=\"noopener noreferrer\">Grammaire formelle<\/a> est \u00ab\u00a0&#8230;un ensemble de r\u00e8gles de production pour les cha\u00eenes de caract\u00e8res dans un langage formel. <b>Les r\u00e8gles d\u00e9crivent comment former des cha\u00eenes \u00e0 partir de l&rsquo;alphabet du langage qui sont valides selon la syntaxe de ce langage<\/b>. Une grammaire ne d\u00e9crit pas le sens des cha\u00eenes ni ce que l&rsquo;on peut en faire dans un contexte donn\u00e9, mais seulement leur forme.\u00a0\u00bb<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Au risque de simplifier \u00e0 l&rsquo;extr\u00eame, cela nous permet de prendre une cha\u00eene de caract\u00e8res comme \u00ab\u00a0Vous avez un email\u00a0!\u00a0\u00bb et de la d\u00e9composer en jetons que nous pouvons analyser s\u00e9mantiquement. En d&rsquo;autres termes, si notre grammaire est bien d\u00e9finie, nous pouvons alors proc\u00e9der \u00e0 un codage suppl\u00e9mentaire pour d\u00e9terminer le sens de cette cha\u00eene.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">L&rsquo;histoire et les types de grammaires pourraient remplir des tonnes de livres et d\u00e9passent donc largement le cadre d&rsquo;un article de blog. Nous allons plut\u00f4t nous concentrer sur les <b>grammaires non contextuelles<\/b> (ou alg\u00e9briques) et plus sp\u00e9cifiquement, sur les grammaires d&rsquo;expression d&rsquo;analyse (PEG).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Grammaires non contextuelles et grammaires d&rsquo;expression d&rsquo;analyse<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Pour citer \u00e0 nouveau Wikip\u00e9dia, une<a href=\"https:\/\/en.m.wikipedia.org\/wiki\/Context-free_grammar\" target=\"_tabs\" rel=\"noopener noreferrer\"> Grammaire non contextuelle<\/a> est \u00ab\u00a0un certain type de grammaire formelle\u00a0: un ensemble de r\u00e8gles de production qui d\u00e9crivent toutes les cha\u00eenes de caract\u00e8res possibles dans un langage formel donn\u00e9. Les r\u00e8gles de production sont de simples remplacements.\u00a0\u00bb<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Autrement dit, une grammaire non contextuelle <b>d\u00e9finit un graphe qui, \u00e0 son tour, d\u00e9finit comment analyser un langage<\/b>. Comme mentionn\u00e9 ci-dessus, cela ne nous dit <i>pas <\/i>comment comprendre le langage. Il convient \u00e9galement de mentionner, comme nous le verrons ci-dessous, que le graphe peut comporter des cycles, mais qu&rsquo;il finit par s&rsquo;arr\u00eater.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Les grammaires non contextuelles ont en quelque sorte une cousine avec la<a href=\"https:\/\/en.m.wikipedia.org\/wiki\/Parsing_expression_grammar\" target=\"_tabs\" rel=\"noopener noreferrer\"> Grammaire d&rsquo;expression d&rsquo;analyse<\/a>, ou PEG. Elles <i>ressemblent<\/i> beaucoup \u00e0 une grammaire non contextuelle (CFG), mais avec une distinction tr\u00e8s utile\u00a0: lorsqu&rsquo;elle est confront\u00e9e \u00e0 un choix ambigu, la PEG choisira toujours la premi\u00e8re r\u00e8gle de production d\u00e9finie. La CFG, en revanche, laisse le choix ambigu, et pourquoi s&#8217;emb\u00eater avec l&rsquo;ambigu\u00eft\u00e9 quand ce n&rsquo;est pas n\u00e9cessaire\u00a0?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ce que cela signifie vraiment, c&rsquo;est qu&rsquo;<b>il est plus facile d&rsquo;\u00e9crire des outils pour d\u00e9finir des PEG<\/b>. Heureusement, de nombreuses personnes l&rsquo;ont d\u00e9j\u00e0 fait pour nous.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prendre son envol<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Apr\u00e8s quelques recherches, nous avons opt\u00e9 pour <a href=\"https:\/\/github.com\/mna\/pigeon\" target=\"_tabs\" rel=\"noopener noreferrer\">Pigeon<\/a> comme base pour notre PEG. Pigeon suit le m\u00eame paradigme que de nombreux outils Go en g\u00e9n\u00e9rant un code qui se compile en m\u00eame temps que votre programme.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Son utilisation est assez simple\u00a0: vous d\u00e9finissez \u00e0 la fois la grammaire et le code Go pour g\u00e9rer chacune des r\u00e8gles dans le m\u00eame package, et vous appelez simplement Parse() sur l&rsquo;analyseur g\u00e9n\u00e9r\u00e9. Le d\u00e9fi consiste \u00e0 \u00e9crire des gestionnaires pour chacune de ces r\u00e8gles. Tout comme les grammaires, le sujet de la compilation pourrait remplir une biblioth\u00e8que enti\u00e8re de livres. Heureusement pour nous, <b>\u00e9crire un interpr\u00e9teur est moins complexe<\/b>, et le code r\u00e9sultant est suffisamment rapide pour nos besoins.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">De plus, la syntaxe tente de s&rsquo;aligner \u00e9troitement sur la syntaxe Go elle-m\u00eame, ce qui facilite l&rsquo;\u00e9criture de votre PEG en parall\u00e8le de votre programme Go utilisant la grammaire.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Comme une feuille au vent<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Imaginons que vous ayez un \u00e9v\u00e9nement g\u00e9n\u00e9r\u00e9 par l&rsquo;envoi d&rsquo;un email, encod\u00e9 en JSON, qui ressemble \u00e0 ceci\u00a0:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>{<br>\n\u00a0\"event\": \"sent\",<br>\n\u00a0\"subject\": \"A special offer just for you!\",<br>\n\u00a0\"account\": \"12345\",<br>\n}<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Il y a plusieurs fa\u00e7ons de consid\u00e9rer cet \u00e9v\u00e9nement\u00a0: vous pourriez d\u00e9cider qu&rsquo;il s&rsquo;agit d&rsquo;un email inoffensif, ou vous pourriez vous dire \u00ab\u00a0Il pourrait s&rsquo;agir de spam, mais il n&rsquo;y a pas assez d&rsquo;informations pour trancher\u00a0\u00bb. Il s&rsquo;agit d&rsquo;un probl\u00e8me tr\u00e8s courant dans notre syst\u00e8me, qui n\u00e9cessite toujours un grand nombre de donn\u00e9es agr\u00e9g\u00e9es pour parvenir \u00e0 une conclusion.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u00c9crivons donc une r\u00e8gle qui correspondra \u00e0 l&rsquo;\u00e9v\u00e9nement ci-dessus\u00a0:<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    event:&quot;sent&quot; AND subject:&quot;A special offer just for you!&quot;\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">C&rsquo;est assez facile \u00e0 analyser et, mieux encore, cela peut aussi \u00eatre v\u00e9rifi\u00e9 dans Kibana\u00a0!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Voyons maintenant comment <b>construire une PEG tr\u00e8s simple <\/b>qui correspondrait \u00e0 cette r\u00e8gle. Nous allons impl\u00e9menter chaque r\u00e8gle de production une par une et expliquer son fonctionnement. Les noms des r\u00e8gles suivent g\u00e9n\u00e9ralement le<a href=\"https:\/\/en.wikipedia.org\/wiki\/Pascal_(programming_language)#Language_constructs\" target=\"_tabs\" rel=\"noopener noreferrer\"> PascalCase<\/a> et autorisent \u00e9galement les chiffres et les tirets du bas (underscores). Chaque r\u00e8gle prend la forme suivante\u00a0:<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    RuleName &lt;- \r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">Notez qu&rsquo;il existe en fait plusieurs caract\u00e8res autoris\u00e9s pour l&rsquo;op\u00e9rateur de d\u00e9finition de r\u00e8gle, mais nous pr\u00e9f\u00e9rons &lt;- car il est facile \u00e0 taper et ressemble davantage aux grammaires telles qu&#039;elles sont d\u00e9finies de mani\u00e8re acad\u00e9mique.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La premi\u00e8re r\u00e8gle de la grammaire est trait\u00e9e comme le point d&rsquo;entr\u00e9e\u00a0:<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    Input &lt;- Term !.\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">Notre r\u00e8gle <code>Input<\/code> dit \u00ab\u00a0Faire correspondre toute la cha\u00eene d&rsquo;entr\u00e9e\u00a0\u00bb avec <code>!.<\/code> ce qui signifie \u00ab\u00a0Faire correspondre la fin du fichier\u00a0\u00bb. Cela transmettra l&rsquo;ensemble de la cha\u00eene d&rsquo;entr\u00e9e \u00e0 une r\u00e8gle nomm\u00e9e Term qui ressemble \u00e0 ceci\u00a0:<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    Term &lt;- Variable AndVar*\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">Cela transmet le flux de contr\u00f4le \u00e0 la r\u00e8gle de production de la variable\u00a0:<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    Variable &lt;-  FieldChars+ _ &quot;:&quot; _ Value\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">Maintenant, cela devient un peu plus complexe. Tout d&rsquo;abord, nous faisons correspondre de mani\u00e8re gourmande tous les caract\u00e8res jusqu&rsquo;\u00e0 ce que la r\u00e8gle FieldChars soit satisfaite. Notez le <code>+<\/code> pr\u00e9sent \u00e0 la fin. La syntaxe PEG a beaucoup en commun avec les expressions r\u00e9guli\u00e8res, cela signifie donc \u00ab\u00a0Faire correspondre la r\u00e8gle <code>FieldChars<\/code> une ou plusieurs fois\u00a0\u00bb<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    FieldChars &lt;- [a-z]\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">L\u00e0 encore, si vous connaissez la syntaxe regex, cela devrait \u00eatre tr\u00e8s clair\u00a0: il suffit de faire correspondre un seul caract\u00e8re compris entre \u00ab\u00a0a\u00a0\u00bb et \u00ab\u00a0z\u00a0\u00bb<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Revenons maintenant \u00e0 la variable, la partie suivante <code>_<\/code> est une r\u00e8gle signifiant \u00ab\u00a0faire correspondre n&rsquo;importe quel caract\u00e8re d&rsquo;espacement\u00a0\u00bb. Notez que <code>_<\/code> est un identifiant tout \u00e0 fait valide pour une r\u00e8gle de production, et avoir moins \u00e0 taper est g\u00e9n\u00e9ralement une bonne chose.<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                Java                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-Java\">\r\n                                <code id=\"code_0_content\" class=\"language-Java\">\r\n\r\n                                    _ &quot;whitespace&quot; &lt;- [ \\n\\t\\r]*\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">Il y a deux ou trois choses \u00e0 noter ici\u00a0:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>La cha\u00eene de caract\u00e8res \u00ab\u00a0whitespace\u00a0\u00bb est le \u00ab\u00a0nom convivial\u00a0\u00bb et existe \u00e0 des fins de documentation et pour votre sant\u00e9 mentale future.<\/li>\n\n\n\n<li>Comme pour la syntaxe des expressions r\u00e9guli\u00e8res, cela correspondra \u00e0 toute forme d&rsquo;espace blanc, de saut de ligne, de tabulation ou de retour chariot.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">La partie suivante de la r\u00e8gle de la variable correspond \u00e0 la cha\u00eene litt\u00e9rale \u00ab\u00a0AND\u00a0\u00bb. Difficile de faire plus simple.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ensuite, nous avons une autre r\u00e8gle d&rsquo;espacement, et enfin la r\u00e8gle Value.<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    Value &lt;- &#039;&quot;&#039; ValueChars* &#039;&quot;&#039;\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">Cette r\u00e8gle correspond \u00e0 la cha\u00eene litt\u00e9rale <code>'\"'<\/code>, \u00e0 z\u00e9ro ou plusieurs r\u00e8gles ValueChars, et enfin \u00e0 un autre guillemet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>ValueChars<\/code> ressemble \u00e0 ce qui suit\u00a0:<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    How we built a Lucene-inspired parser in Go\r\n\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">Ces <code>ValueChars<\/code> correspondront aux lettres minuscules et majuscules de l&rsquo;alphabet, \u00e0 n&rsquo;importe quel chiffre, aux espaces et au point d&rsquo;exclamation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pourquoi avoir d\u00e9fini Value de cette fa\u00e7on\u00a0? Parce que <b>la r\u00e8gle peut supprimer les guillemets doubles pour nous afin que nous n&rsquo;ayons pas \u00e0 le faire<\/b>, et puis nous sommes paresseux. Il ne s&rsquo;agit toutefois que d&rsquo;une commodit\u00e9 que nous aurions pu omettre au profit de l&rsquo;inclusion de la forme de la r\u00e8gle Value avec la d\u00e9finition de la r\u00e8gle de la variable.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Enfin, <code>AndVar<\/code> devrait vous para\u00eetre assez simple \u00e0 ce stade. Notez qu&rsquo;il fait r\u00e9f\u00e9rence \u00e0 Term et impl\u00e9mente le cycle susmentionn\u00e9.<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    ValueChars &lt;- [a-zA-Z0-9 !]\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">La d\u00e9finition compl\u00e8te ressemble \u00e0 ce qui suit.<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    Input &lt;- Term !.\r\nTerm &lt;- Variable AndVar*\r\nAndVar &lt;- _ &quot;AND&quot; _ Term\r\nVariable &lt;- FieldChars+ _ &quot;:&quot; _ Value\r\n_ &quot;whitespace&quot; &lt;- [ \\n\\t\\r]*\r\nValue &lt;- &#039;&quot;&#039; ValueChars &#039;&quot;&#039;\r\nFieldChars &lt;- [a-z]\r\nValueChars &lt;- [a-zA-Z0-9 !]\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<h2 class=\"wp-block-heading\">G\u00e9nial, et maintenant\u00a0?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">La v\u00e9ritable valeur de la d\u00e9finition de votre propre grammaire appara\u00eet lorsque vous fournissez des impl\u00e9mentations pour les actions des r\u00e8gles. Examinons la v\u00e9ritable d\u00e9finition PEG\u00a0:<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    {\r\n package main\r\n\r\n import (\r\n   &quot;strings&quot;\r\n )\r\n\r\n type Node interface {\r\n   Evaluate(input Event) (bool, error)\r\n }\r\n\r\n type Term struct {\r\n   node Node\r\n }\r\n\r\n func (t *Term) Evaluate(input Event) (bool, error) {\r\n   return t.node.Evaluate(input)\r\n }\r\n\r\n type AndNode struct {\r\n   Nodes []Node\r\n }\r\n\r\n func (n *AndNode) Evaluate(input Event) (bool, error) {\r\n   for _, node := range n.Nodes {\r\n     matched, err := node.Evaluate(input)\r\n     if err != nil {\r\n       return false, err\r\n     }\r\n     if !matched {\r\n       return false, nil\r\n     }\r\n   }\r\n   return true, nil\r\n }\r\n\r\n type Variable struct {\r\n   Field string\r\n   Value string\r\n }\r\n\r\n func (v *Variable) Evaluate(input Event) (bool, error) {\r\n   fieldVal, ok := input[v.Field]\r\n   if !ok {\r\n     return false, fmt.Errorf(&quot;Field &#039;%s&#039; not present in the event&quot;, v.Field)\r\n   }\r\n\r\n   return fieldVal == v.Value, nil\r\n }\r\n\r\n func toString(label interface{}) string {\r\n   var sb strings.Builder\r\n   value := label.([]interface{})\r\n   for _, i := range(value) {\r\n     if i == nil {\r\n       continue\r\n     }\r\n     switch b := i.(type) {\r\n     case []byte:\r\n       sb.WriteByte(b[0])\r\n     case []interface{}:\r\n       s := toString(i)\r\n       sb.WriteString(s)\r\n     default:\r\n       fmt.Printf(&quot;She&#039;s dead, Jim %T %+v\\n&quot;, i, i)\r\n     }\r\n   }\r\n   return sb.String()\r\n }\r\n}\r\n\r\nInput &lt;- Term !.\r\n\r\nTerm &lt;- variable:Variable rest:AndVar* {\r\n andVars := rest.([]interface{})\r\n variables := make([]Node, 0, len(andVars))\r\n variables = append(variables, variable.(Node))\r\n for _, r := range(andVars) {\r\n      variables = append(variables, r.(Node))\r\n   }\r\n   return &amp;AndNode{Nodes: variables}, nil\r\n}\r\n\r\nAndVar &lt;- _ &quot;AND&quot; _ rightSide:Term {\r\n   return rightSide, nil\r\n}\r\n\u200b\r\nVariable &lt;- field:FieldChars+ _ &quot;:&quot; _ value:Value {\r\n   return &amp;Variable{Field: toString(field), Value: toString(value)}, nil\r\n}\r\n\r\nValue &lt;- &#039;&quot;&#039; value:ValueChars* &#039;&quot;&#039; {\r\n   return value, nil\r\n}\r\n\r\n_ &quot;whitespace&quot; &lt;- [ \\n\\t\\r]*\r\nFieldChars &lt;- [a-z]\r\nValueChars &lt;- [a-zA-Z0-9 !]\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">Il y a beaucoup \u00e0 analyser ici, proc\u00e9dons \u00e9tape par \u00e9tape.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">En haut, nous avons une section de code entour\u00e9e d&rsquo;accolades. Il s&rsquo;agit d&rsquo;une convention de Pigeon qui prend le code inclus textuellement et l&rsquo;injecte dans la sortie de code g\u00e9n\u00e9r\u00e9e finale. Notez que vous pouvez d\u00e9finir ici les types pertinents pour votre grammaire par commodit\u00e9, ou les placer dans un autre fichier, car Pigeon utilisera le nom du package que vous d\u00e9clarez ici. Tout ce qui suit correspond \u00e0 la d\u00e9finition de la grammaire elle-m\u00eame.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u00c0 ce stade, vous avez probablement remarqu\u00e9 que les r\u00e8gles diff\u00e8rent un peu de la fa\u00e7on dont nous les avons d\u00e9finies plus haut. Jetons un \u0153il \u00e0 <code>Term<\/code>.<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    Term &lt;- variable:Variable rest:AndVar*\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">C&rsquo;est presque la m\u00eame d\u00e9finition de <code>Term<\/code> que pr\u00e9c\u00e9demment, mais nous l&rsquo;avons maintenant rendue utile. Le pr\u00e9fixage d&rsquo;une r\u00e8gle dans la d\u00e9finition par <code>name<\/code>\u00a0: attribue la valeur de retour de cette r\u00e8gle \u00e0 ce nom, puis transmet <code>name<\/code> \u00e0 la fonction d\u00e9finie par l&rsquo;action de votre r\u00e8gle lors de la g\u00e9n\u00e9ration du code. L&rsquo;int\u00e9gralit\u00e9 du code entre les accolades <b>devient une fonction associ\u00e9e \u00e0 cette r\u00e8gle <\/b>et est appel\u00e9e lorsque la r\u00e8gle est satisfaite\u00a0:<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    func (c *current) onTerm1(variable, rest interface{}) (interface{}, error) {\r\n andVars := rest.([]interface{})\r\n variables := make([]Node, 0, len(andVars))\r\n variables = append(variables, variable.(Node))\r\n for _, r := range andVars {\r\n   variables = append(variables, r.(Node))\r\n }\r\n return &amp;AndNode{Nodes: variables}, nil\r\n}\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">Ici, nous pouvons voir que Pigeon traite enti\u00e8rement avec des types d&rsquo;interface vides. C&rsquo;est excellent pour la flexibilit\u00e9, mais moins pratique pour l&rsquo;\u00e9criture de l&rsquo;impl\u00e9mentation car nous devons en tenir compte.<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    andVars := rest.([]interface{})\r\nvariables := make([]Node, 0, len(andVars))\r\nvariables = append(variables, variable.(Node))\r\nfor _, r := range andVars {\r\n variables = append(variables, r.(Node))\r\n}\r\nreturn &amp;AndNode{Nodes: variables}, nil\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">Comme mentionn\u00e9 pr\u00e9c\u00e9demment, <b>nous pouvons avoir des cycles dans les r\u00e8gles<\/b>. Compte tenu de cela, nous savons qu&rsquo;il est possible de recevoir un nombre infini de Termes mapp\u00e9s \u00e0 la variable <code>rest<\/code>. Pigeon g\u00e8re cela en nous donnant une tranche d&rsquo;interfaces vides. Nous avons cr\u00e9\u00e9 une interface <code>Node<\/code> dans laquelle tout doit \u00eatre inf\u00e9r\u00e9 avant de pouvoir les utiliser.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Apr\u00e8s avoir parcouru toute la liste des variables <code>AND<\/code>, nous cr\u00e9ons un <code>AndNode<\/code> contenant chacun des termes. La d\u00e9finition du AndNode se trouve dans la section litt\u00e9rale du code d\u00e9finie en haut de la PEG. En tant qu&rsquo;impl\u00e9mentation de l&rsquo;interface Node, elle d\u00e9finit une m\u00e9thode Evaluate qui indique que l&rsquo;expression est \u00e9valu\u00e9e \u00e0 vrai uniquement si tous les termes individuels le sont \u00e9galement.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u00c0 ce stade, le reste de la d\u00e9finition devrait \u00eatre compr\u00e9hensible, passons donc \u00e0 l&rsquo;ex\u00e9cution de l&rsquo;ensemble. Le listing de code suivant montre l&rsquo;analyse de notre r\u00e8gle, son utilisation, ainsi que quelques exemples suppl\u00e9mentaires pour illustrer les \u00e9checs et la gestion des erreurs\u00a0:<\/p>\n\n\n    <div data-content-type=\"longform\" class=\"code-snippet longform-spacings rounded-lg overflow-hidden shadow \" data-count=\"1\">\r\n        <ul class=\"nav nav-buttons code-snippet__tabs longform-except position-relative d-flex gap-2 flex-wrap p-3\" role=\"tablist\">\r\n\r\n                            \r\n                    \r\n                        <li class=\"nav-item\" role=\"presentation\">\r\n                            <button class=\"nav-link active\" data-bs-toggle=\"tab\" data-bs-target=\"#code_0\" type=\"button\" role=\"tab\" aria-controls=\"code_0\" aria-selected=\"true\">\r\n                                PHP                            <\/button>\r\n                        <\/li>\r\n\r\n                    \r\n                            \r\n        <\/ul>\r\n        <div class=\"code-snippet__tab-content tab-content\">\r\n\r\n                            \r\n                    <div class=\"tab-pane show active\" id=\"code_0\" role=\"tabpanel\" aria-labelledby=\"code_0\">\r\n                        <div class=\"code-snippet__code-wrapper\">\r\n                            <div class=\"nav nav-buttons code-snippet__copy-wrapper\">\r\n                                <button type=\"button\" class=\"nav-link code-snippet__copy\" data-clipboard-target=\"#code_0_content\" data-clipboard-label=\"Copier dans le presse-papiers\" data-clipboard-success-label=\"Copi\u00e9\u00a0!\" data-clipboard-error-label=\"Impossible de copier\" data-tooltip=\"Copier dans le presse-papiers\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copier dans le presse-papiers\">\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--default\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/file-stack.svg\"><\/svg>\r\n                                    <svg class=\"code-snippet__copy-icon code-snippet__copy-icon--success\" width=\"24\" height=\"24\" aria-hidden=\"true\" data-url=\"https:\/\/www.mailgun.com\/wp-content\/plugins\/sinch-core\/assets\/icons\/sinch\/badge-check.svg\"><\/svg>\r\n                                <\/button>\r\n                            <\/div>\r\n                            <pre class=\"w-100 h-100 m-0 line-numbers language-PHP\">\r\n                                <code id=\"code_0_content\" class=\"language-PHP\">\r\n\r\n                                    package main\r\n\r\nimport (\r\n &quot;fmt&quot;\r\n)\r\n\r\ntype Event map[string]string\r\n\r\nfunc Match(rule string, event Event) (bool, error) {\r\n \/\/ Parse is generated by pigeon in this package\r\n tree, err := Parse(&quot;parsing&quot;, []byte(rule))\r\n if err != nil {\r\n   return false, err\r\n }\r\n\r\n \/\/ Yes, this is a bit ugly. It&#039;s a consequence of pigeon dealing in interface slices\r\n iface, ok := tree.([]interface{})\r\n if !ok {\r\n   return false, fmt.Errorf(&quot;Internal Error&quot;)\r\n }\r\n\r\n ast, ok := iface[0].(Node)\r\n if !ok {\r\n   return false, fmt.Errorf(&quot;Internal Error&quot;)\r\n }\r\n\r\n \/\/ ast is the tree generated by our supplementary Go defined by the production rules\r\n return ast.Evaluate(event)\r\n}\r\n\r\nfunc main() {\r\n  rules := []string{\r\n   &quot;event:\\&quot;sent\\&quot; AND subject:\\&quot;A special offer just for you!\\&quot;&quot;,\r\n   &quot;event:\\&quot;found\\&quot; AND subject:\\&quot;A special offer just for you!\\&quot;&quot;,\r\n   &quot;event:\\&quot;sent\\&quot; AND badfield:\\&quot;A special offer just for you!\\&quot;&quot;,\r\n  }\r\n\r\n  event := map[string]string{\r\n    &quot;event&quot;:   &quot;sent&quot;,\r\n    &quot;subject&quot;: &quot;A special offer just for you!&quot;,\r\n    &quot;account&quot;: &quot;12345&quot;,\r\n  }\r\n\r\n  for _, rule := range rules {\r\n    matched, err := Match(rule, Event(event))\r\n    if err != nil {\r\n      fmt.Printf(&quot;Rule &#039;%s&#039; failed with error &#039;%s&#039;\\n&quot;, rule, err.Error())\r\n    } else {\r\n      fmt.Printf(&quot;Rule &#039;%s&#039; matched: %t\\n&quot;, rule, matched)\r\n    }\r\n  }\r\n}\r\n                                <\/code>\r\n                            <\/pre>\r\n                        <\/div>\r\n                    <\/div>\r\n                                    <\/div>\r\n    <\/div>\r\n\n\n\n<p class=\"wp-block-paragraph\">Il vous suffit d&rsquo;ex\u00e9cuter\u00a0:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>~&gt; go get\u00a0<\/code><a href=\"https:\/\/github.com\/mna\/pigeon\"><code>github.com\/mna\/pigeon<\/code><\/a><code>\u00a0\u00a0 ~&gt; pigeon rules.peg &gt; rules.go \u00a0 ~&gt; go run . Rule 'event:\"sent\" AND subject:\"A special offer just for you!\"' matched: true Rule 'event:\"found\" AND subject:\"A special offer just for you!\"' matched: false Rule 'event:\"sent\" AND badfield:\"A special offer just for you!\"' failed with error 'Field 'badfield' not present in the event'<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00e9licitations ! <b>Vous avez maintenant \u00e9crit votre propre langage \u00e0 l&rsquo;utilit\u00e9 extr\u00eamement limit\u00e9e\u00a0!<\/b><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Consid\u00e9rations<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u00c0 ce stade, vous vous dites peut-\u00eatre\u00a0:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Beaucoup d&rsquo;exp\u00e9diteurs n&rsquo;utilisent-ils pas des objets de ce genre\u00a0?<\/li>\n\n\n\n<li>Un moteur de r\u00e8gles qui ne fait correspondre que des cha\u00eenes litt\u00e9rales est-il vraiment si utile\u00a0?<\/li>\n\n\n\n<li>Cet article n&rsquo;aurait-il pas pu \u00eatre deux fois plus court\u00a0?<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Ce \u00e0 quoi nous r\u00e9pondrions\u00a0:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Nous voudrions impl\u00e9menter une sorte de traitement pour le champ <code>account<\/code> tel que d\u00e9fini dans l&rsquo;\u00e9v\u00e9nement d&rsquo;origine. Mailgun r\u00e9sout ce probl\u00e8me en incluant une logique m\u00e9tier dans la base de code pour prendre en charge la limitation de d\u00e9bit bas\u00e9e sur un champ d\u00e9fini. En d&rsquo;autres termes, nous pouvons dire\u00a0: \u00ab\u00a0Si cette r\u00e8gle correspond, enregistrez le compte et l&rsquo;heure actuelle et n&rsquo;effectuez pas cette action pour ce compte pendant les N prochaines minutes.\u00a0\u00bb \u00c9videmment, si nous n&rsquo;avions pas cette gestion et que l&rsquo;exp\u00e9diteur en question envoyait un million d&#8217;emails, le support serait notifi\u00e9 un million de fois. Ce serait un excellent moyen de noyer votre \u00e9quipe de support sous le bruit et de vous faire agresser sur le parking apr\u00e8s le travail.<\/li>\n\n\n\n<li>On pourrait impl\u00e9menter des r\u00e8gles pour analyser des expressions r\u00e9guli\u00e8res et des sous-cha\u00eenes qui seraient bien plus utiles qu&rsquo;une correspondance de cha\u00eene explicite. C&rsquo;est d&rsquo;ailleurs exactement ce que nous avons fait.<\/li>\n\n\n\n<li>D\u00e9sol\u00e9.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Enfin, vous avez probablement remarqu\u00e9 que nous n&rsquo;avons pas d\u00e9fini ce que la r\u00e8gle ferait ici lorsqu&rsquo;elle correspond <i>effectivement<\/i>. L&rsquo;une des solutions possibles est de faire en sorte que la r\u00e8gle publie sur un canal Slack lorsqu&rsquo;elle est d\u00e9clench\u00e9e. Il s&rsquo;agit d&rsquo;une solution courante ici chez Mailgun, et elle se pr\u00e9sente comme suit\u00a0:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>slack:#channel-name<\/code><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prochaines \u00e9tapes<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u00c0 ce stade, nous esp\u00e9rons que votre esprit foisonne de possibilit\u00e9s. Voici quelques r\u00e9flexions que nous avons eues\u00a0:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Il y a bien plus \u00e0 \u00e9muler dans la syntaxe Lucene, comme les op\u00e9rateurs NOT et OR, ou les parenth\u00e8ses.<\/li>\n\n\n\n<li>Fournir une grammaire s\u00e9par\u00e9e pour les actions.<\/li>\n\n\n\n<li>Impl\u00e9menter la cr\u00e9ation de mod\u00e8les pour injecter des valeurs de l&rsquo;\u00e9v\u00e9nement dans l&rsquo;action.<\/li>\n\n\n\n<li>Ajouter du sucre syntaxique pour faciliter l&rsquo;\u00e9criture de certains filtres.<\/li>\n\n\n\n<li>Impl\u00e9menter un syst\u00e8me pour compter et r\u00e9agir \u00e0 un nombre sp\u00e9cifique d&rsquo;occurrences d&rsquo;\u00e9v\u00e9nements sur une p\u00e9riode donn\u00e9e.<\/li>\n\n\n\n<li>Impl\u00e9menter un cache, car l&rsquo;analyse des r\u00e8gles est quelque peu co\u00fbteuse.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Il y a beaucoup d&rsquo;autres choses que vous pouvez faire, en particulier lorsqu&rsquo;il s&rsquo;agit d&rsquo;\u00e9toffer l&rsquo;analyseur d&rsquo;actions. <b>Vous pourriez appeler d&rsquo;autres services, notifier des clients, allumer ou \u00e9teindre les lumi\u00e8res, et bien plus encore.<\/b> Lorsqu&rsquo;il s&rsquo;agit d&rsquo;inventer vos propres outils sur cette base, il n&rsquo;y a pas de limites.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Avantages et inconv\u00e9nients<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u00c0 ce stade, vous vous demandez peut-\u00eatre\u00a0: \u00ab\u00a0Pourquoi n&rsquo;ont-ils pas utilis\u00e9 $SOME_OTHER_TOOL\u00a0?\u00a0\u00bb\u00a0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">La r\u00e9ponse est que nous n&rsquo;avons pas encore besoin de la puissance de ces outils, ni de la complexit\u00e9 qui accompagne souvent leur exploitation. Notre outil actuel de traitement de flux est un simple binaire unique d\u00e9ploy\u00e9 dans un conteneur, qui fonctionne tout simplement (Just Works\u2122). Il y a tr\u00e8s peu de choses \u00e0 g\u00e9rer et il suit facilement notre flux d&rsquo;\u00e9v\u00e9nements \u00e0 tr\u00e8s haut volume.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Avantages\u00a0:<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>C&rsquo;est facile \u00e0 d\u00e9velopper<\/li>\n\n\n\n<li>Il utilise toujours des outils open source et pr\u00eats \u00e0 l&#8217;emploi<\/li>\n\n\n\n<li>Il peut \u00eatre adapt\u00e9 exactement \u00e0 nos besoins<\/li>\n\n\n\n<li>La syntaxe de notre DSL est minuscule, facile \u00e0 articuler et \u00e0 comprendre, et elle oblige tout le monde \u00e0 \u00e9crire les r\u00e8gles \u00e0 peu pr\u00e8s de la m\u00eame mani\u00e8re. Elle rend \u00e9galement plus difficile la cr\u00e9ation d&rsquo;effets secondaires ind\u00e9sirables<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Inconv\u00e9nients\u00a0:<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Les fonctionnalit\u00e9s du langage qui vont au-del\u00e0 de ce que nous avons d\u00e9j\u00e0 impl\u00e9ment\u00e9 repr\u00e9sentent un saut substantiel en mati\u00e8re de complexit\u00e9.<\/li>\n\n\n\n<li>La mise \u00e0 jour de la PEG source g\u00e9n\u00e9rera un nouveau code, et cela perturbe vraiment vos diffs de code.<\/li>\n\n\n\n<li>La simplicit\u00e9 d\u00e9lib\u00e9r\u00e9e de Lucene peut rendre difficile l&rsquo;\u00e9criture de r\u00e8gles plus complexes.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Nous finirons peut-\u00eatre par d\u00e9cider que $SOME_OTHER_TOOL est plus adapt\u00e9 \u00e0 nos besoins, mais dans un avenir pr\u00e9visible, <b>la puissance que notre DSL Mailgun apporte est plus que suffisante.<\/b><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">La fin, enfin<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u00c0 ce stade, nous esp\u00e9rons avoir d\u00e9montr\u00e9 en quoi l&rsquo;\u00e9criture de votre propre DSL peut s&rsquo;av\u00e9rer utile. Notre impl\u00e9mentation traite un nombre consid\u00e9rable d&rsquo;\u00e9v\u00e9nements par jour tout en facilitant grandement la vie de nombreux membres de notre \u00e9quipe (du moins, c&rsquo;est ce que nous leur disons).\u00a0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quant aux fonctionnalit\u00e9s qu&rsquo;il prend en charge, <b>nous ne faisons que commencer<\/b>. Si cela vous a inspir\u00e9 et que vous souhaitez impl\u00e9menter votre propre grammaire de traitement de flux, n&rsquo;h\u00e9sitez pas \u00e0 nous le faire savoir. Nous serions ravis d&rsquo;en entendre parler\u00a0!<\/p>\n\n\n\r\n    <aside data-content-type=\"longform\"  class=\"banner-block longform-spacings rounded-lg shadow-lg px-5 py-6 px-md-6 py-md-7 p-lg-7 bg-light\" data-theme=\"dark\" aria-labelledby=\"banner-block-block_91436b1e60ccbb2f99a53ea291672375\">\r\n                    <p class=\"text-uppercase section-caption text-body-color\">\r\n                S&rsquo;inscrire            <\/p>\r\n                            <p class=\"h4 text-accent fw-bold\" id=\"banner-block-block_91436b1e60ccbb2f99a53ea291672375\">\r\n                Lancez-vous, c&rsquo;est facile ! Et c&rsquo;est gratuit.            <\/p>\r\n                            <div class=\"mb-0 text-body-color\">\r\n                                    <div class=\"content-body mb-0 text-body-color\">D\u00e9couvrez ce que vous pouvez accomplir avec la meilleure plateforme de livraison d\u2019emails au monde.<\/div>\r\n                            <\/div>\r\n        \r\n        <div class=\"text-start mt-5\"><a href=\"https:\/\/signup.mailgun.com\/new\/signup\"  class=\"btn btn-secondary\" >Get started<\/a><\/div>\r\n    <\/aside>\r\n\r\n","protected":false},"excerpt":{"rendered":"<p>Chez Mailgun, nous avons de nombreux syst\u00e8mes qui g\u00e9n\u00e8rent une tonne d&rsquo;\u00e9v\u00e9nements \u00e0 chaque heure de la journ\u00e9e. C&rsquo;est un nombre si important qu&rsquo;il est impossible pour une \u00e9quipe de trier les r\u00e9sultats ElasticSearch et d&rsquo;esp\u00e9rer obtenir des r\u00e9sultats coh\u00e9rents, ou m\u00eame de garder toute sa t\u00eate.<\/p>\n","protected":false},"author":62,"featured_media":4843,"menu_order":0,"template":"","meta":{"_acf_changed":true,"footnotes":""},"blog_category":[23],"class_list":["post-24704","blog","type-blog","status-publish","has-post-thumbnail","hentry","blog_category-it-and-engineering"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Comment nous avons cr\u00e9\u00e9 un analyseur inspir\u00e9 de Lucene en GoLang - Transactional Email API Service For Developers | Mailgun<\/title>\n<meta name=\"description\" content=\"Nous sommes fiers de faire beaucoup avec tr\u00e8s peu, nous avons donc cherch\u00e9 \u00e0 voir comment les filtres en temps r\u00e9el pouvaient fonctionner pour nous. En savoir plus \u2013\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/comment-nous-avons-cree-analyseur-inspire-lucene-go\/\" \/>\n<meta property=\"og:locale\" content=\"fr_FR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Comment nous avons cr\u00e9\u00e9 un analyseur inspir\u00e9 de Lucene en GoLang - Transactional Email API Service For Developers | Mailgun\" \/>\n<meta property=\"og:description\" content=\"Nous sommes fiers de faire beaucoup avec tr\u00e8s peu, nous avons donc cherch\u00e9 \u00e0 voir comment les filtres en temps r\u00e9el pouvaient fonctionner pour nous. En savoir plus \u2013\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/comment-nous-avons-cree-analyseur-inspire-lucene-go\/\" \/>\n<meta property=\"og:site_name\" content=\"Transactional Email API Service For Developers | Mailgun\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-IT-Engineering.png\" \/>\n\t<meta property=\"og:image:width\" content=\"720\" \/>\n\t<meta property=\"og:image:height\" content=\"448\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/it-and-engineering\\\/comment-nous-avons-cree-analyseur-inspire-lucene-go\\\/\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/it-and-engineering\\\/comment-nous-avons-cree-analyseur-inspire-lucene-go\\\/\",\"name\":\"Comment nous avons cr\u00e9\u00e9 un analyseur inspir\u00e9 de Lucene en GoLang - Transactional Email API Service For Developers | Mailgun\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/it-and-engineering\\\/comment-nous-avons-cree-analyseur-inspire-lucene-go\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/it-and-engineering\\\/comment-nous-avons-cree-analyseur-inspire-lucene-go\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/MG-Blog-IT-Engineering.png\",\"datePublished\":\"2026-09-16T16:57:06+00:00\",\"description\":\"Nous sommes fiers de faire beaucoup avec tr\u00e8s peu, nous avons donc cherch\u00e9 \u00e0 voir comment les filtres en temps r\u00e9el pouvaient fonctionner pour nous. En savoir plus \u2013\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/it-and-engineering\\\/comment-nous-avons-cree-analyseur-inspire-lucene-go\\\/#breadcrumb\"},\"inLanguage\":\"fr-FR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/it-and-engineering\\\/comment-nous-avons-cree-analyseur-inspire-lucene-go\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/it-and-engineering\\\/comment-nous-avons-cree-analyseur-inspire-lucene-go\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/MG-Blog-IT-Engineering.png\",\"contentUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/MG-Blog-IT-Engineering.png\",\"width\":720,\"height\":448},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/it-and-engineering\\\/comment-nous-avons-cree-analyseur-inspire-lucene-go\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Blog\",\"item\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Comment nous avons cr\u00e9\u00e9 un analyseur inspir\u00e9 de Lucene en Go\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/#website\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/\",\"name\":\"Transactional Email API Service For Developers | Mailgun\",\"description\":\"Des API d\u2019emails transactionnels puissantes qui vous permettent d'envoyer, de recevoir et de suivre des emails, con\u00e7ues pour les d\u00e9veloppeurs. En savoir plus d\u00e8s aujourd'hui !\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"fr-FR\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/#organization\",\"name\":\"Transactional Email API Service For Developers | Mailgun\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"fr-FR\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/cropped-android-chrome-512x512-1.png\",\"contentUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/cropped-android-chrome-512x512-1.png\",\"width\":512,\"height\":512,\"caption\":\"Transactional Email API Service For Developers | Mailgun\"},\"image\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/fr\\\/#\\\/schema\\\/logo\\\/image\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Comment nous avons cr\u00e9\u00e9 un analyseur inspir\u00e9 de Lucene en GoLang - Transactional Email API Service For Developers | Mailgun","description":"Nous sommes fiers de faire beaucoup avec tr\u00e8s peu, nous avons donc cherch\u00e9 \u00e0 voir comment les filtres en temps r\u00e9el pouvaient fonctionner pour nous. En savoir plus \u2013","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/comment-nous-avons-cree-analyseur-inspire-lucene-go\/","og_locale":"fr_FR","og_type":"article","og_title":"Comment nous avons cr\u00e9\u00e9 un analyseur inspir\u00e9 de Lucene en GoLang - Transactional Email API Service For Developers | Mailgun","og_description":"Nous sommes fiers de faire beaucoup avec tr\u00e8s peu, nous avons donc cherch\u00e9 \u00e0 voir comment les filtres en temps r\u00e9el pouvaient fonctionner pour nous. En savoir plus \u2013","og_url":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/comment-nous-avons-cree-analyseur-inspire-lucene-go\/","og_site_name":"Transactional Email API Service For Developers | Mailgun","og_image":[{"width":720,"height":448,"url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-IT-Engineering.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/comment-nous-avons-cree-analyseur-inspire-lucene-go\/","url":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/comment-nous-avons-cree-analyseur-inspire-lucene-go\/","name":"Comment nous avons cr\u00e9\u00e9 un analyseur inspir\u00e9 de Lucene en GoLang - Transactional Email API Service For Developers | Mailgun","isPartOf":{"@id":"https:\/\/www.mailgun.com\/fr\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/comment-nous-avons-cree-analyseur-inspire-lucene-go\/#primaryimage"},"image":{"@id":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/comment-nous-avons-cree-analyseur-inspire-lucene-go\/#primaryimage"},"thumbnailUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-IT-Engineering.png","datePublished":"2026-09-16T16:57:06+00:00","description":"Nous sommes fiers de faire beaucoup avec tr\u00e8s peu, nous avons donc cherch\u00e9 \u00e0 voir comment les filtres en temps r\u00e9el pouvaient fonctionner pour nous. En savoir plus \u2013","breadcrumb":{"@id":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/comment-nous-avons-cree-analyseur-inspire-lucene-go\/#breadcrumb"},"inLanguage":"fr-FR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/comment-nous-avons-cree-analyseur-inspire-lucene-go\/"]}]},{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/comment-nous-avons-cree-analyseur-inspire-lucene-go\/#primaryimage","url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-IT-Engineering.png","contentUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-IT-Engineering.png","width":720,"height":448},{"@type":"BreadcrumbList","@id":"https:\/\/www.mailgun.com\/fr\/blog\/it-and-engineering\/comment-nous-avons-cree-analyseur-inspire-lucene-go\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.mailgun.com\/fr\/"},{"@type":"ListItem","position":2,"name":"Blog","item":"https:\/\/www.mailgun.com\/fr\/blog\/"},{"@type":"ListItem","position":3,"name":"Comment nous avons cr\u00e9\u00e9 un analyseur inspir\u00e9 de Lucene en Go"}]},{"@type":"WebSite","@id":"https:\/\/www.mailgun.com\/fr\/#website","url":"https:\/\/www.mailgun.com\/fr\/","name":"Transactional Email API Service For Developers | Mailgun","description":"Des API d\u2019emails transactionnels puissantes qui vous permettent d'envoyer, de recevoir et de suivre des emails, con\u00e7ues pour les d\u00e9veloppeurs. En savoir plus d\u00e8s aujourd'hui !","publisher":{"@id":"https:\/\/www.mailgun.com\/fr\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.mailgun.com\/fr\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"fr-FR"},{"@type":"Organization","@id":"https:\/\/www.mailgun.com\/fr\/#organization","name":"Transactional Email API Service For Developers | Mailgun","url":"https:\/\/www.mailgun.com\/fr\/","logo":{"@type":"ImageObject","inLanguage":"fr-FR","@id":"https:\/\/www.mailgun.com\/fr\/#\/schema\/logo\/image\/","url":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/06\/cropped-android-chrome-512x512-1.png","contentUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/06\/cropped-android-chrome-512x512-1.png","width":512,"height":512,"caption":"Transactional Email API Service For Developers | Mailgun"},"image":{"@id":"https:\/\/www.mailgun.com\/fr\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/blog\/24704","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/types\/blog"}],"author":[{"embeddable":true,"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/users\/62"}],"version-history":[{"count":0,"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/blog\/24704\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/media\/4843"}],"wp:attachment":[{"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/media?parent=24704"}],"wp:term":[{"taxonomy":"blog_category","embeddable":true,"href":"https:\/\/www.mailgun.com\/fr\/wp-json\/wp\/v2\/blog_category?post=24704"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}