@@ -375,6 +375,57 @@ predicate hasNonEcmaScriptGrammarFlag(StringLiteral regex) {
375375 )
376376}
377377
378+ // ---------------------------------------------------------------------------
379+ // Grammar classification
380+ // ---------------------------------------------------------------------------
381+
382+ /**
383+ * The `std::regex` grammar dialects that the C++ regex parser is aware of.
384+ *
385+ * - `Ecma()` — ECMAScript, the default grammar used by `std::regex` and the
386+ * only grammar currently parsed. Selected either implicitly
387+ * (no explicit grammar flag) or explicitly via
388+ * `std::regex_constants::ECMAScript`.
389+ * - `Bre()` — POSIX Basic Regular Expressions (selected via the `basic` or
390+ * `grep` flags).
391+ * - `Ere()` — POSIX Extended Regular Expressions (selected via the
392+ * `extended`, `egrep`, or `awk` flags).
393+ *
394+ * `Bre()` and `Ere()` are scaffolding for future phases that will add POSIX
395+ * grammar support. Today the parser still excludes non-ECMAScript regexes
396+ * (see `hasNonEcmaScriptGrammarFlag`), so in practice every parsed regex
397+ * classifies as `Ecma()` and only the `Ecma()` branch of `regexGrammar` is
398+ * exercised — the `Bre()`/`Ere()` branches exist purely so the classifier
399+ * agrees with the flag-detection helpers below.
400+ */
401+ newtype TRegexGrammar =
402+ Ecma ( ) or
403+ Bre ( ) or
404+ Ere ( )
405+
406+ /**
407+ * Gets the `std::regex` grammar dialect of `regex`, inferred from its
408+ * construction-site `syntax_option_type` flag argument (if any).
409+ *
410+ * The mapping is:
411+ * - `basic` / `grep` → `Bre()`
412+ * - `extended` / `egrep` / `awk` → `Ere()`
413+ * - anything else (default, explicit `ECMAScript`, or unresolved) → `Ecma()`
414+ *
415+ * Because the parser still gates on `not hasNonEcmaScriptGrammarFlag`, every
416+ * literal that is actually parsed today classifies as `Ecma()`. The
417+ * `Bre()`/`Ere()` cases are defined only so the classifier is complete for
418+ * later phases; those branches are not exercised by the current parser.
419+ */
420+ TRegexGrammar regexGrammar ( StringLiteral regex ) {
421+ if containsRegexFlag ( getConstructionFlagArg ( regex ) , [ "basic" , "grep" ] )
422+ then result = Bre ( )
423+ else
424+ if containsRegexFlag ( getConstructionFlagArg ( regex ) , [ "extended" , "egrep" , "awk" ] )
425+ then result = Ere ( )
426+ else result = Ecma ( )
427+ }
428+
378429/**
379430 * Holds if `regex` is constructed with an explicit ECMAScript grammar flag.
380431 * This is the default, and also the case that the Phase 1 parser handles.
0 commit comments