Decisões Técnicas
Visão Geral
Esta página registra as principais decisões técnicas tomadas pelo grupo ao longo do desenvolvimento do compilador Mini C → Calango. Cada decisão é acompanhada de sua justificativa, garantindo rastreabilidade e transparência no processo de desenvolvimento.
Ferramentas Escolhidas
| Ferramenta | Função | Justificativa |
|---|---|---|
| Flex | Geração do analisador léxico | Ferramenta padrão da disciplina; gera AFD automaticamente a partir de expressões regulares |
| Bison | Geração do analisador sintático | Complementar ao Flex; gera parser LALR(1) a partir de gramáticas livres de contexto |
| C | Linguagem de implementação | Integração nativa com Flex e Bison; controle fino sobre estruturas de dados |
Arquitetura do Projeto
O compilador é organizado em dois arquivos separados que se comunicam entre si:
lexer.l— analisador léxico (Flex): lê o código-fonte e retorna tokens ao parserparser.y— analisador sintático (Bison): consome os tokens e valida a estrutura do programa
O arquivo parser.tab.h, gerado automaticamente pelo Bison, é incluído no lexer.l para que ambos compartilhem a definição dos tokens. Dessa forma, os arquivos permanecem separados mas integrados.
Fluxo de compilação:
Restrições do Escopo
Por decisão do grupo, as construções abaixo não são suportadas nesta versão do compilador. Todas as restrições foram autorizadas pelo professor e estão justificadas a seguir.
Funções além do main
Decisão: não suportado.
Justificativa: O Calango utiliza subprogramas com sintaxe e semântica distintas das funções em C. A tradução correta exigiria gerenciamento de escopo separado por função em todas as fases do compilador (léxico, sintático, semântico e geração de código), adicionando complexidade desproporcional ao prazo disponível.
return e void
Decisão: não suportado.
Justificativa: Consequência direta da restrição de funções. Sem funções definidas pelo usuário, return e void não se aplicam ao escopo do projeto.
Atribuição composta (+=, -=, *=, /=)
Decisão: não suportado.
Justificativa: Não existe equivalente direto no Calango. A alternativa correta é a atribuição simples expandida: x = x + 1. O lexer reporta erro informativo ao encontrar esses operadores.
Incremento e decremento (++, --)
Decisão: não suportado.
Justificativa: Mesmo motivo da atribuição composta. Substituir por x = x + 1 é equivalente e compatível com o Calango. O lexer reporta erro informativo com sugestão de correção.
Arrays
Decisão: não suportado.
Justificativa: Arrays adicionam complexidade em todas as fases do compilador: declaração com tamanho, acesso indexado, verificação de bounds na semântica e tradução para vetores do Calango. A restrição permite entregar um compilador funcional e completo para variáveis simples dentro do prazo.
Cast explícito
Decisão: não suportado.
Justificativa: O Calango não possui operador de cast explícito. A tradução não seria direta e a construção é pouco comum em programas simples dentro do escopo suportado.
Operadores bitwise (&, |, ^, ~, <<, >>)
Decisão: não suportado.
Justificativa: O Calango não possui operadores bitwise. Não há tradução possível sem alterar a semântica do programa.
Operador ternário (?:)
Decisão: não suportado.
Justificativa: O Calango não possui operador ternário. O equivalente é um se...entao...senao, que pertence à análise sintática e não ao léxico.
Declaração de variáveis fora do início do bloco
Decisão: apenas no início do bloco main (estilo C89).
Justificativa: Simplifica o parser, que não precisa distinguir declarações de instruções em posições arbitrárias. O Calango também exige declarações no início do bloco, tornando a restrição consistente com a linguagem alvo.
Decisões de Implementação
Precedência de operadores via diretivas do Bison
Em vez de criar regras gramaticais separadas para cada nível de precedência (termo_add, termo_mul, etc.), utilizamos as diretivas %left e %right do Bison. O resultado semântico é idêntico, mas o arquivo .y fica significativamente mais simples e legível.
UMINUS — menos unário
O token fictício UMINUS foi criado exclusivamente para atribuir ao menos unário (-x) precedência maior do que a subtração (a - b), evitando ambiguidade na gramática sem necessidade de regra extra.
LIT_FLOAT antes de LIT_INT no lexer
A regra de LIT_FLOAT é posicionada antes de LIT_INT no lexer.l. O Flex aplica a primeira regra que corresponder — sem essa ordem, 3.14 seria tokenizado como LIT_INT(3) + DOT + LIT_INT(14).
Palavras reservadas antes de ID
Todas as palavras reservadas (int, if, while, etc.) são declaradas antes da regra de ID no lexer. Isso garante que if seja sempre KW_IF e nunca classificado como identificador.
Operadores de dois caracteres antes de um caractere
Os operadores ==, !=, <=, >=, &&, || são declarados antes de =, <, >, &, |. Sem essa ordem, == seria tokenizado como dois tokens ASSIGN separados.
Divisão: decisão semântica, não léxica
Em C, / entre inteiros é divisão inteira; entre reais, é divisão real. No Calango, / é sempre divisão real e \ é divisão inteira. O lexer reconhece apenas DIVIDE para o token / — a distinção entre divisão inteira e real será resolvida na fase de geração de código, com base nos tipos dos operandos.
% mapeado para mod
O operador de resto % do Mini C é mapeado para mod do Calango. A tradução é semanticamente equivalente para inteiros positivos, que é o caso de uso predominante no escopo do projeto.
Histórico de Versões
| Versão | Descrição | Data | Responsável |
|---|---|---|---|
0.1 |
Criação da página. | 08/04/2026 | @Luiz Faria |
0.2 |
Início da documentação das decisões técnicas do projeto. | 11/04/2026 | @Luiz Faria, @João Pedro, @Rivaldâvio |