#!/usr/bin/env lmscript # Regex Substring Extraction & Stateful pos() Tokenizer # Demonstrates: # 1. Checking if a string matches (contains) a regex pattern and extracting one or more # matched substrings: regex_test, regex_find, regex_matches, regex_match, regex_find_all # 2. Perl-like stateful pos() with regex_find_pos to build a lexer/tokenizer # over a list of [kind, pattern] rules until pos() == len(src) # (or reporting the exact error offset when no pattern matches). # --- 1. Contains check & extracting one or more matched substrings --- log = "2026-10-17 ERROR disk 91%\n2026-10-18 WARN cpu 72%\n2026-10-18 ERROR mem 88%"; has_error = regex_test(log, r"ERROR"); first_pct = regex_find(log, r"\d+%"); all_pcts = regex_matches(log, r"\d+%"); first_cap = regex_match(log, r"(\d{4}-\d{2}-\d{2}) (\w+)"); all_caps = regex_find_all(log, r"(\w+) (\d+)%"); assert(has_error == true, "regex_test checks if string contains pattern"); assert(first_pct == "91%", "regex_find returns first matched substring"); assert(len(all_pcts) == 3 && all_pcts[0] == "91%" && all_pcts[2] == "88%", "regex_matches returns all matched substrings"); println(f"contains ERROR: {has_error}"); println(f"first match: {first_pct}"); println(f"all matches: {json_stringify(all_pcts)}"); println(f"first captures: {json_stringify(first_cap)}"); println(f"all captures: {json_stringify(all_caps)}"); # --- 2. Stateful Perl-like pos() tokenizer --- const RULES = [ ["WS", r"\s+"], ["NUMBER", r"\d+(?:\.\d+)?"], ["IDENT", r"[A-Za-z_][A-Za-z0-9_]*"], ["OP", r"==|!=|<=|>=|[+\-*/=()<>]"], ["SEMI", r";"] ]; fn tokenize(src) { pos(src, 0); let tokens = []; while (pos() < len(src)) { let start = pos(); let matched = false; for (rule in RULES) { let kind = rule[0]; let pattern = rule[1]; let text = regex_find_pos(src, pattern); if (text != null) { if (kind != "WS") { push(tokens, { kind: kind, text: text, at: start }); } matched = true; break; } } if (!matched) { return { ok: false, tokens: tokens, error_pos: pos(), rest: slice(src, pos()) }; } } return { ok: true, tokens: tokens, final_pos: pos() }; } expr = "total = 42 + tax_rate * 10.5;"; tok_res = tokenize(expr); assert(tok_res.ok && tok_res.final_pos == len(expr), "valid expression must tokenize to end"); println(f"tokenized ({len(tok_res.tokens)} tokens, final pos {tok_res.final_pos}/{len(expr)}):"); println(json_stringify(tok_res.tokens)); bad_expr = "count = 1 @ 99"; bad_res = tokenize(bad_expr); assert(!bad_res.ok && bad_res.error_pos == 10, "unrecognized '@' must stop at pos 10"); println(f"error at pos {bad_res.error_pos}: unexpected {json_stringify(bad_res.rest)}");