Leonardo Alves Silva - 10723113466 | Teoria da computação e compiladores
Um compilador é um programa que traduz código escrito em uma linguagem de programação (linguagem fonte) para outra linguagem (linguagem alvo).
O Compilador Lusitano é tecnicamente um transpilador (source-to-source compiler):
┌─────────────────┐ ┌─────────────┐ ┌─────────────┐
│ Código Fonte │ ──► │ Compilador │ ──► │ Python │
│ (Lusitano) │ │ Lusitano │ │ (Target) │
└─────────────────┘ └─────────────┘ └─────────────┘
- Mesmas fases clássicas: Scanner, Parser, Análise Semântica
- Transforma linguagem A em B: Lusitano → Python
- Análise completa: Verifica erros léxicos, sintáticos e semânticos
- Gera código executável: O Python gerado pode ser executado diretamente
funcao principal() {
var nome: texto = "Mundo"
se (idade >= 18) {
escreva("Maior de idade")
} senao {
escreva("Menor de idade")
}
}
| Lusitano | Equivalente |
|---|---|
funcao |
function |
se/senao |
if/else |
enquanto |
while |
para...de...ate |
for |
retorna |
return |
escreva |
|
leia |
input |
verdadeiro/falso |
true/false |
inteiro/real/texto/logico |
int/float/str/bool |
- Poucas linguagens de programação têm sintaxe em português
- Ainda menos são compiladores completos com análise semântica
- Valor didático imenso para lusófonos
┌─────────────────────────────────────────────────────────────────┐
│ FRONT END │
│ ┌───────────┐ ┌───────────┐ ┌────────────────┐ │
│ │ Scanner │──►│ Parser │──►│ Semântico │ │
│ │ (Léxico) │ │ (Sintaxe) │ │ (Verificação) │ │
│ └───────────┘ └───────────┘ └────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ [Tokens] [AST] [Tabela Símbolos] │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ BACK END │
│ ┌────────────────┐ ┌────────────────┐ │
│ │ Gerador de │──►│ Código Python │ │
│ │ Código │ │ Executável │ │
│ └────────────────┘ └────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Transforma o código fonte (texto) em uma sequência de tokens (unidades léxicas).
Como dividir uma frase em palavras e pontuação:
- "O gato dormiu." → ["O", "gato", "dormiu", "."]
Entrada:
var idade: inteiro = 25
Saída (Tokens):
┌─────────┬─────────────────┬─────────┐
│ Tipo │ Lexema │ Valor │
├─────────┼─────────────────┼─────────┤
│ VAR │ "var" │ - │
│ IDENT │ "idade" │ - │
│ DOIS_PT │ ":" │ - │
│ INTEIRO │ "inteiro" │ - │
│ ATRIB │ "=" │ - │
│ NUMERO │ "25" │ 25 │
└─────────┴─────────────────┴─────────┘
- ✓ Identificar palavras-chave (se, enquanto, funcao...)
- ✓ Reconhecer identificadores (nomes de variáveis)
- ✓ Processar literais (números, strings)
- ✓ Detectar operadores e delimitadores
- ✓ Ignorar comentários e espaços
- ✓ Reportar erros léxicos (caracteres inválidos)
Verifica se a sequência de tokens segue a gramática da linguagem e constrói a AST (Abstract Syntax Tree).
Descida Recursiva (Recursive Descent) - cada regra gramatical vira uma função.
programa → declaracao*
declaracao → funcao | var | statement
funcao → "funcao" IDENT "(" params? ")" bloco
statement → se | enquanto | para | escreva | expressao
expressao → atribuicao | comparacao | termo | fator
Código:
se (x > 10) {
escreva("Grande")
}
Árvore Sintática:
📄 Programa
└── 🔀 Se
├── Condição: ➕ Binária (>)
│ ├── 🔤 Variável: x
│ └── 📌 Literal: 10
└── Então: 📁 Bloco
└── 🖨️ Escreva: "Grande"
- ✓ Verificar estrutura gramatical
- ✓ Construir árvore sintática abstrata
- ✓ Reportar erros de sintaxe
- ✓ Suportar precedência de operadores
Verifica a correção lógica do programa que a sintaxe não consegue garantir.
// ❌ ERRO: variável não declarada
escreva(x)
// ✓ CORRETO
var x: inteiro = 10
escreva(x)
// ❌ ERRO: não pode somar texto com inteiro
var resultado: inteiro = "olá" + 5
// ✓ CORRETO
var resultado: inteiro = 10 + 5
funcao teste() {
var local: inteiro = 1
}
// ❌ ERRO: 'local' não existe fora da função
escreva(local)
// ❌ ERRO: deveria retornar inteiro
funcao soma(a: inteiro, b: inteiro): inteiro {
retorna "texto"
}
const PI: real = 3.14159
// ❌ ERRO: não pode alterar constante
PI = 3.14
┌──────────────┬──────────┬────────────┬────────┐
│ Nome │ Tipo │ Categoria │ Escopo │
├──────────────┼──────────┼────────────┼────────┤
│ fatorial │ funcao │ funcao │ 0 │
│ n │ inteiro │ parametro │ 1 │
│ principal │ funcao │ funcao │ 0 │
│ nome │ texto │ variavel │ 1 │
│ PI │ real │ constante │ 1 │
└──────────────┴──────────┴────────────┴────────┘
Percorre a AST e gera código Python equivalente.
Cada tipo de nó da AST tem um método de visita que gera o código correspondente.
Entrada (Lusitano):
funcao fatorial(n: inteiro): inteiro {
se (n <= 1) {
retorna 1
}
retorna n * fatorial(n - 1)
}
funcao principal() {
para i de 1 ate 5 {
escreva(i, "! = ", fatorial(i))
}
}
Saída (Python):
def fatorial(n):
if (n <= 1):
return 1
return (n * fatorial((n - 1)))
def principal():
for i in range(1, 5 + 1):
print(i, '! = ', fatorial(i), sep='')
if __name__ == '__main__':
principal()| Lusitano | Python |
|---|---|
se/senao |
if/else |
enquanto |
while |
para i de X ate Y |
for i in range(X, Y+1) |
e / ou / nao |
and / or / not |
verdadeiro/falso |
True/False |
┌────────────────────────────────────────────────────────────────────┐
│ CÓDIGO FONTE LUSITANO │
│ funcao principal() { │
│ var x: inteiro = 10 │
│ escreva("Valor: ", x) │
│ } │
└────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────┐
│ 1. ANÁLISE LÉXICA (Scanner) │
│ [FUNCAO][IDENT:principal][ABRE_PAREN][FECHA_PAREN][ABRE_CHAVE] │
│ [VAR][IDENT:x][DOIS_PONTOS][TIPO_INTEIRO][ATRIB][NUM:10]... │
└────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────┐
│ 2. ANÁLISE SINTÁTICA (Parser) │
│ Programa │
│ └── Funcao: principal │
│ └── Bloco │
│ ├── DeclVar: x = 10 (inteiro) │
│ └── Escreva: ["Valor: ", x] │
└────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────┐
│ 3. ANÁLISE SEMÂNTICA │
│ ✓ Função 'principal' declarada │
│ ✓ Variável 'x' declarada como inteiro │
│ ✓ Tipos compatíveis na atribuição │
│ ✓ Tabela de símbolos construída │
└────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────┐
│ 4. GERAÇÃO DE CÓDIGO │
│ def principal(): │
│ x = 10 │
│ print('Valor: ', x, sep='') │
│ │
│ if __name__ == '__main__': │
│ principal() │
└────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────┐
│ EXECUÇÃO │
│ $ python programa.py │
│ Valor: 10 │
└────────────────────────────────────────────────────────────────────┘
// Programa de demonstração
funcao fatorial(n: inteiro): inteiro {
se (n <= 1) {
retorna 1
}
retorna n * fatorial(n - 1)
}
funcao principal(): inteiro {
escreva("Cálculo de Fatoriais:")
para n de 1 ate 6 {
escreva(n, "! = ", fatorial(n))
}
retorna 0
}
╔═══════════════════════════════════════╗
║ COMPILADOR LUSITANO ║
╚═══════════════════════════════════════╝
✓ Análise léxica: 48 tokens
✓ Análise sintática: 2 funções
✓ Análise semântica: sem erros
✓ Código Python gerado
EXECUÇÃO:
Cálculo de Fatoriais:
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
╔══════════════════════════════════════════╗
║ ERRO LÉXICO na linha 5, coluna 12 ║
╠══════════════════════════════════════════╣
║ Caractere não reconhecido: '@' ║
║ Contexto: var email@ = "teste" ║
║ ^ ║
╚══════════════════════════════════════════╝
╔══════════════════════════════════════════╗
║ ERRO SINTÁTICO na linha 3, coluna 5 ║
╠══════════════════════════════════════════╣
║ Esperado ')' após condição ║
║ Token encontrado: ABRE_CHAVE ('{') ║
╚══════════════════════════════════════════╝
╔══════════════════════════════════════════╗
║ ERRO SEMÂNTICO na linha 7, coluna 10 ║
╠══════════════════════════════════════════╣
║ Variável 'contador' não foi declarada ║
╚══════════════════════════════════════════╝
compilador_lusitano/
│
├── lexer.py # Scanner - Análise Léxica
│ ├── TipoToken # Enum com todos os tipos de tokens
│ ├── Token # Estrutura de dados do token
│ ├── Scanner # Analisador léxico principal
│ └── ErroLexico # Exceções léxicas
│
├── parser.py # Parser - Análise Sintática
│ ├── NoAST # Classes para nós da AST
│ ├── Parser # Analisador sintático (Descida Recursiva)
│ ├── VisitanteAST # Interface Visitor
│ └── ErroSintatico # Exceções sintáticas
│
├── semantico.py # Análise Semântica
│ ├── Tipo # Sistema de tipos
│ ├── Simbolo # Entrada da tabela de símbolos
│ ├── TabelaSimbolos# Gerenciamento de escopos
│ └── AnalisadorSemantico # Visitor para verificação
│
├── lusitano.py # Compilador Principal
│ ├── GeradorPython # Transpilador para Python
│ └── CompiladorLusitano # Integração de todas as fases
│
└── exemplos/
└── fibonacci.lus # Programas de exemplo
✓ Scanner Completo
- 40+ tipos de tokens
- Suporte a strings, números, comentários
- Mensagens de erro detalhadas
✓ Parser Recursivo
- Gramática completa da linguagem
- AST com 20+ tipos de nós
- Recuperação de erros
✓ Análise Semântica
- Tabela de símbolos com escopos
- Verificação de tipos
- Detecção de erros lógicos
✓ Gerador de Código
- Transpilação para Python
- Código executável diretamente
Sintaxe 100% Português - Única no mercado acadêmico Didático - Código comentado e organizado Extensível - Fácil adicionar novos recursos Prático - Gera Python executável
Uma linguagem de programação em português
Leonardo Alves Silva - 10723113466 Teoria da computação e compiladores