Interpretador de Linguagem C-Like com TypeScript e ANTLR
Este projeto consiste em um Interpretador completo para um subconjunto da linguagem C, desenvolvido em TypeScript utilizando a ferramenta ANTLR4 para análise léxica e sintática.
O sistema realiza todas as etapas de um compilador moderno: Pré-processamento, Análise Sintática, Análise Semântica e Interpretação (Execução).
Índice
- Funcionalidades Implementadas
- Pré-requisitos
- Instalação e Configuração
- Como Executar
- Arquitetura do Projeto
- Exemplos de Sintaxe
- Estrutura de Arquivos
Funcionalidades Implementadas
O interpretador atende aos requisitos propostos para a avaliação, incluindo:
Tipos de Dados e Estruturas
- Tipos Primitivos:
int, float, char, string, void.
- Structs: Definição, declaração e acesso a membros (
ponto.x).
- Unions: Definição e simulação de memória compartilhada (sobrescrita de valor).
- Arrays: Vetores unidimensionais com leitura e escrita (
arr[i]).
Controle de Fluxo
- Condicionais:
if, if...else.
- Seleção:
switch / case / default.
- Laços de Repetição:
Funções e Escopo
- Funções: Declaração com e sem retorno (
void).
- Recursão: Suporte completo.
- Escopo: Gerenciamento de variáveis globais, locais e parâmetros.
- Retorno: Validação semântica de tipos de retorno.
Pré-processador e Ferramentas
- #include: Inclusão recursiva de arquivos externos.
- #define: Definição de constantes globais.
- Comentários: Linha (
//) e Bloco (/* ... */).
Entrada e Saída (I/O)
- printf: Impressão formatada (
%d, %s, etc.) ou múltipla.
- puts: Impressão com quebra de linha automática.
- scanf / gets: Entrada de dados síncrona pelo terminal.
Pré-requisitos
- Node.js (v14 ou superior)
- npm (Gerenciador de pacotes do Node)
Instalação e Configuração
-
Clone o repositório (ou extraia os arquivos na pasta do projeto):
# Entre na pasta do projeto
cd compilador_ts
-
Instale as dependências:
npm install
-
Gere o Parser e Lexer (ANTLR):
Ele lê o arquivo .g4 e gera os códigos TypeScript base.
npm run build:antlr
Como Executar
-
Edite o arquivo de teste:
Abra o arquivo test.lang na raiz do projeto e escreva o código que deseja interpretar.
Nota: Se usar #include "arquivo.lang", certifique-se de que o arquivo incluído também existe na raiz.
-
Execute o interpretador:
npx ts-node src/index.ts
-
Interação:
Se o seu código contiver scanf, o terminal pausará. Digite o valor e pressione ENTER.
Arquitetura do Projeto
O projeto segue um pipeline de execução em quatro estágios:
1. Pré-processador (index.ts)
Antes da análise, o sistema lê o arquivo fonte e resolve recursivamente todas as diretivas #include, gerando um único buffer de código para compilação.
2. Análise Léxica e Sintática (ANTLR4)
Define a gramática no arquivo grammar/TrabalhoCompiladores.g4. O ANTLR gera a árvore sintática abstrata (AST) e os tokens.
3. Análise Semântica (SemanticAnalyzer.ts)
Percorre a AST utilizando o padrão Visitor.
- Monta a Tabela de Símbolos (
SymbolTable.ts).
- Verifica tipos (ex: não somar
int com string).
- Verifica existência de variáveis e funções.
- Registra definições de
structs, unions e #define.
- Relata erros semânticos no console.
4. Interpretador (Interpreter.ts)
Se a análise semântica for bem sucedida, o Interpretador percorre a AST novamente.
- Utiliza uma Memória em Tempo de Execução (
RuntimeMemory.ts) baseada em pilha de escopos.
- Executa operações matemáticas e lógicas.
- Gerencia chamadas de função e recursão.
- Realiza I/O real (
console.log, fs.readSync).
Exemplos de Sintaxe
1. Structs e Arrays
struct Ponto {
int x;
int y;
};
void main() {
struct Ponto p;
p.x = 10;
int arr[5];
arr[0] = p.x * 2;
printf(arr[0]); // Saída: 20
}
2. Recursão e Controle de Fluxo
int fib(int n) {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
}
void main() {
int resultado = fib(7);
printf("Fibonacci de 7:", resultado); // Saída: 13
}
3. Unions e Memória Compartilhada
union Dados {
int i;
float f;
};
void main() {
union Dados d;
d.i = 10;
d.f = 5.5; // Sobrescreve o espaço de memória
printf(d.i); // Imprime a representação de 5.5 (valor compartilhado)
}
Estrutura de Arquivos
/
├── grammar/
│ └── TrabalhoCompiladores.g4 # Definição da Gramática (Lexer/Parser)
├── src/
│ ├── parser/ # Código gerado automaticamente pelo ANTLR
│ ├── index.ts # Ponto de entrada e Pré-processador
│ ├── Interpreter.ts # Lógica de execução (Back-end)
│ ├── SemanticAnalyzer.ts # Lógica de verificação (Front-end)
│ ├── SymbolTable.ts # Gerenciamento de escopo e símbolos
│ ├── RuntimeMemory.ts # Gerenciamento de memória em execução
│ └── ReturnValue.ts # Classe auxiliar para controle de fluxo
├── test.lang # Arquivo de teste principal
├── my_utils.lang # Arquivo auxiliar para teste de #include
├── package.json # Dependências e scripts
└── tsconfig.json # Configuração do TypeScript
Autoria
Universidade Estadual do Norte do Paraná
Curso: Bacharelado em Ciência da Computação
Disciplina: Compiladores
Ano: 2025
Aluno: Diego Souza Vieira, Miguel Valentim de Almeida, William Haruo Yoshida