Skip to main content

rexact_syntax/
dialect.rs

1//! Dialect names (FR-A02).
2
3use crate::error::{ErrorCode, RexactError};
4
5/// A regex dialect. Patterns are interpreted by the rules of the dialect they
6/// were written for (RULE-10).
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub enum Dialect {
9    /// ECMAScript.
10    Ecma,
11    /// Python `re`.
12    Python,
13    /// Go / RE2.
14    Go,
15    /// Rust `regex`.
16    Rust,
17    /// PCRE2.
18    Pcre2,
19    /// Java `java.util.regex` (not a column of the support matrix; see docs/13 notes).
20    Java,
21}
22
23impl Dialect {
24    /// All dialects, in matrix column order.
25    pub const ALL: [Dialect; 5] = [
26        Dialect::Ecma,
27        Dialect::Python,
28        Dialect::Go,
29        Dialect::Rust,
30        Dialect::Pcre2,
31    ];
32
33    /// Command-line name.
34    pub const fn name(self) -> &'static str {
35        match self {
36            Dialect::Ecma => "ecma",
37            Dialect::Python => "python",
38            Dialect::Go => "go",
39            Dialect::Rust => "rust",
40            Dialect::Pcre2 => "pcre2",
41            Dialect::Java => "java",
42        }
43    }
44
45    /// Parse a dialect name; unknown names give `RX-P002` listing valid ones.
46    pub fn from_name(s: &str) -> Result<Dialect, RexactError> {
47        Dialect::ALL
48            .into_iter()
49            .chain([Dialect::Java])
50            .find(|d| d.name() == s)
51            .ok_or_else(|| {
52                let valid: Vec<&str> = Dialect::ALL
53                    .iter()
54                    .chain([Dialect::Java].iter())
55                    .map(|d| d.name())
56                    .collect();
57                let mut e = RexactError::new(ErrorCode::P002);
58                e.detail = Some(format!("'{s}'; valid dialects: {}", valid.join(", ")));
59                e
60            })
61    }
62}