# A linguagem EVE

A EVE é o motor de correspondência de padrões por trás do filtro de chat do Verité. Vem com a sua própria pequena linguagem para criar ficheiros de filtro. Esta página é o guia de topo: o que é a EVE, como um ficheiro de filtro está estruturado e as diretivas que compõem um documento. Cada um dos dois dialetos tem a sua própria página:

- O [ExpandaEVE](page:eve/expanda) é a forma explícita que se escreve à mão. Utiliza palavras como `HEAR`, `SUFFIX`, `NEVER` e `PLURAL`.
- O [CompactaEVE](page:eve/compacta) é a forma compilada e concisa e a semântica do correspondente por baixo dela. Cada construção do ExpandaEVE é reduzida a um símbolo do CompactaEVE antes de correr.

## O que é a EVE

A EVE lê um documento de filtro e produz um conjunto de regras compiladas. Cada regra é um padrão que decide se uma palavra candidata (ou, para alguns tipos de regra, uma mensagem inteira) é uma correspondência. O motor é deliberadamente tolerante à evasão: uma regra difusa corresponde através de trocas de vogais, lacunas inseridas, letras esticadas e truques semelhantes, por isso uma única raiz criada apanha muitas grafias sem que o autor liste cada uma.

Um ficheiro de filtro é texto UTF-8 simples. As linhas que estão em branco ou começam por `#` são ignoradas, por isso `#` inicia um comentário de linha inteira.

## As duas formas e como se relacionam

Cria em ExpandaEVE. Quando um documento é carregado, cada instrução é traduzida para CompactaEVE, e o CompactaEVE é compilado no correspondente executável. O fluxo é:

```text
ExpandaEVE source  ->  CompactaEVE source  ->  compiled rules
     (authoring)          (terse form)          (the matcher)
```

A tradução é puramente uma reescrita. Tudo o que pode expressar em ExpandaEVE torna-se CompactaEVE real, e cada decisão de correspondência é tomada pela forma compilada. Um documento também pode ser escrito diretamente em CompactaEVE: os verbos das instruções são as mesmas palavras em minúsculas (`hear`, `match`, `let`, `define`, `realm`, e assim por diante), e uma instrução que não utilize nenhuma construção exclusiva do ExpandaEVE passa pelo tradutor quase textualmente.

!!! note "Que forma devo ler?"
    Se está a escrever ou a ler ficheiros `.eve`, comece pelo [ExpandaEVE](page:eve/expanda). Leia o [CompactaEVE](page:eve/compacta) quando quiser compreender exatamente como um padrão corresponde, ou quando estiver a ler a saída compilada.

## Estrutura do documento

Um documento é uma sequência de instruções, uma por linha lógica. As palavras-chave de instrução reconhecidas são `DEFINE`, `LET`, `REALM`, `HEAR`, `FIND`, `MATCH`, `ANYWHERE` e `SEQUENCE`, mais a linha de cabeçalho `eve:`. Qualquer linha que não esteja em branco, não seja um comentário e não comece por uma palavra-chave reconhecida levanta um erro em vez de ser ignorada.

### O cabeçalho eve:

Uma primeira linha opcional declara a versão e o idioma:

```text
eve: 1.0 English
```

O texto após `eve:` até ao primeiro espaço é a versão. O restante é o nome do idioma. Ambos são registados no programa compilado. Um cabeçalho apenas com uma versão e sem idioma é aceite.

### DEFINE: declarar ids de flags

`DEFINE` regista um nome de flag e o id para o qual mapeia. Cada flag que uma regra define com `FLAG(...)` tem de ser declarada, ou o documento não carrega.

```text
DEFINE sh AS selfharm
DEFINE ea AS abuse
DEFINE pf AS profanity
```

O nome à esquerda é o que as regras referenciam. O id à direita é a categoria que o filtro reporta. Consulte [Flags](page:eve/expanda#flag-conditional-rules-and-category-tagging) para saber como as regras as utilizam.

### LET: definir uma função (classe nomeada)

`LET function(name) BE ...` declara uma classe nomeada: uma lista de palavras ou fragmentos intercambiáveis que uma regra pode invocar pelo nome. No CompactaEVE a mesma classe escreve-se `let &name be ...`.

```text
LET function(genderword) BE female OR girl OR woman OR male OR guy OR guys OR men OR man
```

Os membros são separados por `OR`. Uma vez declarada, uma classe é referenciada noutro lugar com `function(name)` no ExpandaEVE ou `&name` no CompactaEVE. Uma referência de classe expande-se para todos os seus membros. As classes podem carregar um marcador `(WHOLE)` ou `(ROOT)` predefinido no nome, que é herdado pelas referências a menos que a referência o substitua:

```text
LET function(frenchstuff) (WHOLE) BE franger OR frenchie OR jizzbag
```

Consulte [Funções e classes](page:eve/expanda#function-named-classes) para a referência completa, incluindo como uma classe é utilizada como raiz, como grupo, como alias e dentro de um esqueleto.

!!! note "Classes numeradas e vogais"
    Uma classe cujo nome é feito inteiramente de dígitos contribui com os seus membros de um único carácter para o conjunto de vogais incorporado que a correspondência relaxada utiliza. É assim que o alfabeto de vogais para a tolerância a leetspeak é montado. Consulte [Esqueletos](page:eve/expanda#skeleton-exact-spellings) e a [lista de classes de caracteres](page:eve/expanda#inline-choice-lists).

### REALM: agrupar regras

`REALM` define o realm a que todas as regras seguintes pertencem, até ao próximo `REALM`. Um realm é um rótulo utilizado para organizar e delimitar regras. Não altera a forma como uma regra corresponde.

```text
REALM racial_and_ethnic_slurs
```

Cada regra `HEAR`, `FIND`, `MATCH`, `ANYWHERE` e `SEQUENCE` que se segue carrega esse nome de realm até que declare um realm diferente.

### As instruções de regra

Cinco instruções declaram regras. Cada uma escreve-se como o verbo, um nome, a palavra-chave `AS` e um corpo. O nome e o corpo podem abranger várias linhas: o corpo corre até à próxima palavra-chave de instrução no início de uma linha.

| Instrução | Tipo de regra | Corresponde a |
|-----------|-----------|---------|
| `HEAR name AS ...` | Difusa | Uma única palavra, tolerante à evasão. Este é o caso comum. |
| `FIND name AS ...` | Difusa | Idêntica a `HEAR`. Uma grafia alternativa do mesmo verbo. |
| `MATCH name AS ...` | Estrita | Toda a entrada, com classes exatas e capturas. Consulte [Regras estritas](page:eve/compacta#strict-rules-match). |
| `ANYWHERE name AS ...` | Anywhere | Dispara quando cada grupo listado aparece algures na mensagem. |
| `SEQUENCE name AS ...` | Sequence | Uma sequência ordenada de glifos que aparecem por ordem ao longo da mensagem. |

`HEAR` e `FIND` são o mesmo tipo de regra, por isso este guia utiliza `HEAR` em todo o texto. O corpo de uma regra difusa é um padrão ExpandaEVE completo: uma raiz mais qualquer uma das construções na [página do ExpandaEVE](page:eve/expanda).

!!! note "ANYWHERE e SEQUENCE"
    `ANYWHERE` constrói uma regra de coocorrência: o corpo é uma lista de grupos separados por `WITH`, e a regra dispara apenas quando pelo menos um membro de cada grupo é encontrado algures na mensagem. Cada membro é compilado como o seu próprio correspondente difuso de palavra inteira, por isso os membros continuam a tolerar a evasão. Uma regra `ANYWHERE` precisa de pelo menos dois grupos.

    `SEQUENCE` é utilizada para padrões ordenados de símbolos e emoji e está documentada com o quadro de símbolos, que é abordado separadamente. Dispara quando todos os seus passos de glifos aparecem por ordem ao longo da mensagem, e um prefixo `mirror` também aceita a ordem inversa. Uma regra `SEQUENCE` precisa de pelo menos dois glifos.

## Um ficheiro mínimo completo

```text
eve: 1.0 English

DEFINE pf AS profanity

REALM profanity

HEAR rule
AS
  shit(WHOLE)
  suffix(NONE OR s OR ty OR head OR heads)
  NEVER(shitake OR shiitake OR mishit)
  FLAG(pf YES)
```

Isto declara uma flag, abre um realm e adiciona uma regra difusa. A regra corresponde à palavra inteira `shit` com qualquer uma das terminações listadas, recusa as palavras inocentes listadas e reporta a categoria `profanity`. Leia a [referência do ExpandaEVE](page:eve/expanda) para cada construção utilizada aqui.
