code wiki / _hdl_build / nx_regex_unified_gate.nx

nx_regex_unified_gate.nx source

↩ module page · 69 lines · 6146 B

1// nx_regex_unified_gate.nx -- GATE: the UNIFIED linear-time regex engine (nx_regex_vm_lib) is a STRICT SUPERSET of 2// BOTH old engines and drives grep. Proves: (T1) every atom-NFA feature works (literal/./*+?/[]ranges/^/$ anchors); 3// (T2) PLUS alternation | and groups () that the atom-NFA could NOT do; (T3) the UNIFICATION payoff -- anchors COMBINED 4// with alternation/groups (^(cat|dog)$), which NEITHER old engine could express; (T4) ReDoS-immune (linear on the 5// classic blowup); (T5) grep runs on it -- ReDoS-immune, full-regex line grep (beats backtracking grep/PCRE); (T6) 6// malformed pattern fails-loud. This consolidates two engines into one SOTA engine. expect_exit: 0 7import "nx_syscalls.nx" 8import "nx_regex_vm_lib.nx" 9 10func g_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 11func g_pn(v: i64) -> i64 { let b: *u8=sys_mmap(28); var x: i64=v; if x<0{b[0]=45;sys_write(1,b,1);x=0-x} if x==0{b[0]=48;sys_write(1,b,1);return 0} var d: i64=0; var y: i64=x; while y>0{d=d+1;y=y/10} var i: i64=d-1; y=x; while i>=0{b[i]=(48+(y%10)) as u8;y=y/10;i=i-1} sys_write(1,b,d); return 0 } 12func ck(name: *u8, c: i64) -> i64 { if c==1 { g_puts(" PASS " as *u8) } else { g_puts(" FAIL " as *u8) } g_puts(name); g_puts("\n" as *u8); return c } 13func m(pat: *u8, text: *u8, n: i64) -> i64 { return re_vm_run(pat, text, n) } 14 15func main() -> i64 { 16 g_puts("nx_regex_unified_gate (ONE linear-time regex engine: superset of both + anchors + alternation + grep, ReDoS-immune)\n" as *u8) 17 var pass: i64=0; var total: i64=0 18 19 // T1: every ATOM-NFA feature (literal, ., *, +, ?, [a-z] class+range, ^ and $ anchors). 20 var t1: i64=0 21 if m("abc" as *u8,"abc" as *u8,3)==1 { if m("abc" as *u8,"abx" as *u8,3)==0 { 22 if m("a.c" as *u8,"axc" as *u8,3)==1 { if m("ab*c" as *u8,"ac" as *u8,2)==1 { if m("ab+c" as *u8,"ac" as *u8,2)==0 { 23 if m("ab?c" as *u8,"abc" as *u8,3)==1 { if m("[a-z]+" as *u8,"hello" as *u8,5)==1 { if m("[0-9]" as *u8,"a" as *u8,1)==0 { 24 if m("^abc" as *u8,"abc" as *u8,3)==1 { if m("^abc" as *u8,"xabc" as *u8,4)==0 { if m("abc$" as *u8,"abc" as *u8,3)==1 { if m("abc$" as *u8,"abcd" as *u8,4)==0 { t1=1 } } } } } } } } } } } } 25 pass=pass+ck("T1: all atom-NFA features -- literal . * + ? [a-z] ranges + ^ $ anchors -- work on the unified engine" as *u8, t1); total=total+1 26 27 // T2: alternation | and groups () -- which the atom-NFA CANNOT do. 28 var t2: i64=0 29 if m("cat|dog" as *u8,"cat" as *u8,3)==1 { if m("cat|dog" as *u8,"dog" as *u8,3)==1 { if m("cat|dog" as *u8,"cow" as *u8,3)==0 { 30 if m("(ab)+" as *u8,"abab" as *u8,4)==1 { if m("a(b|c)d" as *u8,"abd" as *u8,3)==1 { if m("a(b|c)d" as *u8,"aed" as *u8,3)==0 { t2=1 } } } } } } 31 pass=pass+ck("T2: PLUS alternation | and groups () -- capabilities the atom-NFA engine never had" as *u8, t2); total=total+1 32 33 // T3: THE UNIFICATION PAYOFF -- anchors COMBINED with alternation/groups. Neither old engine could express this. 34 var t3: i64=0 35 if m("^(cat|dog)$" as *u8,"cat" as *u8,3)==1 { if m("^(cat|dog)$" as *u8,"dog" as *u8,3)==1 { 36 if m("^(cat|dog)$" as *u8,"cats" as *u8,4)==0 { if m("^(cat|dog)$" as *u8,"scat" as *u8,4)==0 { t3=1 } } } } 37 g_puts(" T3 '^(cat|dog)$': cat="); g_pn(m("^(cat|dog)$" as *u8,"cat" as *u8,3)); g_puts(" cats="); g_pn(m("^(cat|dog)$" as *u8,"cats" as *u8,4)); g_puts(" (anchors+alternation, neither old engine could do this)\n" as *u8) 38 pass=pass+ck("T3 (unification payoff): ^(cat|dog)$ -- anchors + alternation together, expressible by NEITHER old engine" as *u8, t3); total=total+1 39 40 // T4: ReDoS-immune -- the classic '(a|a)*b$' on many a's (no b) stays LINEAR (a backtracker explodes). 41 let r4: i64 = m("(a|a)*b$" as *u8,"aaaaaaaaaaaaaaaaaaaaaaaaaa" as *u8,26) 42 var t4: i64=0; if r4==0 { t4=1 } 43 pass=pass+ck("T4 (ReDoS): '(a|a)*b$' on 26 a's = linear-time no-match (backtracking regex would blow up exponentially)" as *u8, t4); total=total+1 44 45 // T5: GREP runs on the unified engine -- ReDoS-immune, full-regex line grep. A 4-line log: 46 let log: *u8 = "ERROR disk fail\nwarn mem low\nERROR net down\ninfo all ok\n" as *u8 47 let nlog: i64 = 55 48 let nStart: i64 = re_vm_grep_count(log, nlog, "^ERROR" as *u8) // lines STARTING with ERROR -> 2 49 let nAlt: i64 = re_vm_grep_count(log, nlog, "warn|ERROR" as *u8) // lines with warn OR ERROR -> 3 50 let nNone: i64 = re_vm_grep_count(log, nlog, "^debug" as *u8) // none 51 g_puts(" T5 grep: '^ERROR'="); g_pn(nStart); g_puts(" 'warn|ERROR'="); g_pn(nAlt); g_puts(" '^debug'="); g_pn(nNone); g_puts(" (expect 2, 3, 0)\n" as *u8) 52 var t5: i64=0; if nStart==2 { if nAlt==3 { if nNone==0 { t5=1 } } } 53 pass=pass+ck("T5: sovereign grep on the unified engine -- anchored + alternation regex over lines (ReDoS-immune)" as *u8, t5); total=total+1 54 55 // T6 (teeth): a malformed pattern (unbalanced paren) fails-loud (-1), never crashes/miscompiles. 56 let r6: i64 = m("(ab" as *u8,"ab" as *u8,2) 57 var t6: i64=0; if r6==(0-1) { t6=1 } 58 g_puts(" T6 malformed '(ab' rc="); g_pn(r6); g_puts(" (-1 = fail-loud)\n" as *u8) 59 pass=pass+ck("T6 (teeth): a malformed pattern (unbalanced paren) fails-loud (-1), never a crash or miscompile" as *u8, t6); total=total+1 60 61 var okall: i64=0; if pass==total { okall=1 } 62 g_puts("---- nx_regex_unified_gate: passed "); g_pn(pass); g_puts(" / "); g_pn(total); g_puts(" ----\n" as *u8) 63 if okall==1 { 64 let logf: i64=sys_openat_append("knowledge/status/regex_unified.log" as *u8, 420) 65 if logf>=0 { let z: i64=sys_write(logf,"NXREGEXUNIFIED GREEN: ONE linear-time regex engine (nx_regex_vm_lib) -- strict superset of both old engines (literals/./*+?/[]/ranges + | + () + ^ $ anchors), ReDoS-immune, drives sovereign grep; ^(cat|dog)$ expressible by neither old engine\n" as *u8,240); sys_close(logf) } 66 g_puts("verdict=GREEN (two regex engines UNIFIED into one linear-time ReDoS-immune superset -- anchors + alternation + groups + classes, driving grep; the REGEX consolidation gap closed)\n" as *u8); sys_exit(0); return 0 67 } 68 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1 69}