Pular para o conteúdo

O parser

Descida recursiva: uma função por nível de precedência, a recuperação que junta vários erros, e o fim de linha exigido.

O parser é descendente recursivo: uma função por construção da gramática, e uma por nível de precedência. 1 + 2 * 3 vira + na raiz porque a função da soma chama a da multiplicação para ler cada lado — a precedência está na ordem das chamadas, e não numa tabela.

dataforge
adopt Arcane.Compilador as Comp

raiz := Comp.arvore("x := 1 + 2 * 3")["corpo"][0]["valor"]
assert raiz["op"] is "+"
assert raiz["direita"]["op"] is "*"               // o * ficou mais fundo: liga mais forte
Do mais fracoao mais forte
>> (pipeline)a mais fraca de todas
a given c otherwise bo ternário
??abaixo de orx ?? 0 is 0 é x ?? (0 is 0): o check avisa
or · and · not
is, bigger, smallerencadeiam: 1 smaller x smaller 9
+ - · * / ~/ % · **** associa à direita
unário, chamada, índice, membroo mais forte

Vários erros de uma vez#

Um parser que para no primeiro erro obriga a corrigir, compilar e corrigir uma vez por erro. Este registra o erro, ressincroniza no começo da próxima instrução e continua: quem lê recebe os quatro erros do arquivo de uma vez. O erro que viaja continua sendo um só, e os demais vão em outros.

Uma instrução por linha#

Depois de uma instrução completa, a linha tem de acabar. x := 1 vazios era aceito como duas instruções — x := 1 e vazios —, e o caso que custou caro foi o comentário começando com número, que virava uma divisão seguida de uma instrução solta. Dezessete blocos desta documentação só "compilavam" por isso; hoje todos compilam de verdade.

dataforge
adopt Arcane.Compilador as Comp

recusado := no
monitor:
    Comp.arvore("x := 1 vazios")
handle Error as e:
    recusado := e.message.contains("same line")
assert recusado