concept.md is the full design document: the objective (Python re parity plus binary/ASCII/UTF-8 modes, gigabyte-scale input, single C file), the automata-theory argument for why unrestricted backreferences/lookaround are incompatible with strict single-pass constant memory, the resulting two-engine architecture, the exact Python-mirroring naming convention, and a full comparison against POSIX regex.h for C-background readers. regexx.c/regexx.h are the v1 implementation: parser, compiler to a Pike/backtracking-style bytecode, and a single recursive backtracking engine covering the pattern syntax and operations listed in README.md, validated against CPython's own re module output (tests/), clean under AddressSanitizer/UBSan, and stress-tested (50MB simple-quantifier match, graceful failure rather than a crash on complex repeats over large input, clean rejection of every intentionally unsupported construct). Also included: examples/rxgrep.c (a small grep-like program exercising all three data modes and the substitution API), the Makefile, the MIT LICENSE, and docs/API.md, an exhaustive reference for every type, flag, and function's exact return-value and memory-ownership convention, checked against the current source and against a real CPython interpreter rather than against memory. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EjuMk8kY9SDus1wWe2K9xY
37 lines
1.5 KiB
C
37 lines
1.5 KiB
C
/* tests/harness.h - shared by hand-written and generated test cases.
|
|
* Ground truth for generated cases comes from CPython's own `re`
|
|
* module (concept.md Section 11); see gen.py. */
|
|
#ifndef REGEXX_TEST_HARNESS_H
|
|
#define REGEXX_TEST_HARNESS_H
|
|
#include "../regexx.h"
|
|
#include <stddef.h>
|
|
|
|
extern int tc_pass, tc_fail;
|
|
|
|
/* search/match/fullmatch: exp_spans holds 2*n_spans int64_t values,
|
|
* (start,end) for group 0, then group 1, 2, ... in order; -1,-1 means
|
|
* the group did not participate (or, for group 0 alone, that
|
|
* exp_matched is 0 and no spans are checked). */
|
|
void tc_search_family(const char *desc, const char *pat, int flags,
|
|
const char *subj, size_t subjlen, int kind,
|
|
int exp_matched, int n_spans, const long long *exp_spans);
|
|
|
|
/* finditer: exp_spans holds 2*n_matches int64_t values, (start,end) of
|
|
* the whole match for each match found, in order. */
|
|
void tc_finditer(const char *desc, const char *pat, int flags,
|
|
const char *subj, size_t subjlen,
|
|
int exp_n_matches, const long long *exp_spans);
|
|
|
|
void tc_sub(const char *desc, const char *pat, int flags,
|
|
const char *subj, size_t subjlen, const char *repl, int count,
|
|
const char *exp_result, int exp_n);
|
|
|
|
/* split: texts[i] == NULL means that list element is None in Python. */
|
|
void tc_split(const char *desc, const char *pat, int flags,
|
|
const char *subj, size_t subjlen, int maxsplit,
|
|
int n_items, const char *const *texts);
|
|
|
|
void harness_report(void);
|
|
|
|
#endif
|