/** * Generic string/comment masking (phase 167, T1). * * Walks `text` once against a per-profile `LanguageSyntax` table, * classifying every character as code / string / comment, and derives two * masks from that classification: * - `computeCodeMask` — `1` only for genuine code characters, `0` for * string OR comment content. Used by block-boundary strategies * (`./strategies.ts`) and assertion-pattern testing (`./engine.ts`) so * delimiter characters and assertion tokens inside strings or comments * never affect span resolution — the direct generalization of the * `code`/`sq`/`dq`/`tpl`/`line`/`block` state machine the original * `test-spans.ts` hardcoded for JS/TS only. * - `computeCommentMask` — `1` for code OR string content, `0` only for * comment content. Used for opener matching (`./engine.ts`), where a * profile's opener may legitimately need to match through a quoted * title (e.g. `do-end-keyword`'s `it 'title' do`); only comment content * is never legitimately part of an opener's own syntax (phase 167, T3 * review finding: an opener pattern requiring an interior literal was * spoofable by a comment placed inside a function signature). * * `LanguageSyntax.fencedStrings` (phase 167, T4 review) additionally * supports dynamic-fence string forms — Rust's raw strings * (`r"..."`/`r#"..."#`/`r##"..."##`/...) with no fixed hash-count bound. * `matchFence` resolves the close dynamically per match rather than via a * fixed enumerated `StringDelimiter` list, so there is no "beyond N hashes" * gap that could fall through to an unrelated, prematurely-closing * delimiter and expose a raw string's own content as live code. * * `LanguageSyntax.heredocs` (phase 167, T5 review) supports line-anchored, * dynamic-IDENTIFIER-fenced string forms — PHP's heredoc/nowdoc * (`<<