← Hub Principal |
🧩

05: Zero-Dependency JSON Parser & AST

Rust 2021 (Compilers & AST)
Teoria de Compiladores & Linguagens Formais Módulo 05

Parser JSON Descendente Recursivo & AST

Uma implementação artesanal de um interpretador sintático para a especificação RFC 8259 (JSON). Sem recorrer a crates externas como serde, o módulo demonstra as técnicas centrais de engenharia de compiladores: tokenização léxica com rastreamento posicional, recursão mútua e tipos de dados algébricos (ADTs).


01. Arquitetura Clássica: Lexer vs Parser

Interpretar linguagens em uma única passagem misturando caracteres brutos com regras gramaticais resulta em código frágil e de difícil manutenção. Separamos o processo em dois estágios desacoplados:

1. Análise Léxica (Lexer / Tokenizer)

Varre a string de caracteres e agrupa sequências com significado semântico em unidades atômicas chamadas Tokens (LeftBrace, Colon, StringLiteral). Cada token carrega sua coordenada de origem (Span { line, col }).

2. Análise Sintática (Recursive Descent)

Consome o fluxo linear de tokens e valida se a sequência respeita a Gramática Livre de Contexto da linguagem, construindo uma estrutura arbórea hierárquica na memória: a AST (Abstract Syntax Tree).

02. Modelagem Expressiva de ASTs com Enums

Em linguagens orientadas a objetos tradicionais, ASTs exigem herança e ponteiros polimórficos (virtual / interface), provocando indireções de memória. Em Rust, os Enums são Tagged Unions de primeira classe:

pub enum JsonValue { Null, Bool(bool), Number(f64), String(String), Array(Vec<JsonValue>), Object(BTreeMap<String, JsonValue>) }

Essa definição é intrinsecamente recursiva: um JsonValue::Object contém nós que também são JsonValue. O compilador garante casamento de padrões exaustivo (match), assegurando que nenhum caso sintático seja ignorado em tempo de execução.

03. Tratamento de Erros e Diagnósticos Posicionais

Um parser profissional não deve apenas falhar com um booleano ou mensagem vaga. Ao carregar as coordenadas Span durante o lexing, o parser emite diagnósticos precisos que indicam a linha e coluna exatas onde a gramática foi violada.

Variante do Erro Causa Gramatical Feedback de Diagnóstico
UnexpectedToken Token fora da regra (ex: chave sem valor) Linha X, Coluna Y: Esperava valor JSON
UnexpectedEof Payload truncado sem fechar chaves/colchetes EOF antes de fechar delimitadores
TrailingCharacters Tokens residuais após o fechamento da raiz Caracteres extras detectados após a raiz

04. Complexidade & Zero-Copy Considerations

💡 Evolução para Zero-Copy com Lifetimes:

Esta implementação aloca instâncias de String para manter o código modular e simples. Em cenários de altíssimo throughput, o ecossistema Rust utiliza Slices Emprestados (&'a str) com parâmetros de Lifetime: o parser não aloca nenhuma nova string no Heap, apontando diretamente para fatias da memória do buffer original de entrada.

cargo run --bin json_parser
Ambiente pronto. Clique em "Compilar & Executar" para rodar o Lexer e o Parser JSON em tempo real.