{"id":24793,"date":"2026-09-16T17:51:41","date_gmt":"2026-09-16T17:51:41","guid":{"rendered":"https:\/\/www.mailgun.com\/blog\/como-criamos-um-parser-inspirado-no-lucene-em-go\/"},"modified":"2026-09-16T17:51:41","modified_gmt":"2026-09-16T17:51:41","slug":"como-criamos-um-parser-inspirado-no-lucene-em-go","status":"publish","type":"blog","link":"https:\/\/www.mailgun.com\/pt\/blog\/it-and-engineering\/como-criamos-um-parser-inspirado-no-lucene-em-go\/","title":{"rendered":"Como criamos um parser inspirado no Lucene em Go"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Na Mailgun, temos v\u00e1rios sistemas gerando uma enorme quantidade de eventos a cada hora do dia. \u00c9 um n\u00famero t\u00e3o grande que \u00e9 imposs\u00edvel para uma equipe classificar os resultados do ElasticSearch e esperar resultados consistentes, ou at\u00e9 mesmo manter a sanidade.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Como muitas empresas, <b>ainda precisamos encontrar uma maneira de lidar com todos os dados<\/b>. Isso cria uma tarefa substancial: criar um sistema que permita aos nossos clientes internos reagir a eventos em tempo real.<\/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-1753\"><p class=\"h5 m-0\" id=\"toc-title-1753\">\u00cdndice<\/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=\"#brainstorming\">Brainstorming<\/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=\"#entrando-na-gramatica\">Entrando na gram\u00e1tica<\/a><a class=\"scrollme link-body-color\" href=\"#gramaticas-livres-de-contexto-e-gramaticas-de-expressao-de-analise\">Gram\u00e1ticas livres de contexto e gram\u00e1ticas de express\u00e3o de an\u00e1lise<\/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=\"#levantando-voo\">Levantando voo<\/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=\"#como-uma-folha-ao-vento\">Como uma folha ao vento<\/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=\"#legal-mas-e-agora\">Legal, mas e agora?<\/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=\"#consideracoes\">Considera\u00e7\u00f5es<\/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=\"#proximos-passos\">Pr\u00f3ximos passos<\/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=\"#pros-e-contras\">Pr\u00f3s e contras<\/a><a class=\"scrollme link-body-color\" href=\"#pros\">Pr\u00f3s:<\/a><a class=\"scrollme link-body-color\" href=\"#contras\">Contras:<\/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=\"#o-fim-finalmente\">O fim, finalmente<\/a><\/div><\/div><\/nav>\n\n\n<p class=\"wp-block-paragraph\">Tradicionalmente, as op\u00e7\u00f5es para resolver esse problema incluem:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Inserir os dados em um banco de dados e, em seguida, executar consultas de banco de dados, muitas vezes em um intervalo de tempo fixo<\/li>\n\n\n\n<li>Solu\u00e7\u00f5es map-reduce, como o Hadoop<\/li>\n\n\n\n<li>Mechanical Turk \u00a0<\/li>\n\n\n\n<li>Filtros em tempo real.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Temos orgulho de fazer muito com muito pouco, ent\u00e3o decidimos ver como poder\u00edamos fazer os filtros em tempo real funcionarem para n\u00f3s. Focamos em construir um sistema que permita essencialmente a qualquer pessoa nas equipes de engenharia e suporte <b>escrever regras que reajam e executem a\u00e7\u00f5es em seu nome.<\/b><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Brainstorming<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ao projetar esse sistema, tentamos construir algo que desse a todo mundo as ferramentas para iterar e responder rapidamente a amea\u00e7as ao nosso sistema, e que tivesse de estar em conformidade com as seguintes regras:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Os usu\u00e1rios devem poder adicionar as pr\u00f3prias regras \u00e0 vontade<\/li>\n\n\n\n<li>A linguagem de dom\u00ednio espec\u00edfico, doravante chamada de DSL, deve ser o mais simples poss\u00edvel e, de prefer\u00eancia, se parecer com algo que j\u00e1 conhecem.<\/li>\n\n\n\n<li>As pessoas devem poder testar as pr\u00f3prias regras nos dados hist\u00f3ricos antes de aplic\u00e1-las.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Usamos o Kibana internamente, <b>ent\u00e3o algo que pudesse ser testado nele para cumprir o ponto n\u00famero tr\u00eas seria o ideal<\/b>. Isso nos leva a uma conclus\u00e3o direta: devemos escrever um parser de DSL inspirado no Lucene!\u00a0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A primeira itera\u00e7\u00e3o do sistema dependia de express\u00f5es regulares e muito parsing de caractere por caractere. Isso resolveu o problema, mas as itera\u00e7\u00f5es subsequentes cresceram rapidamente em complexidade. Se voc\u00ea j\u00e1 fez algum grande projeto de parsing de strings, sabe do que estamos falando.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Seguindo em frente, <b>sab\u00edamos que t\u00ednhamos de construir algo que pudesse ser iterado rapidamente<\/b> e que, idealmente, estivesse em conformidade com um padr\u00e3o conhecido.<\/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_2081454ff48e7bffff4f62056d48399c\">\r\n                    <p class=\"text-uppercase section-caption text-body-color\">\r\n                Cadastre-se            <\/p>\r\n                            <p class=\"h4 text-accent fw-bold\" id=\"banner-block-block_2081454ff48e7bffff4f62056d48399c\">\r\n                \u00c9 f\u00e1cil come\u00e7ar. E \u00e9 gr\u00e1tis.            <\/p>\r\n                            <div class=\"mb-0 text-body-color\">\r\n                                    <div class=\"content-body mb-0 text-body-color\">Veja o que voc\u00ea pode alcan\u00e7ar com a melhor plataforma de entrega de e-mail do mundo.<\/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\">Entrando na gram\u00e1tica<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Quem de n\u00f3s j\u00e1 fez cursos universit\u00e1rios de Teoria dos Aut\u00f4matos e afins provavelmente se lembra das gram\u00e1ticas no contexto das linguagens de programa\u00e7\u00e3o. Al\u00e9m disso, \u00e9 certo que algumas pessoas lendo isso ter\u00e3o muito mais conhecimento do que este humilde autor no assunto, ent\u00e3o deixe as explica\u00e7\u00f5es mais aprofundadas para o seu mecanismo de busca preferido.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ainda assim, \u00e9 \u00fatil falar brevemente sobre o que comp\u00f5e uma gram\u00e1tica e a sua utilidade. Citando a Wikip\u00e9dia, uma <a href=\"https:\/\/en.wikipedia.org\/wiki\/Formal_grammar\" target=\"_tabs\" rel=\"noopener noreferrer\">Gram\u00e1tica Formal<\/a> \u00e9 &#8220;&#8230;um conjunto de regras de produ\u00e7\u00e3o para cadeias de caracteres (strings) em uma linguagem formal. <b>As regras descrevem como formar strings a partir do alfabeto da linguagem que sejam v\u00e1lidas de acordo com a sintaxe da linguagem<\/b>. Uma gram\u00e1tica n\u00e3o descreve o significado das strings nem o que pode ser feito com elas em qualquer contexto \u2014 apenas a sua forma.&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Correndo o risco de simplificar demais, isso nos permite pegar uma string como &#8220;Voc\u00ea tem um e-mail!&#8221; e dividi-la em tokens que podemos analisar semanticamente. Em outras palavras, se a nossa gram\u00e1tica estiver bem definida, podemos escrever um c\u00f3digo adicional para determinar o significado dessa string.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A hist\u00f3ria e os tipos de gram\u00e1ticas dariam para preencher muitos livros e, portanto, v\u00e3o muito al\u00e9m do escopo de um post de blog. Em vez disso, vamos nos concentrar nas <b>gram\u00e1ticas livres de contexto<\/b> e, mais especificamente, nas gram\u00e1ticas de express\u00e3o de an\u00e1lise (parsing expression grammars).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Gram\u00e1ticas livres de contexto e gram\u00e1ticas de express\u00e3o de an\u00e1lise<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Citando a Wikip\u00e9dia novamente, uma<a href=\"https:\/\/en.m.wikipedia.org\/wiki\/Context-free_grammar\" target=\"_tabs\" rel=\"noopener noreferrer\"> Gram\u00e1tica livre de contexto<\/a> \u00e9 &#8220;um determinado tipo de gram\u00e1tica formal: um conjunto de regras de produ\u00e7\u00e3o que descrevem todas as strings poss\u00edveis em uma determinada linguagem formal. As regras de produ\u00e7\u00e3o s\u00e3o simples substitui\u00e7\u00f5es.&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dito de outra forma, uma gram\u00e1tica livre de contexto <b>define um grafo que, por sua vez, define como analisar sintaticamente (fazer o parse de) uma linguagem<\/b>. Conforme mencionado acima, ela <i>n\u00e3o <\/i>nos diz como entender a linguagem. Tamb\u00e9m vale a pena mencionar, como veremos abaixo, que o grafo pode ter ciclos, mas acaba terminando.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As gram\u00e1ticas livres de contexto t\u00eam uma esp\u00e9cie de prima na<a href=\"https:\/\/en.m.wikipedia.org\/wiki\/Parsing_expression_grammar\" target=\"_tabs\" rel=\"noopener noreferrer\"> Parsing Expression Grammar<\/a>, ou PEG. Elas se <i>parecem<\/i> muito com uma gram\u00e1tica livre de contexto (ou CFG, na sigla em ingl\u00eas), mas trazem uma distin\u00e7\u00e3o muito \u00fatil: ao se deparar com uma escolha amb\u00edgua, a PEG sempre escolher\u00e1 a primeira regra de produ\u00e7\u00e3o definida. Por outro lado, a CFG deixa a escolha amb\u00edgua, e por que nos preocuparmos com a ambiguidade se n\u00e3o somos obrigados?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">O que isso realmente significa \u00e9 que <b>\u00e9 mais f\u00e1cil criar ferramentas para definir as PEGs<\/b>. Felizmente, muitas pessoas j\u00e1 fizeram isso por n\u00f3s.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Levantando voo<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Depois de algumas pesquisas, escolhemos o <a href=\"https:\/\/github.com\/mna\/pigeon\" target=\"_tabs\" rel=\"noopener noreferrer\">Pigeon<\/a> como base da nossa PEG. O Pigeon segue o mesmo paradigma de muitas ferramentas de Go, gerando um c\u00f3digo que \u00e9 compilado junto com o seu programa.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">O seu uso \u00e9 bastante simples: voc\u00ea define tanto a gram\u00e1tica quanto o c\u00f3digo em Go para processar cada uma das regras no mesmo pacote, e simplesmente chama Parse() no parser gerado. O desafio \u00e9 escrever handlers para cada uma dessas regras. Assim como as gram\u00e1ticas, o tema da compila\u00e7\u00e3o daria para preencher uma biblioteca de livros. Felizmente para n\u00f3s, <b>escrever um interpretador \u00e9 menos complexo<\/b> e o c\u00f3digo resultante \u00e9 suficientemente r\u00e1pido para as nossas necessidades.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Al\u00e9m disso, a sintaxe procura se alinhar ao m\u00e1ximo com a pr\u00f3pria sintaxe do Go, o que facilita na hora de escrever a sua PEG junto com o seu programa em Go utilizando a gram\u00e1tica.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Como uma folha ao vento<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Digamos que voc\u00ea tenha um evento gerado pelo envio de um e-mail, codificado em JSON, com a seguinte apar\u00eancia:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>{<br>\n\u00a0\"event\": \"sent\",<br>\n\u00a0\"subject\": \"Uma oferta especial s\u00f3 para voc\u00ea!\",<br>\n\u00a0\"account\": \"12345\",<br>\n}<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">H\u00e1 algumas maneiras de analisar esse evento: voc\u00ea pode decidir que se trata de um e-mail inofensivo, ou dizer &#8220;Isso pode ser spam, mas n\u00e3o h\u00e1 informa\u00e7\u00f5es suficientes para decidir&#8221;. Esse \u00e9 um problema muito comum no nosso sistema e sempre exige muitos dados agregados para chegarmos a uma conclus\u00e3o.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Portanto, vamos escrever uma regra que corresponda ao evento acima:<\/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=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-clipboard-success-label=\"Copiado!\" data-clipboard-error-label=\"N\u00e3o foi poss\u00edvel copiar\" data-tooltip=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copiar para a \u00e1rea de transfer\u00eancia\">\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\">Isso \u00e9 bem f\u00e1cil de analisar sintaticamente e, melhor ainda, tamb\u00e9m pode ser verificado no Kibana!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Agora vamos <b>construir uma PEG muito simples <\/b>que corresponderia a essa regra. Implementaremos cada regra de produ\u00e7\u00e3o, uma de cada vez, e explicaremos o que ela faz. Os nomes das regras normalmente seguem o padr\u00e3o<a href=\"https:\/\/en.wikipedia.org\/wiki\/Pascal_(programming_language)#Language_constructs\" target=\"_tabs\" rel=\"noopener noreferrer\"> PascalCase<\/a> e permitem o uso de n\u00fameros e underlines. Cada regra adota a seguinte forma:<\/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=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-clipboard-success-label=\"Copiado!\" data-clipboard-error-label=\"N\u00e3o foi poss\u00edvel copiar\" data-tooltip=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copiar para a \u00e1rea de transfer\u00eancia\">\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\">Note que, na verdade, h\u00e1 v\u00e1rios caracteres v\u00e1lidos para o operador de defini\u00e7\u00e3o de regra, mas gostamos de &lt;-, pois \u00e9 f\u00e1cil de digitar e se parece mais com as gram\u00e1ticas definidas academicamente.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A primeira regra na gram\u00e1tica \u00e9 tratada como o ponto de entrada:<\/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=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-clipboard-success-label=\"Copiado!\" data-clipboard-error-label=\"N\u00e3o foi poss\u00edvel copiar\" data-tooltip=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copiar para a \u00e1rea de transfer\u00eancia\">\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\">A nossa regra <code>Input<\/code> diz &#8220;Corresponder a toda a string de entrada&#8221; com <code>!.<\/code> que significa &#8220;Corresponder ao final do arquivo&#8221;. Isso passar\u00e1 toda a string de entrada para uma regra chamada Term, com a seguinte apar\u00eancia:<\/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=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-clipboard-success-label=\"Copiado!\" data-clipboard-error-label=\"N\u00e3o foi poss\u00edvel copiar\" data-tooltip=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copiar para a \u00e1rea de transfer\u00eancia\">\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\">Isso passa o fluxo de controle para a regra de produ\u00e7\u00e3o Variable:<\/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=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-clipboard-success-label=\"Copiado!\" data-clipboard-error-label=\"N\u00e3o foi poss\u00edvel copiar\" data-tooltip=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copiar para a \u00e1rea de transfer\u00eancia\">\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\">Agora est\u00e1 ficando um pouco mais complexo. Primeiro, correspondemos todos os caracteres de forma gananciosa at\u00e9 que a regra FieldChars seja satisfeita. Note o <code>+<\/code> ali no final. A sintaxe da PEG tem muito em comum com as express\u00f5es regulares, ent\u00e3o isso quer dizer &#8220;Corresponder \u00e0 regra <code>FieldChars<\/code> uma ou mais vezes&#8221;<\/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=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-clipboard-success-label=\"Copiado!\" data-clipboard-error-label=\"N\u00e3o foi poss\u00edvel copiar\" data-tooltip=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copiar para a \u00e1rea de transfer\u00eancia\">\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\">Novamente, se voc\u00ea tem familiaridade com a sintaxe de regex, isso deve ser simples: basta corresponder a qualquer caractere \u00fanico entre &#8220;a&#8221; e &#8220;z&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Voltando agora a Variable, a pr\u00f3xima parte <code>_<\/code> \u00e9 uma regra que diz &#8220;corresponder a qualquer caractere de espa\u00e7o em branco&#8221;. Note que o <code>_<\/code> \u00e9 um identificador totalmente v\u00e1lido para uma regra de produ\u00e7\u00e3o, e digitar menos geralmente \u00e9 algo bom.<\/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=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-clipboard-success-label=\"Copiado!\" data-clipboard-error-label=\"N\u00e3o foi poss\u00edvel copiar\" data-tooltip=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copiar para a \u00e1rea de transfer\u00eancia\">\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\">H\u00e1 algumas coisas a serem observadas aqui:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>A string &#8220;whitespace&#8221; \u00e9 o &#8220;nome amig\u00e1vel&#8221; e existe para fins de documenta\u00e7\u00e3o e para a sua sanidade no futuro.<\/li>\n\n\n\n<li>Como ocorre com a sintaxe de express\u00f5es regulares, isso corresponder\u00e1 a qualquer forma de espa\u00e7o em branco, quebras de linha, tabula\u00e7\u00f5es ou retornos de carro (carriage-returns).<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">A pr\u00f3xima parte da regra Variable corresponde \u00e0 string literal &#8220;AND&#8221;. N\u00e3o fica muito mais f\u00e1cil do que isso.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Em seguida, temos outra regra de espa\u00e7o em branco e, por fim, a regra 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=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-clipboard-success-label=\"Copiado!\" data-clipboard-error-label=\"N\u00e3o foi poss\u00edvel copiar\" data-tooltip=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copiar para a \u00e1rea de transfer\u00eancia\">\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\">Essa regra corresponde \u00e0 string literal <code>'\"'<\/code> , zero ou mais regras ValueChars e, por \u00faltimo, outras aspas.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">O <code>ValueChars<\/code> tem a seguinte apar\u00eancia:<\/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=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-clipboard-success-label=\"Copiado!\" data-clipboard-error-label=\"N\u00e3o foi poss\u00edvel copiar\" data-tooltip=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copiar para a \u00e1rea de transfer\u00eancia\">\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\">Esses <code>ValueChars<\/code> corresponder\u00e3o ao alfabeto min\u00fasculo e mai\u00fasculo, a qualquer n\u00famero, espa\u00e7os e ao ponto de exclama\u00e7\u00e3o.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Por que definimos Value dessa maneira? Porque <b>a regra pode retirar as aspas duplas por n\u00f3s, para n\u00e3o termos que fazer isso<\/b>, e tamb\u00e9m porque somos pregui\u00e7osos. No entanto, trata-se de uma mera conveni\u00eancia que poder\u00edamos ter omitido a favor de incluir a forma da regra Value junto com a defini\u00e7\u00e3o da regra Variable.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Por fim, o <code>AndVar<\/code> deve parecer bastante direto neste ponto. Note que ele se remete a Term e implementa o ciclo mencionado anteriormente.<\/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=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-clipboard-success-label=\"Copiado!\" data-clipboard-error-label=\"N\u00e3o foi poss\u00edvel copiar\" data-tooltip=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copiar para a \u00e1rea de transfer\u00eancia\">\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\">A defini\u00e7\u00e3o completa tem a seguinte apar\u00eancia.<\/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=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-clipboard-success-label=\"Copiado!\" data-clipboard-error-label=\"N\u00e3o foi poss\u00edvel copiar\" data-tooltip=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copiar para a \u00e1rea de transfer\u00eancia\">\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\">Legal, mas e agora?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">O verdadeiro valor de definir a sua pr\u00f3pria gram\u00e1tica vem quando voc\u00ea fornece implementa\u00e7\u00f5es para as a\u00e7\u00f5es das regras. Vejamos a verdadeira defini\u00e7\u00e3o da PEG:<\/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=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-clipboard-success-label=\"Copiado!\" data-clipboard-error-label=\"N\u00e3o foi poss\u00edvel copiar\" data-tooltip=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copiar para a \u00e1rea de transfer\u00eancia\">\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\">Temos muito a analisar aqui, ent\u00e3o vamos prosseguir passo a passo.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Na parte superior, temos uma se\u00e7\u00e3o de c\u00f3digo cercada por chaves. Essa \u00e9 uma conven\u00e7\u00e3o do Pigeon que pega o c\u00f3digo inclu\u00eddo literalmente e o injeta na sa\u00edda final do c\u00f3digo gerado. Note que, por conveni\u00eancia, voc\u00ea pode definir aqui tipos relevantes para a sua gram\u00e1tica, ou pode coloc\u00e1-los em outro arquivo, pois o Pigeon usar\u00e1 o nome do pacote que voc\u00ea declarar aqui. Tudo o que vier depois disso \u00e9 a pr\u00f3pria defini\u00e7\u00e3o da gram\u00e1tica.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Neste ponto, voc\u00ea provavelmente deve ter notado que as regras diferem um pouco da forma como as definimos acima. Vamos dar uma olhada em <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=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-clipboard-success-label=\"Copiado!\" data-clipboard-error-label=\"N\u00e3o foi poss\u00edvel copiar\" data-tooltip=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copiar para a \u00e1rea de transfer\u00eancia\">\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\">Essa \u00e9 quase a nossa defini\u00e7\u00e3o anterior de <code>Term<\/code>, mas agora a tornamos \u00fatil. Colocar o prefixo <code>name<\/code>: numa regra da defini\u00e7\u00e3o atribui o valor de retorno dessa regra a name e depois passa <code>name<\/code> para a fun\u00e7\u00e3o definida pela a\u00e7\u00e3o da sua regra quando o c\u00f3digo for gerado. Todo o c\u00f3digo entre as chaves <b>se torna uma fun\u00e7\u00e3o associada a essa regra <\/b>e \u00e9 chamado quando ocorre a correspond\u00eancia com a regra:<\/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=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-clipboard-success-label=\"Copiado!\" data-clipboard-error-label=\"N\u00e3o foi poss\u00edvel copiar\" data-tooltip=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copiar para a \u00e1rea de transfer\u00eancia\">\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\">Aqui podemos ver que o Pigeon lida inteiramente com tipos de interfaces vazias (empty interface). \u00c9 \u00f3timo para a flexibilidade, mas n\u00e3o t\u00e3o bom para escrever a implementa\u00e7\u00e3o, pois temos que lev\u00e1-las em conta.<\/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=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-clipboard-success-label=\"Copiado!\" data-clipboard-error-label=\"N\u00e3o foi poss\u00edvel copiar\" data-tooltip=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copiar para a \u00e1rea de transfer\u00eancia\">\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\">Conforme mencionado anteriormente, <b>podemos ter ciclos em regras<\/b>. Considerando isso, sabemos que \u00e9 poss\u00edvel receber um n\u00famero infinito de Terms mapeados para a vari\u00e1vel <code>rest<\/code>. O Pigeon lida com isso nos entregando um slice de interfaces vazias. Criamos uma interface <code>Node<\/code> na qual tudo deve sofrer infer\u00eancia de tipo (type inference) antes que possamos us\u00e1-los.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Depois de percorrer toda a lista de vari\u00e1veis com o operador <code>AND<\/code>, criamos um <code>AndNode<\/code> contendo cada um dos Terms. A defini\u00e7\u00e3o do AndNode pode ser encontrada na se\u00e7\u00e3o de c\u00f3digo literal definida na parte superior da PEG. Como implementador da interface Node, ele define um m\u00e9todo Evaluate (avaliar) que diz que a express\u00e3o \u00e9 avaliada como verdadeira apenas se todos os termos individuais tamb\u00e9m forem avaliados como verdadeiros.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A esta altura, o restante da defini\u00e7\u00e3o deve fazer sentido; portanto, vamos passar direto para a execu\u00e7\u00e3o. A listagem de c\u00f3digo a seguir mostra como analisar a nossa regra, como us\u00e1-la e alguns exemplos extras para mostrar falhas e tratamentos de erro:<\/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=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-clipboard-success-label=\"Copiado!\" data-clipboard-error-label=\"N\u00e3o foi poss\u00edvel copiar\" data-tooltip=\"Copiar para a \u00e1rea de transfer\u00eancia\" data-tooltip-placement=\"left\" role=\"tooltip\" aria-label=\"Copiar para a \u00e1rea de transfer\u00eancia\">\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\">Tudo que voc\u00ea precisa fazer \u00e9 executar:<\/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:\"Uma oferta especial s\u00f3 para voc\u00ea!\"' matched: true Rule 'event:\"found\" AND subject:\"Uma oferta especial s\u00f3 para voc\u00ea!\"' matched: false Rule 'event:\"sent\" AND badfield:\"Uma oferta especial s\u00f3 para voc\u00ea!\"' failed with error 'Field 'badfield' not present in the event'<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Parab\u00e9ns! <b>Agora voc\u00ea criou sua pr\u00f3pria linguagem, de utilidade extremamente limitada!<\/b><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Considera\u00e7\u00f5es<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A esta altura, voc\u00ea pode estar pensando:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Muitos remetentes n\u00e3o usam assuntos assim?<\/li>\n\n\n\n<li>Um mecanismo de regras que corresponda apenas a strings literais \u00e9 t\u00e3o \u00fatil assim?<\/li>\n\n\n\n<li>Este post n\u00e3o poderia ter metade do tamanho?<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Ao que responder\u00edamos:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Gostar\u00edamos de implementar algum tipo de tratamento para o campo <code>account<\/code> (conta) conforme definido no evento original. O Mailgun resolve esse problema incluindo uma l\u00f3gica de neg\u00f3cios na base de c\u00f3digo (codebase) para dar suporte \u00e0 limita\u00e7\u00e3o de taxa (rate-limiting) com base em um campo definido. Em outras palavras, podemos dizer: &#8220;Se houver correspond\u00eancia com essa regra, salve a conta e o tempo atual e n\u00e3o execute essa a\u00e7\u00e3o nessa conta pelos pr\u00f3ximos N minutos.&#8221; Obviamente, se n\u00e3o tiv\u00e9ssemos esse tratamento e o remetente em quest\u00e3o enviasse um milh\u00e3o de e-mails, o suporte seria notificado um milh\u00e3o de vezes. Isso seria uma \u00f3tima maneira de afogar a sua equipe de suporte em barulho e tamb\u00e9m de sofrer uma emboscada no estacionamento depois do trabalho.<\/li>\n\n\n\n<li>Algu\u00e9m poderia implementar regras para fazer parse de express\u00f5es regulares e substrings que seriam muito mais \u00fateis do que uma correspond\u00eancia expl\u00edcita de strings. De fato, n\u00f3s fizemos exatamente isso.<\/li>\n\n\n\n<li>Desculpe.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Por fim, voc\u00ea provavelmente notou que n\u00e3o definimos aqui o que a regra faria quando ela <i>realmente<\/i> correspondesse. Uma solu\u00e7\u00e3o poss\u00edvel \u00e9 fazer com que a regra publique num canal do Slack quando for acionada. Essa \u00e9 uma solu\u00e7\u00e3o comum aqui no Mailgun, e tem a seguinte apar\u00eancia:<\/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\">Pr\u00f3ximos passos<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Esperamos que, a essa altura, a sua cabe\u00e7a esteja fervilhando de possibilidades. Aqui est\u00e3o algumas ideias que tivemos:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>H\u00e1 muito mais a emular na sintaxe lucene, como instru\u00e7\u00f5es NOT e OR, e par\u00eanteses.<\/li>\n\n\n\n<li>Fornecer uma gram\u00e1tica separada para a\u00e7\u00f5es.<\/li>\n\n\n\n<li>Implementar uso de templates para injetar valores do evento na a\u00e7\u00e3o.<\/li>\n\n\n\n<li>Adicionar uma camada de &#8220;syntactic sugar&#8221; (a\u00e7\u00facar sint\u00e1tico) para facilitar a escrita de alguns filtros.<\/li>\n\n\n\n<li>Implementar um sistema para contar e reagir a um n\u00famero espec\u00edfico de ocorr\u00eancias de eventos ao longo de um per\u00edodo de tempo.<\/li>\n\n\n\n<li>Implementar um cache, pois analisar sintaticamente as regras \u00e9 um pouco custoso.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">H\u00e1 muito mais que voc\u00ea pode fazer, especialmente quando se trata de estruturar o parser de a\u00e7\u00e3o. <b>Voc\u00ea poderia acionar outros servi\u00e7os, notificar clientes, acender e apagar as luzes, e muito mais.<\/b> Quando se trata de inventar suas pr\u00f3prias ferramentas com base nisso, o c\u00e9u \u00e9 o limite.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Pr\u00f3s e contras<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ent\u00e3o, neste ponto, voc\u00ea deve estar se perguntando: &#8220;por que n\u00e3o usaram $SOME_OTHER_TOOL?&#8221;\u00a0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A resposta \u00e9 que ainda n\u00e3o precisamos do poder de nenhuma dessas ferramentas nem da complexidade que frequentemente as acompanha. Nossa atual ferramenta de processamento de stream \u00e9 um \u00fanico bin\u00e1rio simples implantado em um cont\u00eainer que simplesmente funciona (Just Works\u2122). H\u00e1 muito pouco para gerenciar, e ela est\u00e1 lidando muito bem com nosso feed de eventos de alt\u00edssimo volume.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Pr\u00f3s:<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u00c9 f\u00e1cil de desenvolver<\/li>\n\n\n\n<li>Ainda utiliza ferramentas de c\u00f3digo aberto (FOSS) prontas para uso<\/li>\n\n\n\n<li>Pode ser adaptada exatamente \u00e0s nossas necessidades<\/li>\n\n\n\n<li>A sintaxe da nossa DSL \u00e9 min\u00fascula, f\u00e1cil de articular e de raciocinar, for\u00e7ando todo mundo a escrever as regras quase da mesma maneira. Tamb\u00e9m torna mais dif\u00edcil criar efeitos colaterais indesejados<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Contras:<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Os recursos de linguagem que v\u00e3o al\u00e9m do que j\u00e1 implementamos representam um salto substancial em complexidade.<\/li>\n\n\n\n<li>Atualizar a PEG de origem gerar\u00e1 um novo c\u00f3digo, e isso bagun\u00e7a bastante os diffs do seu c\u00f3digo.<\/li>\n\n\n\n<li>A simplicidade proposital do Lucene pode dificultar a cria\u00e7\u00e3o de regras mais complexas.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Podemos acabar decidindo que a $SOME_OTHER_TOOL \u00e9 mais adequada \u00e0s nossas necessidades, mas em um futuro previs\u00edvel, <b>o poder que a nossa DSL do Mailgun oferece \u00e9 mais do que suficiente.<\/b><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">O fim, finalmente<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A esta altura, esperamos ter demonstrado como criar a sua pr\u00f3pria DSL pode ser \u00fatil. Nossa implementa\u00e7\u00e3o processa um n\u00famero enorme de eventos por dia, al\u00e9m de facilitar muito a vida de v\u00e1rias pessoas da nossa equipe (pelo menos \u00e9 o que dizemos a elas).\u00a0<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quanto aos recursos aos quais oferece suporte, <b>estamos apenas come\u00e7ando<\/b>. Se isso inspirou voc\u00ea a estudar a implementa\u00e7\u00e3o da sua pr\u00f3pria gram\u00e1tica de processamento de streams, conte para n\u00f3s. Adorar\u00edamos saber mais sobre isso!<\/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_2081454ff48e7bffff4f62056d48399c\">\r\n                    <p class=\"text-uppercase section-caption text-body-color\">\r\n                Cadastre-se            <\/p>\r\n                            <p class=\"h4 text-accent fw-bold\" id=\"banner-block-block_2081454ff48e7bffff4f62056d48399c\">\r\n                \u00c9 f\u00e1cil come\u00e7ar. E \u00e9 gr\u00e1tis.            <\/p>\r\n                            <div class=\"mb-0 text-body-color\">\r\n                                    <div class=\"content-body mb-0 text-body-color\">Veja o que voc\u00ea pode alcan\u00e7ar com a melhor plataforma de entrega de e-mail do mundo.<\/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>Na Mailgun, temos v\u00e1rios sistemas gerando uma enorme quantidade de eventos a cada hora do dia. \u00c9 um n\u00famero t\u00e3o grande que \u00e9 imposs\u00edvel para uma equipe classificar os resultados do ElasticSearch e esperar resultados consistentes, ou at\u00e9 mesmo manter a sanidade.<\/p>\n","protected":false},"author":62,"featured_media":4843,"menu_order":0,"template":"","meta":{"_acf_changed":true,"footnotes":""},"blog_category":[23],"class_list":["post-24793","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>Como criamos um parser inspirado no Lucene em GoLang - Transactional Email API Service For Developers | Mailgun<\/title>\n<meta name=\"description\" content=\"Temos muito orgulho de fazer muito com muito pouco, ent\u00e3o resolvemos ver como poder\u00edamos fazer com que os filtros em tempo real funcionassem para n\u00f3s. Leia mais \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\/pt\/blog\/it-and-engineering\/como-criamos-um-parser-inspirado-no-lucene-em-go\/\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Como criamos um parser inspirado no Lucene em GoLang - Transactional Email API Service For Developers | Mailgun\" \/>\n<meta property=\"og:description\" content=\"Temos muito orgulho de fazer muito com muito pouco, ent\u00e3o resolvemos ver como poder\u00edamos fazer com que os filtros em tempo real funcionassem para n\u00f3s. Leia mais \u2013\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.mailgun.com\/pt\/blog\/it-and-engineering\/como-criamos-um-parser-inspirado-no-lucene-em-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 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/blog\\\/it-and-engineering\\\/como-criamos-um-parser-inspirado-no-lucene-em-go\\\/\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/blog\\\/it-and-engineering\\\/como-criamos-um-parser-inspirado-no-lucene-em-go\\\/\",\"name\":\"Como criamos um parser inspirado no Lucene em GoLang - Transactional Email API Service For Developers | Mailgun\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/blog\\\/it-and-engineering\\\/como-criamos-um-parser-inspirado-no-lucene-em-go\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/blog\\\/it-and-engineering\\\/como-criamos-um-parser-inspirado-no-lucene-em-go\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.mailgun.com\\\/wp-content\\\/uploads\\\/2025\\\/07\\\/MG-Blog-IT-Engineering.png\",\"datePublished\":\"2026-09-16T17:51:41+00:00\",\"description\":\"Temos muito orgulho de fazer muito com muito pouco, ent\u00e3o resolvemos ver como poder\u00edamos fazer com que os filtros em tempo real funcionassem para n\u00f3s. Leia mais \u2013\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/blog\\\/it-and-engineering\\\/como-criamos-um-parser-inspirado-no-lucene-em-go\\\/#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/blog\\\/it-and-engineering\\\/como-criamos-um-parser-inspirado-no-lucene-em-go\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/blog\\\/it-and-engineering\\\/como-criamos-um-parser-inspirado-no-lucene-em-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\\\/pt\\\/blog\\\/it-and-engineering\\\/como-criamos-um-parser-inspirado-no-lucene-em-go\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/inicio\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Blog\",\"item\":\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Como criamos um parser inspirado no Lucene em Go\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/#website\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/\",\"name\":\"Transactional Email API Service For Developers | Mailgun\",\"description\":\"Poderosas APIs de e-mail transacional que permitem a voc\u00ea enviar, receber e rastrear e-mails, criadas com os desenvolvedores em mente. Saiba mais hoje mesmo!\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"pt-BR\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/#organization\",\"name\":\"Transactional Email API Service For Developers | Mailgun\",\"url\":\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\\\/\\\/www.mailgun.com\\\/pt\\\/#\\\/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\\\/pt\\\/#\\\/schema\\\/logo\\\/image\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Como criamos um parser inspirado no Lucene em GoLang - Transactional Email API Service For Developers | Mailgun","description":"Temos muito orgulho de fazer muito com muito pouco, ent\u00e3o resolvemos ver como poder\u00edamos fazer com que os filtros em tempo real funcionassem para n\u00f3s. Leia mais \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\/pt\/blog\/it-and-engineering\/como-criamos-um-parser-inspirado-no-lucene-em-go\/","og_locale":"pt_BR","og_type":"article","og_title":"Como criamos um parser inspirado no Lucene em GoLang - Transactional Email API Service For Developers | Mailgun","og_description":"Temos muito orgulho de fazer muito com muito pouco, ent\u00e3o resolvemos ver como poder\u00edamos fazer com que os filtros em tempo real funcionassem para n\u00f3s. Leia mais \u2013","og_url":"https:\/\/www.mailgun.com\/pt\/blog\/it-and-engineering\/como-criamos-um-parser-inspirado-no-lucene-em-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 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.mailgun.com\/pt\/blog\/it-and-engineering\/como-criamos-um-parser-inspirado-no-lucene-em-go\/","url":"https:\/\/www.mailgun.com\/pt\/blog\/it-and-engineering\/como-criamos-um-parser-inspirado-no-lucene-em-go\/","name":"Como criamos um parser inspirado no Lucene em GoLang - Transactional Email API Service For Developers | Mailgun","isPartOf":{"@id":"https:\/\/www.mailgun.com\/pt\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.mailgun.com\/pt\/blog\/it-and-engineering\/como-criamos-um-parser-inspirado-no-lucene-em-go\/#primaryimage"},"image":{"@id":"https:\/\/www.mailgun.com\/pt\/blog\/it-and-engineering\/como-criamos-um-parser-inspirado-no-lucene-em-go\/#primaryimage"},"thumbnailUrl":"https:\/\/www.mailgun.com\/wp-content\/uploads\/2025\/07\/MG-Blog-IT-Engineering.png","datePublished":"2026-09-16T17:51:41+00:00","description":"Temos muito orgulho de fazer muito com muito pouco, ent\u00e3o resolvemos ver como poder\u00edamos fazer com que os filtros em tempo real funcionassem para n\u00f3s. Leia mais \u2013","breadcrumb":{"@id":"https:\/\/www.mailgun.com\/pt\/blog\/it-and-engineering\/como-criamos-um-parser-inspirado-no-lucene-em-go\/#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.mailgun.com\/pt\/blog\/it-and-engineering\/como-criamos-um-parser-inspirado-no-lucene-em-go\/"]}]},{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.mailgun.com\/pt\/blog\/it-and-engineering\/como-criamos-um-parser-inspirado-no-lucene-em-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\/pt\/blog\/it-and-engineering\/como-criamos-um-parser-inspirado-no-lucene-em-go\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.mailgun.com\/pt\/inicio\/"},{"@type":"ListItem","position":2,"name":"Blog","item":"https:\/\/www.mailgun.com\/pt\/blog\/"},{"@type":"ListItem","position":3,"name":"Como criamos um parser inspirado no Lucene em Go"}]},{"@type":"WebSite","@id":"https:\/\/www.mailgun.com\/pt\/#website","url":"https:\/\/www.mailgun.com\/pt\/","name":"Transactional Email API Service For Developers | Mailgun","description":"Poderosas APIs de e-mail transacional que permitem a voc\u00ea enviar, receber e rastrear e-mails, criadas com os desenvolvedores em mente. Saiba mais hoje mesmo!","publisher":{"@id":"https:\/\/www.mailgun.com\/pt\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.mailgun.com\/pt\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"pt-BR"},{"@type":"Organization","@id":"https:\/\/www.mailgun.com\/pt\/#organization","name":"Transactional Email API Service For Developers | Mailgun","url":"https:\/\/www.mailgun.com\/pt\/","logo":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.mailgun.com\/pt\/#\/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\/pt\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/www.mailgun.com\/pt\/wp-json\/wp\/v2\/blog\/24793","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mailgun.com\/pt\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.mailgun.com\/pt\/wp-json\/wp\/v2\/types\/blog"}],"author":[{"embeddable":true,"href":"https:\/\/www.mailgun.com\/pt\/wp-json\/wp\/v2\/users\/62"}],"version-history":[{"count":0,"href":"https:\/\/www.mailgun.com\/pt\/wp-json\/wp\/v2\/blog\/24793\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mailgun.com\/pt\/wp-json\/wp\/v2\/media\/4843"}],"wp:attachment":[{"href":"https:\/\/www.mailgun.com\/pt\/wp-json\/wp\/v2\/media?parent=24793"}],"wp:term":[{"taxonomy":"blog_category","embeddable":true,"href":"https:\/\/www.mailgun.com\/pt\/wp-json\/wp\/v2\/blog_category?post=24793"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}