====== std.regex ======
Reguläre Ausdrücke mit NFA-basiertem Bytecode-Interpreter. Unterstützt Match (ganzer String), Search (erstes Vorkommen), Replace, Alternation (''foo|bar'') und Capture-Gruppen (bis zu 32, ''CaptureText''). Flags: IGNORE_CASE (Groß-/Kleinschreibung ignorieren), ANCHORED (nur am Anfang), MULTILINE ('''^'''/''$'' matchen Zeilengrenzen). Sowohl einfache API (''RegexMatch'', ''RegexSearch'', ''RegexReplace'') als auch kompilierte Varianten für Wiederverwendung. ''RegexSearchSpan'' liefert Start- und End-Position eines Treffers; ''RegexFindAll'' findet alle nicht-überlappenden Treffer auf einmal.
Einsatzbereiche: Eingabevalidierung (E-Mail, Telefon, URLs), Log-Parsing, Template-Ersetzung, Protokoll-Analyse, SEO-Content-Analyse.
**Autor:** Andreas Röne\\
**Copyright:** 2024-2025 Andreas Röne
----
===== Imports =====
* ''[[lyx_-_programmiersprache:units:string|std.string]]''
* ''std.alloc''
----
===== Funktionen =====
^ Signatur ^ Sichtbarkeit ^ Beschreibung ^
| ''isAlpha(c: int64): int64'' | pub | Prüft ob Zeichen ein Buchstabe ist |
| ''isDigit(c: int64): int64'' | pub | Prüft ob Zeichen eine Ziffer ist |
| ''isAlnum(c: int64): int64'' | pub | Prüft ob Zeichen alphanumerisch ist |
| ''isWhitespace(c: int64): int64'' | pub | Prüft ob Zeichen ein Leerzeichen ist |
| ''isWordChar(c: int64): int64'' | pub | Prüft ob Zeichen ein Wortzeichen ist |
| ''atomLen(pattern: pchar, start: int64): int64'' | pub | Berechnet Länge eines Regex-Atoms |
| ''atomMatches(pattern: pchar, start: int64, c: int64): int64'' | pub | Prüft ob Zeichen auf Regex-Atom passt |
| ''matchHere(pattern: pchar, pIdx: int64, text: pchar, tIdx: int64): int64'' | pub | Interner rekursiver Regex-Matcher |
| ''regexSearchFrom(pattern: pchar, text: pchar, startIdx: int64): int64'' | pub | Sucht Muster ab gegebenem Startindex |
| ''_RegexMatch(pattern: pchar, text: pchar): bool'' | pub | Interne Match-Implementierung |
| ''_RegexSearch(pattern: pchar, text: pchar): int64'' | pub | Interne Search-Implementierung |
| ''_RegexReplace(pattern: pchar, text: pchar, replacement: pchar): int64'' | pub | Interne Replace-Implementierung |
| ''Match(pattern: pchar, text: pchar): bool'' | pub | Prüft ob gesamter Text zum Muster passt |
| ''Search(pattern: pchar, text: pchar): int64'' | pub | Sucht erstes Vorkommen des Musters |
| ''Replace(pattern: pchar, text: pchar, replacement: pchar): int64'' | pub | Ersetzt erstes Vorkommen durch Ersatztext |
----
===== Konstanten =====
^ Name ^ Typ ^ Wert ^ Sichtbarkeit ^
| ''REGEX_FLAG_IGNORE_CASE'' | ''int64'' | ''1'' | pub |
| ''REGEX_FLAG_ANCHORED'' | ''int64'' | ''2'' | pub |
| ''REGEX_FLAG_MULTILINE'' | ''int64'' | ''4'' | pub |
| ''REGEX_MAX_CAPTURE_SLOTS'' | ''int64'' | ''32'' | pub |
| ''REGEX_STACK_MAX'' | ''int64'' | ''256'' | pub |
----
===== Typen =====
==== RegexProgramInfo (struct) ====
^ Feld ^ Typ ^
| ''instrStart'' | ''int64'' |
| ''classCount'' | ''int64'' |
| ''captureSlots'' | ''int64'' |
==== RegexFrame (struct) ====
^ Feld ^ Typ ^
| ''pc'' | ''int64'' |
| ''pos'' | ''int64'' |
| ''caps'' | ''array[32]int64'' |
^ Signatur ^ Sichtbarkeit ^ Beschreibung ^
| ''RegexSearchCompiledEx(prog: pchar, progLen: int64, text: pchar,'' | pub | Sucht in Text mit Flags und Capture-Gruppen |
| ''RegexMatchCompiledEx(prog: pchar, progLen: int64, text: pchar,'' | pub | Matcht gesamten Text mit Flags und Captures |
| ''RegexSearchCompiled(prog: pchar, progLen: int64, text: pchar): int64'' | pub | Sucht erstes Vorkommen mit kompiliertem Programm |
| ''RegexMatchCompiled(prog: pchar, progLen: int64, text: pchar): bool'' | pub | Matcht gesamten Text mit kompiliertem Programm |
| ''RegexReplaceCompiledEx(prog: pchar, progLen: int64, text: pchar,'' | pub | Ersetzt Treffer mit Flags und kompiliertem Programm |
| ''RegexReplaceCompiled(prog: pchar, progLen: int64, text: pchar,'' | pub | Ersetzt Treffer mit kompiliertem Programm |
| ''RegexMatchEx(pattern: pchar, text: pchar, flags: int64): bool'' | pub | Matcht Text mit Muster und Flags |
| ''RegexSearchEx(pattern: pchar, text: pchar, flags: int64): int64'' | pub | Sucht Muster in Text mit Flags |
| ''RegexReplaceEx(pattern: pchar, text: pchar, replacement: pchar,'' | pub | Ersetzt Treffer mit Flags |
| ''RegexReplaceInto(dest: pchar, pattern: pchar, text: pchar,'' | pub | Schreibt Ergebnis in vorhandenen Puffer |
| ''RegexCaptureCount(): int64'' | pub | Gibt Anzahl der letzten Capture-Gruppen zurück |
| ''RegexCaptureStart(group: int64): int64'' | pub | Gibt Startposition einer Capture-Gruppe zurück |
| ''RegexCaptureEnd(group: int64): int64'' | pub | Gibt Endposition einer Capture-Gruppe zurück |
| ''RegexCaptureText(dest: pchar, text: pchar, group: int64): pchar'' | pub | Kopiert Capture-Gruppen-Text in Puffer |
| ''MatchEx(pattern: pchar, text: pchar, flags: int64): bool'' | pub | Kurzform von RegexMatchEx |
| ''SearchEx(pattern: pchar, text: pchar, flags: int64): int64'' | pub | Kurzform von RegexSearchEx |
| ''ReplaceEx(pattern: pchar, text: pchar, replacement: pchar,'' | pub | Kurzform von RegexReplaceEx |
| ''ReplaceInto(dest: pchar, pattern: pchar, text: pchar,'' | pub | Kurzform von RegexReplaceInto |
| ''CaptureCount(): int64'' | pub | Kurzform von RegexCaptureCount |
| ''CaptureStart(group: int64): int64'' | pub | Kurzform von RegexCaptureStart |
| ''CaptureEnd(group: int64): int64'' | pub | Kurzform von RegexCaptureEnd |
| ''CaptureText(dest: pchar, text: pchar, group: int64): pchar'' | pub | Kurzform von RegexCaptureText |
| ''RegexMatch(pattern: pchar, text: pchar): bool'' | pub | Kanonischer Alias für ''Match'' |
| ''RegexSearch(pattern: pchar, text: pchar): int64'' | pub | Kanonischer Alias für ''Search'' |
| ''RegexReplace(pattern: pchar, text: pchar, replacement: pchar): int64'' | pub | Kanonischer Alias für ''Replace'' |
| ''RegexSearchSpan(pattern: pchar, text: pchar, startOut: int64, endOut: int64): bool'' | pub | Sucht Muster und schreibt Match-Start und -End per ''poke64'' in zwei int64-Adressen; gibt ''false'' zurück wenn kein Treffer |
| ''RegexFindAll(pattern: pchar, text: pchar, out: int64, maxMatches: int64): int64'' | pub | Findet alle nicht-überlappenden Treffer; ''out'' ist Adresse eines Puffers der ''pchar''-Zeiger aufnimmt (8 Bytes je Treffer, heap-alloc'd); gibt Trefferanzahl zurück |
----
===== Codebeispiele =====
==== RegexSearchSpan ====
var startBuf: int64 := alloc(8) as int64;
var endBuf: int64 := alloc(8) as int64;
if (RegexSearchSpan("foo|bar", text, startBuf, endBuf)) {
var s: int64 := peek64(startBuf);
var e: int64 := peek64(endBuf);
// Treffer liegt in text[s..e)
}
free(startBuf, 8);
free(endBuf, 8);
==== RegexFindAll ====
var buf: int64 := alloc(16 * 8) as int64; // max. 16 Treffer
var n: int64 := RegexFindAll("\d+", text, buf, 16);
var i: int64 := 0;
while (i < n) {
var s: pchar := peek64(buf + i * 8) as pchar;
// s ist jeder Treffer als heap-alloc'd pchar — Aufrufer muss free aufrufen
i := i + 1;
}
free(buf, 16 * 8);
==== Alternation ====
// | matcht auf oberster Ebene; Gruppen schränken den Geltungsbereich ein
var pos: int64 := RegexSearch("error|warn|info", logLine);
var pos2: int64 := RegexSearch("(GET|POST) /api", httpLine);
----
===== Hinweise =====
* **Alternation nur in der einfachen API**: ''|'' wird von ''RegexSearch'', ''RegexMatch'', ''RegexSearchSpan'' und ''RegexFindAll'' unterstützt. Die kompilierte API (''RegexSearchCompiledEx'' etc.) kennt kein ''|'' im Bytecode-Format.
* **''RegexFindAll'': Aufrufer gibt Treffer frei** — jeder zurückgegebene ''pchar''-Zeiger ist heap-alloc'd. Für n Treffer der Länge L gilt: ''free(ptr, L + 1)'' pro Treffer.
* **''RegexSearchSpan'': Adressen, keine Werte** — ''startOut'' und ''endOut'' sind ''int64''-Adressen (z. B. ''alloc(8) as int64''), nicht direkte Ausgabevariablen.
* **Keyword-Konflikt ''match''** — in internem Code verwendet die Unit ''matched2'' statt ''matched'' und ''pEnd'' statt ''to'', da beide reservierte Keywords sind (TK_MATCH = 27). Betrifft nur eigenen Code der Unit, nicht die öffentliche API.