invalid character in source — Como Resolver em Zig

invalid character in source — Como Resolver em Zig

O Que Este Erro Significa

O erro invalid character in source ocorre quando o compilador Zig encontra um caractere no código-fonte que não é permitido fora de strings e comentários. Zig é rigoroso sobre quais caracteres são válidos no código-fonte: apenas ASCII imprimível (exceto certas exceções), newlines e tabs em contextos específicos. Caracteres Unicode fora de strings literais, caracteres de controle invisíveis e marcas BOM (Byte Order Mark) são rejeitados.

Causas Comuns

1. BOM (Byte Order Mark) no Início do Arquivo

Alguns editores (especialmente no Windows) adicionam um caractere BOM (U+FEFF) invisível no início de arquivos UTF-8:

// O arquivo começa com bytes invisíveis: EF BB BF
const std = @import("std"); // ERRO: invalid character

2. Caracteres Unicode em Identificadores

pub fn main() void {
    const preço = 42; // ERRO: 'ç' não é ASCII válido em identificadores
    _ = preço;
}

3. Aspas Inteligentes (Smart Quotes)

Copiando código de editores de texto ou páginas web, você pode acabar com aspas curvas:

pub fn main() void {
    const nome = "Zig"; // ERRO: aspas curvas " " ao invés de retas " "
    _ = nome;
}

4. Espaço Não-Quebrável (Non-Breaking Space)

O caractere U+00A0 (non-breaking space) se parece com um espaço normal, mas não é:

pub fn main() void {
    const x = 42; // ERRO: espaço invisível errado entre 'const' e 'x'
    _ = x;
}

5. Tab em Local Inadequado

Zig tem regras específicas sobre onde tabs são permitidos. O zig fmt converte tabs para espaços:

pub fn main() void {
	const x = 42; // Tab para indentação — pode causar aviso
	_ = x;
}

6. Caracteres de Controle Copiados Acidentalmente

pub fn main() void {
    const x = 42; // Pode conter Ctrl+M (^M / \r) em arquivos do Windows
    _ = x;
}

Como Corrigir

Solução 1: Remover BOM do Arquivo

No Linux/macOS:

# Verificar se o arquivo tem BOM
file src/main.zig
# Remover BOM
sed -i '1s/^\xEF\xBB\xBF//' src/main.zig

No VS Code: abra o arquivo, clique em “UTF-8 with BOM” no canto inferior direito e selecione “UTF-8” (sem BOM).

Solução 2: Usar Apenas ASCII em Identificadores

pub fn main() void {
    const preco = 42; // Correto: 'preco' sem acentos
    _ = preco;
}

Se precisar de texto com acentos, use strings:

const nome_display = "Preço"; // Unicode é permitido dentro de strings

Solução 3: Substituir Aspas Inteligentes

pub fn main() void {
    const nome = "Zig"; // Correto: aspas retas
    _ = nome;
}

Solução 4: Usar zig fmt

O formatador do Zig pode corrigir alguns desses problemas automaticamente:

zig fmt src/main.zig

Solução 5: Converter Fins de Linha

Converta \r\n (Windows) para \n (Unix):

# No Linux/macOS
dos2unix src/main.zig

# Ou com sed
sed -i 's/\r$//' src/main.zig

Solução 6: Reescrever o Arquivo

Se nada mais funcionar, crie um novo arquivo e copie apenas o texto visível:

# Copiar apenas caracteres ASCII imprimíveis + newlines
tr -cd '\11\12\15\40-\176' < src/main.zig > src/main_clean.zig
mv src/main_clean.zig src/main.zig

Como Prevenir

Configurar o Editor Corretamente

VS Code — adicione ao settings.json:

{
    "files.encoding": "utf8",
    "files.eol": "\n",
    "editor.renderControlCharacters": true,
    "files.trimTrailingWhitespace": true
}

Vim — adicione ao .vimrc:

set encoding=utf-8
set fileformat=unix
set list

Usar .editorconfig

Crie um arquivo .editorconfig no projeto:

[*.zig]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
insert_final_newline = true

Verificar com xxd ou hexdump

Para encontrar caracteres invisíveis problemáticos:

xxd src/main.zig | head -5
# Procure por bytes fora do range 20-7E (exceto 0A e 0D)

Caracteres Válidos no Código-Fonte Zig

  • Identificadores: letras ASCII (a-z, A-Z), dígitos (0-9), underscore (_)
  • Strings: qualquer sequência de bytes UTF-8 válida
  • Comentários: qualquer sequência de bytes UTF-8 válida
  • Whitespace: espaço (0x20), newline (0x0A)

Perguntas Frequentes

Posso usar nomes de variáveis com acentos em Zig de alguma forma?

Não diretamente como identificadores — Zig só permite ASCII em nomes de variáveis, funções, tipos e constantes. Isso é uma decisão deliberada de design para garantir portabilidade e evitar ambiguidades de encoding. A alternativa aceita pela comunidade é usar o equivalente sem acento (por exemplo, preco em vez de preço, configuracao em vez de configuração). Para strings e comentários, Unicode é totalmente suportado — você pode ter const nome_display = "Preço" e comentários em português com todos os acentos. O formatador zig fmt também ajuda a identificar problemas de encoding ao formatar o arquivo.

Por que o erro de caractere inválido às vezes aponta para a linha errada?

Caracteres invisíveis como BOM (U+FEFF) ou non-breaking spaces (U+00A0) podem causar essa confusão. O BOM, por exemplo, é inserido antes do primeiro caractere do arquivo, então o compilador reporta o erro na linha 1, coluna 1, mas você não vê nada de errado ao olhar o arquivo no editor. A ferramenta xxd é especialmente útil nesses casos: execute xxd src/main.zig | head -3 e verifique se o arquivo começa com ef bb bf (que é a representação hexadecimal do BOM UTF-8). Se começar com esses bytes, use sed ou a configuração do editor para salvar sem BOM.

Como o zig fmt trata caracteres inválidos?

O zig fmt pode resolver alguns problemas de encoding, como normalizar fins de linha de \r\n para \n, mas não consegue adivinhar qual caractere Unicode você quis usar em um identificador. Para BOM e non-breaking spaces em whitespace, o formatador geralmente consegue corrigir. Para aspas inteligentes ou caracteres em identificadores, você precisará fazer a correção manualmente antes de executar zig fmt. Uma boa prática é sempre executar zig fmt como parte do pipeline de CI para garantir que o código está devidamente formatado.

Erros Relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.