(var anyChar ".") (var start "^") (var end "\$") // TODO these are very anglocentric: (var capitalLetter "[A-Z]") (var smallLetter "[a-z]") (var anyLetter "[A-Za-z]") (var anyDigit "[0-9]") (function :String _group [:Array exprs] (+ "(" (apply + (assert exprs)) ")")) (var :Function group (Reflect.makeVarArgs _group)) (#when hxnodejs (function :String _namedGroup [:Array exprs] (let [groupName (assert (exprs.shift))] (_group (concat ["?<${groupName}>"] exprs)))) (var :Function namedGroup (Reflect.makeVarArgs _namedGroup))) (function :String escape [:String str] (group (EReg.escape str))) (function :String _oneOf [:Array exprs] (group (exprs.join "|"))) (var :Function oneOf (Reflect.makeVarArgs _oneOf)) (function :String repeat [:String expr &opt :Int min :Int max] (apply group (concat (for _ (range min) expr) (cond // unlimited repetitions after minimum if max is null: (!max [(group expr) "*"]) ((= max min) []) (true (for _ (range (- max min)) (oneOf expr ""))))))) (function :String optional [:String expr] (repeat expr 0 1)) // TODO could memoize compiled regexes (function :Null match [:String regex :String textToSearch &opt :String flags] (#if hxnodejs (ifLet [match (the RegExpMatch (.exec (new RegExp regex /* TODO use or for this once it's fixed */ (if flags flags "")) textToSearch))] (object left (textToSearch.substr 0 match.index) match (first match) right (textToSearch.substr (+ match.index .length (first match))) group ->idx (nth match idx) groups match namedGroups match.groups namedGroup ->name (dictGet match.groups name))) (let [r (new EReg regex /*TODO use or for this once fixed */(if flags flags ""))] (if (r.match textToSearch) (object left (r.matchedLeft) match (r.matched 0) right (r.matchedRight) group ->idx (r.matched idx)))))) // Return an array of all non-overlapping matches in the given text, from left-to-right (function :Array distinctMatches [:String regex :String textToSearch &opt :String flags] (let [matches [] &mut nextMatch null] (while (set nextMatch (match regex textToSearch flags)) (matches.push nextMatch) (set textToSearch nextMatch.right)) matches))