# ExpandaEVE-Verfassungsreferenz

ExpandaEVE ist die lesbare Form der EVE-Sprache. Es ist das, was du in einer `.eve`-Filterdatei schreibst. Jedes Konstrukt hier wird in [CompactaEVE](page:eve/compacta) übersetzt und dann kompiliert. Diese Seite dokumentiert jedes Konstrukt mit echten Beispielen aus den ausgelieferten Filterdateien.

Für die dokumentweiten Direktiven (`DEFINE`, `LET`, `REALM`, die Regelanweisungen) siehe [Die EVE-Sprache](page:eve/language). Diese Seite handelt vom Rumpf einer Fuzzy-Regel: dem Muster selbst.

## Die Form eines Regelrumpfs

Ein Fuzzy-Regelrumpf hat immer eine Wurzel und kann eine beliebige Anzahl von Konstrukten um sie herum hinzufügen. Die Wurzel ist das Stammwort, auf dem die Regel aufgebaut ist. Alles andere verfeinert sie: Suffixe, Pluralbehandlung, Ausschlüsse, Kontext und so weiter.

```text
HEAR rule
AS
  fuck(WHOLE)
  suffix(NONE OR er OR ers OR ing OR ed OR s)
  FLAG(pf YES)
```

Hier ist `fuck(WHOLE)` die Wurzel, `suffix(...)` fügt erlaubte Endungen hinzu, und `FLAG(pf YES)` kennzeichnet die Kategorie. Die Konstrukte können in jeder Reihenfolge erscheinen, die sich natürlich liest; der Übersetzer erkennt jedes am Schlüsselwort.

## Die Wurzel und ihre Grenzmarker

Die Wurzel ist der Anker einer Regel. Genau ein Wurzelmarker legt fest, wie streng der Treffer an der Wurzel begrenzt ist:

| Marker | Bedeutung |
|--------|---------|
| `(WHOLE)` | Die Wurzel muss als ganzes Wort treffen. Der Kandidat beginnt mit dem Wurzelstamm und die ganze Route läuft bis zu einer Wortgrenze. Wird `[^^]` in CompactaEVE geschrieben. |
| `(ROOT)` | Die Wurzel ist ein Stamm, auf dem Suffixe und Gruppen aufbauen. Sie muss für sich kein ganzes Wort sein. Wird `[*^]` in CompactaEVE geschrieben. |

Verwende `(WHOLE)`, wenn das bloße Wort selbst der Verstoß ist:

```text
  spic(WHOLE)
  PLURAL
```

Verwende `(ROOT)`, wenn du Endungen oder nachfolgende Gruppen anhängst:

```text
  ni(ROOT)
  suffix(g OR ga OR gga OR gger OR gl LETTER t)
  PLURAL
```

!!! warning "Jede Fuzzy-Regel braucht einen Wurzelmarker"
    Ein Regelrumpf ohne `(WHOLE)`- oder `(ROOT)`-Marker kann nicht kompilieren. Der Marker ist das, was den Wurzelstamm vom Rest des Musters trennt.

### Fuzzy-Matching ist automatisch

Eine Fuzzy-Wurzel ist kein literaler Stringtest. Der Matcher toleriert bereits gängige Umgehung: Vokale sind über den Vokalsatz austauschbar, Buchstaben können gedehnt werden, und Gaps (siehe [GAP](#gap-and-letter)) lassen eingefügte Zeichen dort durch, wo du es erlaubst. Du aktivierst das nicht; so treffen Fuzzy-Regeln. Um eine breitere Streuung absichtlicher Falschschreibungen abzufangen, füge [Aliase](#alias-alternate-spellings) und [Skelette](#skeleton-exact-spellings) hinzu.

## suffix: erlaubte Endungen

`suffix(...)` listet Endungen auf, die das Wort nach der Wurzel annehmen darf. Die Arme werden durch `OR` getrennt. Es wird nur eine Suffixgruppe benötigt, aber du kannst mehrere stapeln; jede fügt ein optionales Segment der Reihe nach hinzu.

```text
  bitch(WHOLE)
  suffix(NONE OR es OR ed OR ing OR y OR ier OR iest OR fest OR fests)
```

`NONE` bedeutet, dass die Endung optional ist: das Wort darf direkt an der Wurzel enden. Ohne einen `NONE`-Arm ist das Suffix erforderlich.

Suffixgruppen setzen sich von links nach rechts zusammen, sodass mehrere in Folge eine Kette optionaler Segmente bilden:

```text
  fa(ROOT)
  suffix(g OR gg OR NONE)
  suffix(ggot OR NONE)
  suffix(ggie OR NONE)
```

Ein Suffixarm kann selbst `GAP` oder `LETTER` enthalten (siehe [GAP und LETTER](#gap-and-letter)):

```text
  suffix(g OR ga OR gga OR gger OR gl LETTER t)
```

```text
  suffix(my GAP OR NONE)
```

### PLURAL

`PLURAL` fügt in einem Wort einen reichen Satz von Plural- und Flexionsendungen hinzu. Es expandiert zum eingebauten `s`-Satz von Endungen, sodass eine mit `PLURAL` gekennzeichnete Regel auch `-s`, `-z`, `-es`, `-ing`, `-ed`, `-er`, `-y` und die anderen in der `s`-Funktion deklarierten Mitglieder abfängt.

```text
  dyke(WHOLE)
  PLURAL
```

`PLURAL` liest die Klasse namens `s`. Der ausgelieferte englische Filter deklariert sie als:

```text
LET function(s) BE s OR z OR es OR ez OR ies OR iez OR y>ies OR y>iez OR ing OR ings OR ed OR er OR ers OR y OR ys
```

Ein Arm, der `from>to` geschrieben wird, ist eine Umschreib-Endung: er trifft ein Wort, das auf `to` endet, indem er die Wurzel mit der `from`-Endung stattdessen testet. `y>ies` fängt ein Wort, das auf `ies` endet, so ab, als ob es auf `y` endete, was der Grund ist, warum `baby` und `babies` beide von einer Wurzel erreicht werden. Siehe [Umschreib-Suffixe](page:eve/compacta#rewrite-suffixes) für die Mechanik.

## NEVER: Ausschlüsse

`NEVER(...)` listet Ausdrücke auf, die nicht in der umgebenden Zeile erscheinen dürfen. Wenn irgendein aufgeführter Ausdruck vorhanden ist, feuert die Regel nicht, selbst wenn das Muster andernfalls trifft. So wird eine aggressive Wurzel davon abgehalten, unschuldige Wörter abzufangen.

```text
  wop(WHOLE)
  PLURAL
  NEVER(doowop OR doo wop OR doowap OR doo wap OR dowap OR do wap OR do wop)
```

```text
  gook(WHOLE)
  PLURAL
  NEVER(600k OR 900k OR 60ok OR 90ok OR 6ook OR 9ook OR 600ks OR 900ks)
```

Eine `NEVER`-Prüfung ist ein einfacher Teilstring-Test gegen die ganze Zeile, kleingeschrieben. Wenn der Ausdruck irgendwo in der Nachricht ist, wird die Regel vetoiert.

## ALIAS: alternative Schreibweisen

`ALIAS(...)` fügt eine alternative Schreibweise der Wurzel hinzu. Jeder Alias ist eine separate Wurzelvariante, die den Rest der Regel (ihre Suffixe, Gruppen, Ausschlüsse) wiederverwendet. Liste einen Alias pro Zeile auf, um absichtliche Falschschreibungen und Buchstabenvertauschungen abzudecken.

```text
  ALIAS(phuck)
  ALIAS(fuk)
  ALIAS(fukk)
  ALIAS(fucc)
  ALIAS(fck)
  ALIAS(fk)
  fuck(WHOLE)
  suffix(NONE OR er OR ers OR ing OR ed OR s)
```

Jeder Alias hier trifft mit demselben Suffixsatz wie `fuck`. Ein Alias kann seinen eigenen `(WHOLE)`- oder `(ROOT)`-Marker tragen; ohne einen erbt er die Grenze der Wurzel.

Ein Alias kann eine Funktion referenzieren, in welchem Fall jedes Mitglied dieser Funktion zu einem Alias wird:

```text
  ALIAS(function(selfharmverb))
  kill(ROOT)
```

Ein Alias kann auch ein segmentiertes Wort oder ein mehrteiliges Fragment sein; er wird auf dieselbe Weise wie die Wurzel normalisiert.

## ALSO: additive Fragmente

`ALSO(...)` fügt ein Fragment hinzu, das überall nach der Wurzel erscheinen darf, statt in fester Reihenfolge. Es wird verwendet, wenn ein erforderliches zusätzliches Wort relativ zum Stamm schweben kann.

```text
  kill(ROOT)
  GAP
  suffix(yo OR ur OR your OR yor)
  suffix(self)
  ALSO(wrists OR wrist OR throat)
```

`ALSO` wird zu einer schwebenden Gruppe heruntergebrochen, die an jeder erreichbaren Position nach der Wurzel und den normalen Gruppen andockt. Siehe [Plus-Gruppen](page:eve/compacta#plus-groups-floating) dafür, wie eine schwebende Gruppe getroffen wird.

## GAP und LETTER

Diese Kürzel steuern, was zwischen Teilen eines Musters sitzen darf.

| Konstrukt | Bedeutung | CompactaEVE |
|-----------|---------|-------------|
| `GAP` | Ein optionaler Lauf beliebiger Zeichen (Buchstaben oder Nicht-Buchstaben), sodass eingefügte Leerzeichen, Interpunktion oder Füller toleriert werden. | `(#*)` |
| `LETTERS` | Ein optionaler Lauf nur aus Buchstaben. | `($^)` |
| `LETTER` | Genau ein Zeichen Wortmaterial. | `@` |

`GAP` zwischen einer Wurzel und einem Suffix lässt einen Ausdruck sich über Wörter hinweg ausbreiten:

```text
  moon(ROOT)
  GAP
  suffix(cricket)
  PLURAL
```

Dies fängt `moon cricket`, `mooncricket` und Schreibweisen mit Füller zwischen den beiden Teilen ab. `LETTER` trifft ein einzelnes Zeichen, nützlich innerhalb eines Suffixarms, um eine Wildcard-Position zuzulassen:

```text
  suffix(m LETTER GAP OR NONE)
```

`LETTERS` trifft einen Lauf nur aus Buchstaben, es hört also an einem Leerzeichen auf:

```text
  my(ROOT)
  GAP
  LETTERS
  GAP
  suffix(hit)
```

!!! note "Was als Buchstabe zählt"
    Wortmaterial ist ein ASCII-Buchstabe oder ein beliebiges Byte einer Nicht-ASCII-Glyphe, sodass ein Emoji- oder Symbollauf ebenfalls als Wortmaterial für Grenzen und die `LETTER`-Wildcard zählt. Reiner ASCII-Text ist unberührt.

## OR und NONE

`OR` trennt Alternativen innerhalb eines Konstrukts wie `suffix(...)`, `NEVER(...)`, `ALSO(...)`, `BEFORE(...)` und `AFTER(...)`, und es trennt Klassenmitglieder in einer `LET`-Deklaration. Es muss als ganzes Wort stehen.

`NONE` ist eine leere Alternative. In einem Suffix macht es die Endung optional; in einer Funktionsmitgliederliste lässt es die Klasse einen leeren Treffer beitragen:

```text
LET function(quantifier) BE NONE OR some OR any OR a OR an OR the
```

## BEFORE und AFTER: Kontext-Gating

Diese gaten eine Regel anhand von Text anderswo in der Zeile. Sie werden verwendet, um einen andernfalls breiten oder mehrdeutigen Begriff nur in einem aufschlussreichen Kontext feuern zu lassen.

| Konstrukt | Bedeutung | CompactaEVE |
|-----------|---------|-------------|
| `BEFORE(...)` | Ein Precheck. Die Regel aktiviert sich nur, wenn einer der aufgeführten Ausdrücke in der umgebenden Zeile erscheint. | `{pre:...}` |
| `AFTER(...)` | Eine Post-Bedingung. Erlaubte Endungen, die die Regel am Wort selbst feuern lassen, auch ohne einen anwesenden Precheck-Ausdruck. | `{post:...}` |

```text
  BEFORE(function(seeking))
  cp
  AFTER(mega OR pack OR packs OR nz OR db OR dropbox OR folder OR vids OR pics)
  (WHOLE)
```

Ein `BEFORE`-Ausdruck ist eine einfache Teilstring-Prüfung gegen die ganze Zeile, kleingeschrieben. Wenn eine Regel ein `BEFORE`-Gate hat, bleibt sie inaktiv, sofern nicht einer der Ausdrücke vorhanden ist, oder das Wort die `AFTER`-Post-Bedingung selbst erfüllt. `AFTER` akzeptiert ein nachfolgendes Plural-`s` bei seinen Endungen. Siehe [Gating](page:eve/compacta#precheck-and-post-gating) für die genaue Regel.

## SWAP: Inline-Substitutionssatz

`SWAP(...)` trifft einen beliebigen von mehreren kleinen Fragmenten an einer Position, mit Kontrolle über Wortgrenzen. Es wird dort verwendet, wo ein kurzes austauschbares Stück innerhalb eines Ausdrucks sitzt.

```text
  kill(ROOT)
  GAP
  SWAP(my* OR me*)
  suffix(self)
```

Jeder Arm kann Sternchen tragen, die eine Grenze freigeben:

- Ein führendes `*` gibt den Start frei (der Arm muss nicht an einer Wortgrenze beginnen).
- Ein nachfolgendes `*` gibt das Ende frei.
- Kein Sternchen oder ein doppelt führendes `**` verankert beide Seiten an einer Wortgrenze.

So trifft `my*` das Wort `my` mit einer erforderlichen Grenze davor, aber nicht notwendigerweise danach, sodass es in `self` hineinlaufen kann. Siehe [Swaps](page:eve/compacta#swaps) für die Grenzregeln in voller Länge.

## SKELETON: exakte Schreibweisen

`SKELETON(...)` listet exakte Wortformen auf, die die Regel auch direkt trifft, unter Umgehung des Fuzzy-Matchers. Es wird verwendet, um bestimmte verschleierte Schreibweisen mit Inline-Auswahllisten festzunageln.

```text
  ni(ROOT)
  suffix(g OR ga OR gga OR gger OR gl LETTER t)
  PLURAL
  NEVER(snigger OR sniggers OR sniggered)
  SKELETON(n[a,e,i,o,u]gg[a,e,i,o,u]r OR n[a,e,i,o,u]gg[a,e,i,o,u]h)
```

Ein Skelett wird in den vollständigen Satz konkreter Wörter expandiert, die es buchstabieren kann, und jeder Kandidat, der einem dieser Wörter gleicht, trifft sofort. Die Expansion nimmt das Kreuzprodukt jeder Auswahl, sodass `n[a,e,i,o,u]gg[a,e,i,o,u]r` die Wörter `naggar`, `neggar`, `niggar` und so weiter für jedes Vokalpaar erzeugt.

### Inline-Auswahllisten

Innerhalb eines Skeletts ist `[a,e,i,o,u]` eine Inline-Auswahlliste: eine Zeichenposition, die jedes der kommagetrennten Mitglieder sein kann. Mitglieder können länger als ein Zeichen sein. Whitespace um ein Mitglied wird entfernt. Ein Skelett kann auch eine Funktion mit `&name` referenzieren, die zu den Mitgliedern dieser Funktion expandiert.

```text
  SKELETON(r[e,i]t[a,e,i]rd)
```

```text
  SKELETON(m[a,e,i,o,u]st[a,e,i,o,u]rb[a,e,i,o,u]t OR m[a,e,i,o,u]st[a,e,i,o,u]rb[a,e,i,o,u]t[a,e,i,o,u])
```

Das Ergebnis ist kleingeschrieben. Skelette treffen die exakte Schreibweise, sie ergänzen also die Fuzzy-Wurzel, die die lockereren Varianten behandelt.

## FUNCTION: benannte Klassen

Eine Funktion ist eine benannte Klasse, die mit `LET` deklariert wird (siehe [Die EVE-Sprache](page:eve/language#let-defining-a-function-named-class)). Sie wird mit `function(name)` referenziert, und die Referenz expandiert zu den Klassenmitgliedern. Funktionen haben mehrere Rollen, je nachdem, wo sie erscheinen.

Als ganze Gruppe von Alternativen in einem Regelrumpf:

```text
  groom(ROOT)
  suffix(NONE OR ing OR ed)
  GAP
  MAYBE function(declarative)
  GAP
  function(vulnerable)
```

Als Alias, wobei jedes Mitglied zu einer alternativen Wurzel wird:

```text
  ALIAS(function(genderword))
  internal
  GAP
  condom(WHOLE)
```

Innerhalb einer `suffix`-, `NEVER`-, `ALSO`-, `BEFORE`- oder `AFTER`-Liste, wo die Mitglieder sich den Alternativen anschließen:

```text
  suffix(function(article) OR box of OR a box of OR internal OR function(genderword) OR NONE)
```

### Funktionsmodifikatoren

Eine `function(...)`-Referenz kann Modifikatoren tragen, verbunden mit `+`:

| Modifikator | Wirkung | CompactaEVE |
|----------|--------|-------------|
| `ADDITIVE` | Die Referenz ist eine schwebende Ergänzung zum Treffer statt eine Anforderung fester Reihenfolge. | wird als Plus-Gruppe `[+[...]]` umhüllt |
| `GAP` | Die Referenz trifft locker und erlaubt ein Gap danach. | hängt `(#*)` an |

```text
  function(subject + ADDITIVE + GAP)
  function(desire + ADDITIVE + GAP)
  function(quantifier + ADDITIVE + GAP)
  rap(ROOT)
  suffix(e OR ist OR ed OR ing OR eable OR able)
  PLURAL
```

Jede additive Funktion hier schwebt dorthin in den Treffer, wo sie passt, sodass die Subjekt-, Wunsch- und Quantorwörter in wechselnder Reihenfolge vor der Wurzel erscheinen dürfen.

## MAYBE FUNCTION: optionale Funktion

`MAYBE FUNCTION(name)` macht eine Funktionsreferenz optional: der Treffer gelingt, ob eines ihrer Mitglieder vorhanden ist oder nicht.

```text
  rap(ROOT)
  suffix(NONE OR e OR es OR ed OR ing OR eing OR in OR ist OR ists)
  GAP
  MAYBE function(declarative)
  GAP
  function(vulnerable)
```

Hier darf `function(declarative)` (Wörter wie `a`, `the`, `my`) zwischen dem Verb und dem Wort für die verletzliche Person erscheinen oder nicht.

## FLAG: bedingte Regeln und Kategoriekennzeichnung

`FLAG(name YES)` kennzeichnet die Regel mit einem deklarierten Flag. Wenn die Regel feuert, wird dieses Flag gesetzt, was der Weg ist, wie der Filter eine Kategorie wie Selbstverletzung oder Missbrauch statt einer gewöhnlichen Blockierung meldet.

```text
  kms(WHOLE)
  FLAG(sh YES)
```

Der Wert kann `YES`, `Y` oder `TRUE` für an und alles andere für aus geschrieben werden. Der Flag-Name muss mit `DEFINE` deklariert sein (siehe [Die EVE-Sprache](page:eve/language#define-declaring-flag-ids)), sonst schlägt das Laden des Dokuments fehl. Unter der Haube wickelt ein Flag das Muster in ein bedingtes Gate; siehe [Flag-Wrapper](page:eve/compacta#flag-wrappers).

## NOTE: Kommentare

`NOTE(...)` hängt einen Inline-Kommentar an. Er wird vor der Kompilierung entfernt und beeinflusst das Matching nicht, er ist also ein Weg, ein Muster an Ort und Stelle zu annotieren. Ganzzeilige Kommentare verwenden weiterhin ein führendes `#`.

## ALIAS mit WHOLE- oder ROOT-Markern

Ein Alias kann auf `(WHOLE)` oder `(ROOT)` enden, um seine eigene Grenze zu setzen, unabhängig von der Wurzel:

```text
  ALIAS(dike)
  dyke(WHOLE)
```

Ohne einen nachfolgenden Marker erbt der Alias den Grenzmarker der Wurzel.

## Segmentierte Wurzeln

Eine Wurzel kann als mehrere geklammerte und bloße Stücke geschrieben werden, um einen Teil davon als flektierbar zu markieren. Wenn mindestens zwei Stücke vorhanden sind und mindestens eines geklammert ist, falten sie sich zu einer einzigen Wurzel mit alternativen Einstiegspunkten zusammen.

```text
  re[tard] (WHOLE)
  suffix(NONE OR d OR ded OR ted OR t OR der OR ders OR ing OR ed OR s)
```

Das geklammerte Stück markiert das flektierbare Segment. Siehe [Segmentierte Wurzeln](page:eve/compacta#segmented-roots) dafür, welche Alternativen genau erzeugt werden.

## Alles zusammensetzen

Eine realistische Regel kombiniert mehrere Konstrukte:

```text
HEAR rule
AS
  ALIAS(masterb)
  masturb(ROOT)
  suffix(ate OR ating OR ation OR ated OR ates OR at)
  SKELETON(m[a,e,i,o,u]st[a,e,i,o,u]rb[a,e,i,o,u]t OR m[a,e,i,o,u]st[a,e,i,o,u]rb[a,e,i,o,u]t[a,e,i,o,u])
```

Diese Regel hat einen Alias für eine gängige Falschschreibung, eine Wurzel mit einem festen Suffixsatz und Skelette für die Leetspeak-Schreibweisen, die der Fuzzy-Matcher übersehen könnte. Lies [CompactaEVE](page:eve/compacta), um zu sehen, wie jedes davon heruntergebrochen wird und trifft.
