code wiki / (root) / nx_rxfull.nx

nx_rxfull.nx

buildroot/runtime/nx_rxfull.nx

35338 B768 linesdepth 2pulls 2 transitivereach 143 importersview sourcekind library
docsdependenciesstructsconstsfunctions

about

nx_regex.nx -- SOVEREIGN regex engine (operator 2026-07-08/09: push the JS engine to run modern bundles; regex is the last bundle-blocker + a PARSE-level one). Standalone + self-gated so it is proven before wiring into the JS lexer/RegExp. Architecture = Cox's "regex VM" (compile the pattern to a flat INSTRUCTION PROGRAM, then a backtracking matcher over it) -- flat dispatch dodges nx_cc's deep-else-nest miscompile, and it makes captures + step-bounding clean. STEP + DEPTH bounded => a hostile bundle regex can NEVER hang/crash the crawler (fails safe to no-match). Covers: literals, ., char classes [..] (ranges/negation/predef), \d\w\s\D\W\S, anchors ^ $, quantifiers * + ? and {n} {n,} {n,m} (greedy + lazy ?), groups (capturing + (?:..)), alternation |, escapes, \b \B word-boundary, flags i (icase) m (multiline) s (dotall). Leftmost match + capture groups. license_tier: ORIGINAL

dependencies 1 imports · 2 importers

nx_syscalls.nx nx_rxfull.nx nx_js_eval.nx nx_regex_gate.nx

imports: nx_syscalls.nx

imported by: nx_js_eval.nxnx_regex_gate.nx

structs

69struct Regex { prog: *i64, nprog: i64, classes: *i64, ngroup: i64, flags: i64, nsave: i64, ok: i64, nmark: i64 }
72struct RxP { pat: *u8, plen: i64, pos: i64, nodes: *i64, nn: i64, classes: *i64, nc: i64, ngroup: i64, flags: i64, err: i64 }
75struct Rx { s: *u8, slen: i64, prog: *i64, classes: *i64, flags: i64, saves: *i64, fuel: *i64, marks: *i64 }

consts

13const RE_CHAR: i64 = 1 // a = charcode (lowered if icase)
14const RE_ANY: i64 = 2 // any char (not newline unless dotall)
15const RE_CLASS: i64 = 3 // a = class-table base
16const RE_SPLIT: i64 = 4 // a,b = two pcs to try (a first)
17const RE_JMP: i64 = 5 // a = pc
18const RE_SAVE: i64 = 6 // a = capture slot
19const RE_MATCH: i64 = 7
20const RE_BOL: i64 = 8 // ^
21const RE_EOL: i64 = 9 // $
22const RE_WORDB: i64 = 10 // \b
23const RE_NWORDB: i64 = 11 // \B
24const RE_AHEAD: i64 = 12 // a=negate(0 pos/1 neg) b=after-pc; ZERO-WIDTH sub-match of [p+1 .. RE_AEND)
25const RE_AEND: i64 = 13 // terminates a lookahead sub-match program (acts like MATCH for the sub-run)
26const RE_BREF: i64 = 14 // a=groupnum; re-match the text a prior capture group matched (JS \1..\9)
27const RE_MARK: i64 = 15 // a=slot; record current input pos into marks[slot] (loop-entry stamp)
28const RE_BACK: i64 = 16 // a=slot b=target; take the loop back-edge to `target` ONLY if pos advanced since
31const RE_LOOPA: i64 = 17 // a=min(0 star/1 plus) b=greedy; the SINGLE consuming atom insn sits at p+1 and the
37const RX_CHAR: i64 = 1 // a=code
38const RX_ANY: i64 = 2
39const RX_CLASS: i64 = 3 // a=class base
40const RX_CONCAT: i64 = 4 // a=left b=right
41const RX_ALT: i64 = 5 // a=left b=right
42const RX_STAR: i64 = 6 // a=child b=greedy
43const RX_PLUS: i64 = 7 // a=child b=greedy
44const RX_QUEST: i64 = 8 // a=child b=greedy
45const RX_REPEAT: i64 = 9 // a=child b=min c=max(-1=inf) d=greedy
46const RX_GROUP: i64 = 10 // a=child b=capturing c=groupnum
47const RX_BOL: i64 = 11
48const RX_EOL: i64 = 12
49const RX_WORDB: i64 = 13
50const RX_NWORDB: i64 = 14
51const RX_EMPTY: i64 = 15
52const RX_LOOKAHEAD: i64 = 16 // a=child b=negate(0 pos/1 neg) -- (?=..) / (?!..)
53const RX_BACKREF: i64 = 17 // a=groupnum -- \1..\9
56const RXF_I: i64 = 1
57const RXF_M: i64 = 2
58const RXF_S: i64 = 4
59const RXF_G: i64 = 8
62const RX_MAXNODE: i64 = 8192
63const RX_MAXPROG: i64 = 16384
64const RX_MAXCLASS: i64 = 8192
65const RX_MAXREP: i64 = 1000 // {n,m} expansion clamp
66const RX_MAXDEPTH: i64 = 6000 // backtracking recursion cap (stack-overflow guard)
67const RX_FUEL: i64 = 5000000 // total backtracking steps (catastrophic-backtrack guard)
70const REGEX_BYTES: i64 = 64
73const RXP_BYTES: i64 = 80
76const RX_BYTES: i64 = 64

functions

79func rx_lc(c: i64) -> i64 { if c >= 65 { if c <= 90 { return c + 32 } } return c }
80func rx_swapcase(c: i64) -> i64 { if c >= 65 { if c <= 90 { return c + 32 } } if c >= 97 { if c <= 122 { return c - 32 } } return c }
called by 1: rx_class_match
81func rx_isword(c: i64) -> i64 { if c >= 48 { if c <= 57 { return 1 } } if c >= 65 { if c <= 90 { return 1 } } if c >= 97 { if c <= 122 { return 1 } } if c == 95 { return 1 } return 0 }
called by 1: rx_wordb
84func rp_peek(p: *RxP) -> i64 { if p.pos < p.plen { return (p.pat[p.pos]) as i64 } return 0 - 1 }
85func rp_at(p: *RxP, off: i64) -> i64 { let q: i64 = p.pos + off; if q < p.plen { return (p.pat[q]) as i64 } return 0 - 1 }
86func rp_adv(p: *RxP) -> i64 { p.pos = p.pos + 1; return 0 }
88func rp_node(p: *RxP, kind: i64, a: i64, b: i64, c: i64) -> i64
99func rp_add_range(p: *RxP, lo: i64, hi: i64) -> i64 { let cl: *i64 = p.classes; if p.nc + 2 > RX_MAXCLASS { p.err = 1; return 0 } cl[p.nc] = lo; cl[p.nc + 1] = hi; p.nc = p.nc + 2; return 0 }
101func rp_add_predef(p: *RxP, which: i64) -> i64
called by 2: rp_predef_noderp_class calls 1: rp_add_range
107func rp_predef_node(p: *RxP, which: i64, neg: i64) -> i64
called by 1: rp_escape calls 2: rp_add_predefrp_node
121func rp_class_esc_val(p: *RxP) -> i64
143func rp_class(p: *RxP) -> i64
177func rp_class_lit(p: *RxP, lo: i64) -> i64
191func rx_hexval(c: i64) -> i64
198func rx_esc_char(e: i64) -> i64
209func rp_escape(p: *RxP) -> i64
257func rp_backref_node(p: *RxP, g: i64) -> i64 { return rp_node(p, RX_BACKREF, g, 0, 0) }
called by 1: rp_escape calls 1: rp_node
260func rp_atom(p: *RxP) -> i64
305func rp_brace(p: *RxP, box: *i64) -> i64
called by 1: rp_repeat calls 2: rp_advrp_peek
332func rp_repeat(p: *RxP) -> i64
349func rp_lazy(p: *RxP) -> i64 { if rp_peek(p) == 63 { rp_adv(p); return 0 } return 1 }
called by 1: rp_repeat calls 2: rp_peekrp_adv
351func rp_wrap(p: *RxP, kind: i64, child: i64, x: i64, y: i64, g: i64) -> i64
called by 1: rp_repeat calls 1: rp_node
361func rp_concat(p: *RxP) -> i64
called by 1: rp_alt calls 3: rp_peekrp_repeatrp_node
379func rp_alt(p: *RxP) -> i64
394func rc_emit(prog: *i64, npp: *i64, op: i64, a: i64, b: i64) -> i64
402func rx_single_atom(nodes: *i64, node: i64) -> i64
called by 2: rc_starrc
412func rc_star(nodes: *i64, child: i64, prog: *i64, npp: *i64, greedy: i64) -> i64
called by 1: rc calls 3: rx_single_atomrc_emitrc
429func rc(nodes: *i64, node: i64, prog: *i64, npp: *i64) -> i64
527func rx_class_match(rx: *Rx, cbase: i64, ch: i64) -> i64
called by 1: re_bt calls 1: rx_swapcase
542func rx_wordb(rx: *Rx, i: i64) -> i64
called by 1: re_bt calls 1: rx_isword
552func re_bt(rx: *Rx, pc: i64, sp: i64, depth: i64) -> i64
702func nx_regex_compile(pat: *u8, plen: i64, flags: i64) -> *Regex
725func nx_regex_exec(re: *Regex, s: *u8, slen: i64, start: i64, saves: *i64) -> i64
750func nx_regex_test(re: *Regex, s: *u8, slen: i64) -> i64
756func nx_regex_flags(fs: *u8, flen: i64) -> i64
called by 1: js_make_regex_val