====== 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.