Caso 01 C++ · WebAssembly · Compiladores
Parsec: uma linguagem de fórmulas compartilhada entre plataformas
Fórmulas de negócio precisam dar o mesmo resultado em qualquer lugar onde são calculadas. Trabalhei no Parsec, uma biblioteca C++ que interpreta equações em etapas inspiradas em compiladores, e desenvolvi individualmente o parsec-web, sua versão em WebAssembly.
Contexto
Sistemas de negócio muitas vezes guardam regras na forma de fórmulas e equações. Na Oxeanbits, essas fórmulas precisavam ser avaliadas em contextos diferentes, do backend às aplicações web e mobile.
O Parsec é a biblioteca de avaliação de equações criada para isso. Seu núcleo em C++ foi construído a partir do muparserx, uma biblioteca open source, e recebeu contribuições de outras pessoas da Oxeanbits. Não o apresento como obra exclusivamente minha.
Problema
Quando cada plataforma implementa sua própria interpretação de uma fórmula, pequenas diferenças aparecem: precedência de operadores, tratamento de tipos, mensagens de erro. O mesmo cálculo pode produzir resultados diferentes no servidor e no aplicativo, e a diferença só aparece para quem usa o sistema.
Também é preciso rejeitar fórmulas inválidas com clareza antes de executá-las, em vez de falhar no meio de um cálculo.
Minha responsabilidade
Trabalhei no desenvolvimento do Parsec, cuja interpretação segue etapas típicas de um compilador: tokenização, análise sintática e análise semântica antes da avaliação.
Desenvolvi individualmente o parsec-web, a versão WebAssembly que leva essa interpretação ao navegador. É uma contribuição específica minha; não significa que construí sozinho cada produto ou integração em volta da biblioteca.
Decisão
A intenção arquitetural era definir uma linguagem comum para fórmulas e equações, interpretada por um núcleo compartilhado e consumida em backend, web, mobile e cenários offline, em vez de deixar cada plataforma reinterpretar as regras.
Isso descreve o objetivo do projeto, não uma prova de que todos esses destinos foram implantados. Há repositórios públicos para o uso em Ruby, a gem parsec, e na web, o parsec-web.
Alternativas e trade-offs
Análise atual, escrita para este site. Não é um registro das alternativas avaliadas na época.
- Reimplementar o interpretador em cada linguagem dispensa a camada de integração, mas multiplica o trabalho e as chances de divergência entre plataformas.
- Um núcleo compartilhado concentra a correção em um só lugar. Em troca, exige uma ponte para cada plataforma, como o WebAssembly no navegador, e testes que confirmem o mesmo comportamento entre ambientes.
Implementação
A avaliação de uma fórmula passa por etapas, cada uma com uma responsabilidade clara.
Tokenização
A expressão é quebrada em unidades com significado: números, variáveis, operadores, funções e parênteses.
Análise sintática
Os tokens são organizados em uma estrutura que respeita precedência e agrupamento, como uma árvore de expressão.
Análise semântica
A estrutura é validada antes da execução: as operações precisam fazer sentido para os tipos envolvidos, e os erros são reportados com clareza.
WebAssembly
No parsec-web, o núcleo C++ é compilado para WebAssembly com Emscripten e exposto por uma biblioteca JavaScript. Em vez de enviar cada fórmula ao backend, o navegador a avalia localmente com a mesma lógica, o que também viabiliza o uso offline.
Visualização
Etapa 1 de 5: Expressão
Fórmula válida
01 · Expressão
quantidade * preco * (1 - desconto)02 · Tokens
quantidadevariável*operadorprecovariável*operador(parêntese1número-operadordescontovariável)parêntese
03 · Estrutura
04 · Validação
- Variáveis definidas: quantidade, preco, desconto
- O operador * recebe dois números
- O operador - recebe dois números
05 · Resultado
108
3 × 40 × (1 − 0,1) = 108
Valores de exemplo: quantidade = 3 · preco = 40 · desconto = 0,1
Fórmula com erro
01 · Expressão
quantidade * preco * (1 - "10%")02 · Tokens
quantidadevariável*operadorprecovariável*operador(parêntese1número-operador"10%"texto)parêntese
03 · Estrutura
04 · Validação
- Variáveis definidas: quantidade, preco
- O operador * recebe dois números
- O operador - recebe um número e um texto
05 · Resultado
O operador "-" recebeu um número e um texto. A fórmula é rejeitada antes de qualquer cálculo.
Valores de exemplo: quantidade = 3 · preco = 40
Descrição em texto
Fórmula válida
- Expressão:
quantidade * preco * (1 - desconto). O texto da fórmula, como alguém escreveria em uma regra de negócio. - Tokens: quantidade (variável), * (operador), preco (variável), * (operador), ( (parêntese), 1 (número), - (operador), desconto (variável), ) (parêntese). A tokenização separa números, variáveis, operadores e parênteses.
- Estrutura: Multiplicação entre (quantidade × preco) e (1 − desconto). Os parênteses fazem a subtração acontecer antes da multiplicação final. A análise sintática organiza os tokens em uma árvore que respeita precedência e parênteses.
- Validação: Variáveis definidas: quantidade, preco, desconto (ok); O operador * recebe dois números (ok); O operador - recebe dois números (ok). Todas as verificações passaram.
- Resultado: 3 × 40 × (1 − 0,1) = 108
Fórmula com erro
- Expressão:
quantidade * preco * (1 - "10%"). O texto da fórmula, como alguém escreveria em uma regra de negócio. - Tokens: quantidade (variável), * (operador), preco (variável), * (operador), ( (parêntese), 1 (número), - (operador), "10%" (texto), ) (parêntese). A tokenização separa números, variáveis, operadores e parênteses.
- Estrutura: Multiplicação entre (quantidade × preco) e (1 − "10%"). A estrutura é sintaticamente válida: o problema só aparece na análise semântica. A análise sintática organiza os tokens em uma árvore que respeita precedência e parênteses.
- Validação: Variáveis definidas: quantidade, preco (ok); O operador * recebe dois números (ok); O operador - recebe um número e um texto (falha).
- Resultado: O operador "-" recebeu um número e um texto. A fórmula é rejeitada antes de qualquer cálculo. Não avaliada. O erro é reportado antes da execução.
Resultado
O parsec-web leva a avaliação de fórmulas ao navegador, alinhado à ideia de uma única linguagem entre plataformas. O repositório é público.
O caso mostra o tipo de problema em que gosto de trabalhar: quando a consistência entre ambientes depende de decisões de linguagem, parsing e integração, e não apenas de escrever mais código.