CompactaEVE et la sémantique de correspondance
CompactaEVE est la forme compilée concise du langage EVE, et l’entrée que le compilateur de motifs analyse réellement. Chaque construction ExpandaEVE est abaissée en un symbole CompactaEVE avant de s’exécuter. Cette page documente les symboles compacts, ce que le compilateur accepte, et comment un motif compilé décide si un candidat correspond.
Vous n’avez pas à écrire CompactaEVE à la main : le traducteur ExpandaEVE le produit. Mais le lire est utile pour comprendre exactement comment un motif se comporte, et un document peut être rédigé directement dans le dialecte compact.
Les formes d’énoncé compactes
Les directives de niveau document conservent les mêmes noms en minuscules :
| ExpandaEVE | CompactaEVE |
|---|---|
DEFINE name AS id |
define name as id |
LET function(name) BE a OR b |
let &name be a|b |
REALM x |
realm x |
HEAR n AS body / FIND n AS body |
hear n as body |
MATCH n AS body |
match n as body |
ANYWHERE n AS ... |
anywhere n as g1 !! g2 |
SEQUENCE n AS ... |
sequence n as ... |
Les membres de classe et les branches de groupe sont séparés par la barre | plutôt que par OR. Une classe est référencée par &name. Le reste de cette page couvre le corps de motif d’une règle floue, où résident les symboles compacts.
Marqueurs de racine
Un seul marqueur de racine sépare le radical de la racine du reste du motif :
| Symbole | Depuis ExpandaEVE | Signification |
|---|---|---|
[^^] |
(WHOLE) |
La racine correspond comme un mot entier. Le parcours doit courir jusqu’à une frontière de mot. |
[*^] |
(ROOT) |
La racine est un radical sur lequel les parties ultérieures s’appuient. |
Le texte avant le marqueur est le radical de la racine. ni[*^] a le radical ni ; spic[^^] a le radical spic et exige une correspondance de mot entier.
Parties : les morceaux d’un fragment
Un fragment (une racine, une branche de groupe, un suffixe) est analysé en une liste ordonnée de parties. Le compilateur reconnaît ces jetons ; tout le reste s’accumule comme une suite littérale.
| Jeton | Type | Correspond à |
|---|---|---|
| texte brut | Littéral | Les caractères exacts, dans l’ordre. |
@ |
Any | Exactement un caractère de matière de mot. |
(#*) |
Gap | Une suite de caractères quelconques, lettres ou non. Non déterministe : elle peut se terminer à toute position atteignable. |
($^) |
Gap (lettres) | Une suite de lettres (matière de mot) uniquement. |
[swap:...] |
Swap | L’une de plusieurs branches alternatives avec des règles de frontière. |
Un littéral correspond exactement. @ consomme un octet de mot. Un gap est la tolérance du moteur aux caractères insérés : il peut sauter zéro ou plusieurs positions, et le matcheur essaie chaque fin atteignable.
Matière de mot
La matière de mot est une lettre ASCII ou tout octet non ASCII. Un glyphe multi-octets tel qu’un emoji est une suite d’octets de mot, de sorte que les suites de glyphes se tokenisent et se délimitent comme des mots. Aucun octet ASCII n’est traité comme un octet de symbole, donc le texte ordinaire est inchangé.
Racines et alternatives de racine
La racine peut prendre trois formes :
- Un radical simple :
masturb[*^]se compile en une racine. - Une référence de classe :
&name...s’étend de sorte que chaque membre de la classe devient une alternative de racine, tout texte suivant étant conservé. - Une racine segmentée
[[..][..]]: voir Racines segmentées.
Les crochets de dérogation en tête et les produits de préfixe génèrent davantage d’alternatives de racine :
[text;]avant la racine remplace le littéral de tête de la racine partext, produisant une orthographe alternative. C’est ce en quoi ALIAS s’abaisse. Une dérogation[text^^;]ou[text*^;]fixe aussi la frontière de cette alternative.[+[a|b]]avant la racine est un produit croisé de préfixes : chaque préfixe listé est préfixé à chaque racine, multipliant les alternatives. C’est ce que ALSO utilise lorsqu’il se trouve avant la racine, et ce en quoi une référence de classe à l’intérieur de[+[...]]s’étend.
Les alternatives de racine sont ordonnées littéral le plus long d’abord, de sorte qu’une orthographe plus spécifique est essayée avant une plus courte. Une alternative de racine est écartée tôt lorsqu’un littéral qu’elle doit consommer est absent du candidat.
Racines segmentées
Une racine segmentée s’écrit [[seg1][seg2]...] où un segment se terminant par * est un point d’entrée. Elle génère des alternatives qui commencent à chaque segment étoilé, éventuellement préfixées par les segments antérieurs. Cela permet à une racine comme re[tard] d’être atteinte à la fois comme mot entier et à partir du segment fléchissable. Une racine segmentée sans point d’entrée étoilé est une erreur.
Suffixes et terminaisons (en fin)
Les terminaisons résident dans la liste de suffixes de fin. En CompactaEVE, elles sont ajoutées avec |[a|b|...] après la racine, ce en quoi suffix(...) s’abaisse. Un parcours ne correspond que lorsque le candidat se termine sur l’un des suffixes de fin et court jusqu’à la fin du mot.
Une branche vide (NONE) rend le suffixe facultatif.
Suffixes de réécriture
Une branche de fin écrite from>to est une réécriture. Elle correspond à un candidat se terminant par to en retirant to, en ajoutant from, et en testant le résultat contre le motif principal. y>ies permet à une racine se terminant par y de correspondre aussi à un mot se terminant par ies, de sorte qu’une seule racine atteint à la fois baby et babies. Le marqueur > est le seul endroit où une réécriture est interprétée, de sorte que chaque lecteur de suffixes de fin s’accorde sur sa signification.
Groupes
Entre la racine et les suffixes de fin, le motif est une séquence de groupes. Un groupe est un ensemble de branches alternatives, dont l’une quelconque peut le satisfaire. Un groupe a un type :
| Type | CompactaEVE | Comportement |
|---|---|---|
| Normal | `[a | b]` |
| Plus (flottant) | `[+[a | b]]` |
| Hard (ancré) | une référence de classe hard | Une alternative ancrée appariée depuis le début. |
Une branche vide rend son groupe facultatif. Un groupe écrit comme un gap nu, (#*) ou ($^), est un groupe de gap facultatif, ce en quoi un GAP ou LETTERS autonome entre les parties s’abaisse.
Références de classe comme groupes
&name en position de groupe étend la classe en un groupe de branches, une par membre. &!name rend le groupe facultatif (une branche vide supplémentaire est ajoutée), ce en quoi MAYBE FUNCTION s’abaisse. Une référence peut porter [^^] ou [*^] pour forcer une correspondance hard ou soft ; sinon, elle hérite de la dureté déclarée de la classe. Une référence de classe hard devient un groupe ancré hard.
Groupes plus (flottants)
Un groupe plus [+[...]] ne se place pas dans un ordre fixe. Une fois la racine et les groupes normaux consommés, le matcheur calcule chaque position atteignable et laisse le groupe plus s’attacher à l’une quelconque d’entre elles, courant jusqu’à la fin du mot. C’est ainsi que les fonctions ADDITIVE et ALSO flottent par rapport au radical.
Swaps
[swap:a|b] correspond à une branche quelconque à une position. Chaque branche porte des drapeaux de frontière décidés par ses astérisques :
- Un seul
*de tête libère la frontière de début. - Un seul
*de fin libère la frontière de fin. - Aucun astérisque, ou un double
**de tête, ancre les deux côtés.
Un côté ancré exige une frontière de mot à cet endroit : le début doit suivre un octet non-mot (ou être le début de la chaîne), et la fin doit précéder un octet non-mot (ou être la fin de la chaîne). Un swap peut être écrit en ligne dans un fragment ou comme son propre groupe.
Exclusions (veto)
[-[a|b]] est une liste de veto, ce en quoi NEVER s’abaisse. Chaque phrase listée est un test de sous-chaîne simple contre la ligne entière, en minuscules. Si une phrase quelconque est présente, le motif ne se déclenche pas, quel que soit le reste de la correspondance.
Contrôle en amont et en aval
Deux constructions conditionnent un motif sur la ligne environnante :
{pre:a|b}est un contrôle en amont, issu de BEFORE. Le motif reste inerte à moins que l’une des phrases ne soit une sous-chaîne de la ligne, en minuscules.{post:a|b}est une condition en aval, issue de AFTER. Elle est insérée au marqueur de racine comme un groupe de tête facultatif de terminaisons autorisées.
Un motif conditionné (avec un contrôle en amont) ne se déclenche que lorsqu’une phrase de contrôle en amont est présente dans la ligne, ou lorsque le candidat satisfait à lui seul la condition en aval : il commence par le radical de la racine et se termine par l’une des terminaisons en aval, avec un s pluriel de fin toléré. Les faits de contrôle en amont et de veto ne dépendent que de la ligne, non du candidat, ils sont donc calculés une fois par ligne et réutilisés à travers les candidats.
Squelettes
{skel:...} est la liste blanche de squelette, issue de SKELETON. Elle est étendue à la compilation en un ensemble de mots concrets. Un candidat exactement égal à l’un de ces mots correspond immédiatement, avant que le matcheur principal ne s’exécute.
À l’intérieur d’un squelette :
[a,b,c]est une liste de choix en ligne : une position qui peut être n’importe quel membre séparé par une virgule. Les membres peuvent comporter plusieurs caractères. Les espaces autour d’un membre sont supprimés.&names’étend en les membres de cette classe. Un nom de classe numérique s’étend chiffre par chiffre ; une classe nommée s’étend en lettres.
L’expansion est le produit croisé complet de chaque choix, en minuscules.
Enveloppes de flag
{name:y?...} et {name:n?...} enveloppent un motif dans une condition de flag, issue de FLAG. La forme y exige le flag activé, la forme n l’exige désactivé. Plusieurs enveloppes peuvent s’imbriquer. Le nom du flag doit être déclaré avec define, sinon le document échoue au chargement. Les flags déclarés sont ce que le filtre rapporte comme catégorie.
Commentaires
{#c:...} est un commentaire en ligne, issu de NOTE. Il est retiré avant la compilation, y compris les accolades imbriquées. Les commentaires de ligne entière utilisent un # de tête.
Comment un motif flou correspond
Lorsqu’un mot candidat est testé contre un motif flou compilé, le moteur exécute ces vérifications dans l’ordre :
- Conditionnement. Si le motif a un contrôle en amont et que ni une phrase de contrôle en amont n’est présente dans la ligne ni la condition en aval n’est satisfaite, il ne correspond pas. Si une phrase de veto quelconque est présente dans la ligne, il ne correspond pas.
- Squelette. Si le candidat est exactement égal à un mot de squelette, il correspond.
- Correspondance principale. Le moteur principal s’exécute (ci-dessous).
- Repli par réécriture. Pour chaque suffixe de réécriture, si le candidat se termine par le côté
to, le côtéfromest restauré et la correspondance principale est réessayée sur le mot restauré.
La correspondance principale
Le matcheur principal décide si le candidat entier est pris en compte par un parcours :
- Un rejet rapide écarte le candidat lorsqu’il lui manque chaque littéral qu’un parcours principal doit contenir.
- Les groupes ancrés hard sont essayés depuis le début ; un parcours qui atteint une terminaison autorisée correspond.
- Chaque alternative de racine est exécutée depuis le début. Une racine dont les littéraux requis sont absents est écartée. Les fins atteignables alimentent la séquence de groupes normaux.
- Les groupes normaux sont enfilés dans l’ordre à partir des fins de racine. Un parcours correspond lorsqu’il atteint un suffixe de fin autorisé qui court jusqu’à la fin du mot. À moins que le parcours ne soit purement littéral, au moins une branche non vide doit s’être déclenchée.
- Les groupes plus flottants sont essayés à chaque emplacement atteignable, et un groupe plus correspond lorsqu’une de ses branches court d’une ancre atteignable jusqu’à la fin du mot.
Les frontières de mot proviennent de la matière de mot : une frontière existe aux extrémités de la chaîne et partout où un octet non-mot rencontre un octet de mot. Les gaps sautent des suites de caractères de manière non déterministe, de sorte que le matcheur explore chaque position qu’un gap peut atteindre.
Ancres et préfiltre de balayage
Pour chaque règle floue, le compilateur calcule un ensemble d’ancres littérales requises : des littéraux tels qu’un candidat n’en contenant aucun ne peut pas correspondre. Si une règle peut correspondre sans aucun littéral garanti (par exemple un parcours purement gap ou conditionné), son ensemble d’ancres est vide et la règle est toujours exécutée. Les ancres de chaque règle construisent un préfiltre Aho-Corasick qui, en une seule passe sur un message, marque quelles règles pourraient éventuellement correspondre, de sorte que les règles dont les littéraux sont absents sont sautées. Ceci est une optimisation uniquement : elle ne saute jamais une règle qui pourrait correspondre.
Règles strictes (MATCH)
Une règle MATCH utilise le langage strict plutôt que le moteur flou. Un motif strict est ancré : il réussit seulement lorsque ses termes consomment l’entrée entière du début à la fin. Il est utilisé pour des entrées structurées comme les nombres et les adresses, et il peut capturer des morceaux nommés.
Primitives strictes
| Mot-clé | Correspond à |
|---|---|
digit |
Exactement un chiffre. |
digits |
Une suite de chiffres. |
letter |
Exactement une lettre. |
letters |
Une suite de lettres. |
word |
Une suite de lettres, de chiffres ou de tirets bas. |
number |
Une suite de chiffres. |
ip |
Une suite de chiffres et de points. |
space |
Exactement un caractère d’espacement. |
spaces |
Une suite d’espacement. |
anything |
N’importe quelle étendue de texte. |
La correspondance de mots-clés ignore la casse. Un jeton "..." est un littéral, avec les échappements par barre oblique inverse honorés.
Quantificateurs stricts et structure
| Construction | Effet |
|---|---|
any x |
Zéro ou plusieurs x, gourmand. |
many x |
Un ou plusieurs x, gourmand. |
maybe x |
Zéro ou un x. |
m to n x |
Entre m et n x. |
n digit (etc.) |
Exactement n d’une classe, par exemple 3 digit. |
( ... ) |
Un groupe apparié comme une sous-séquence. |
x or y |
Alternance : l’une ou l’autre branche peut satisfaire la position. |
then |
Liant lisible facultatif entre les termes ; ignoré. |
x as name |
Capture le texte apparié de x sous name. |
Un quantificateur appliqué à une classe plurielle la réduit à sa forme à caractère unique afin qu’elle se répète un caractère à la fois. La répétition est gourmande uniquement ; il n’y a pas de mode paresseux, et une répétition vide ne peut pas boucler.
Références de liste et recherche floue en strict
&name dans un motif strict s’étend en une alternance des membres de la classe en tant que littéraux. Un terme entre accents graves find `pattern` intègre un motif EVE flou : le matcheur strict remet une étendue sans espace au motif flou compilé et accepte l’étendue lorsqu’elle correspond. Les deux ont besoin du registre, disponible lorsqu’un document est compilé.
Règles anywhere et sequence
ANYWHERE et SEQUENCE sont des types de règle distincts. ANYWHERE se déclenche lorsque chaque groupe (séparé par !! en forme compacte, WITH en ExpandaEVE) a un membre trouvé quelque part dans le message ; chaque membre est compilé comme un matcheur flou de mot entier, et la règle nécessite au moins deux groupes. SEQUENCE correspond à une suite ordonnée de glyphes et est utilisée par le tableau de symboles, qui est documenté séparément ; un préfixe mirror accepte aussi l’ordre inversé, et la règle nécessite au moins deux glyphes.