Pular para o conteúdo

O lexer

Texto em tokens: indentação vira INDENT e DEDENT, a interpolação vira partes, e // decide entre comentário e divisão.

O lexer lê o texto caractere por caractere e entrega tokens: cada um com tipo, valor, linha e coluna. É a linha e a coluna que fazem todo erro posterior apontar o lugar certo — um token sem posição produziria um erro sem seta.

dataforge
adopt Arcane.Compilador as Comp

tipos := [t["tipo"] cycle t in Comp.tokens("given x bigger 1:\n    out x\n")]
assert tipos.contains("INDENT") and tipos.contains("DEDENT")
assert Comp.tokens("total := 7")[2] is {"tipo": "INTEGER", "valor": 7, "linha": 1, "coluna": 10}

A indentação vira token#

A linguagem marca bloco por recuo, e o parser não conta espaços: o lexer mantém uma pilha de recuos e emite INDENT quando o recuo cresce e um DEDENT para cada nível que fecha. Tabulação é recusada (SyncError) — dois editores mostram um tab com larguras diferentes, e um bloco pareceria certo em um e errado no outro.

`//`: comentário ou divisão?#

// é comentário por padrão, e vira divisão inteira só quando o que vem depois é um número, (, ou uma chamada/índice/membro. É por isso que total // 2 divide e total // nota comenta — e é a regra que exige cuidado com comentário que começa com número:

dataforge
adopt Arcane.Compilador as Comp

divide := [t["tipo"] cycle t in Comp.tokens("x := a // 2")]
comenta := [t["tipo"] cycle t in Comp.tokens("x := a // metade")]
assert divide.contains("FLOOR_DIV")
assert not comenta.contains("FLOOR_DIV")