rulex/
lib.rs

1//! # rulex
2//!
3//! ⚠️ **DEPRECATED** ⚠️ Use the `pomsky` crate instead. Rulex was
4//! [renamed to pomsky](https://pomsky-lang.org/blog/renaming-rulex/).
5//!
6//! To learn about the _language_, please read
7//! [the book](https://pomsky-lang.org/docs/get-started/introduction/).
8//!
9//! The _rulex macro_ can be [found here](https://docs.rs/rulex-macro/latest/rulex_macro/).
10//!
11//! ## Usage
12//!
13//! This library can parse a rulex expression and generate a regex string:
14//!
15//! ```
16//! use rulex::Rulex;
17//! use rulex::options::{CompileOptions, RegexFlavor};
18//!
19//! let options = CompileOptions { flavor: RegexFlavor::Java };
20//! let regex: String = match Rulex::parse_and_compile("'test'", Default::default(), options) {
21//!     Ok(regex) => regex,
22//!     Err(_) => {
23//!         eprintln!("The input is not a valid rulex");
24//!         return;
25//!     }
26//! };
27//! ```
28//!
29//! You can get fancy error messages with [miette](https://docs.rs/miette/latest/miette/)
30//! by enabling the `diagnostics` feature:
31//!
32//! ```
33//! use rulex::Rulex;
34//! use rulex::options::{CompileOptions, RegexFlavor};
35//! use rulex::error::Diagnostic;
36//!
37//! pub fn compile(input: &str) -> miette::Result<String> {
38//!     let options = CompileOptions { flavor: RegexFlavor::Java };
39//!     let compiled: String = Rulex::parse_and_compile(input, Default::default(), options)
40//!         .map_err(|e| e.diagnostic(input))?;
41//!     Ok(compiled)
42//! }
43//! ```
44
45#![warn(missing_docs)]
46
47use std::collections::HashMap;
48
49use boundary::{Boundary, BoundaryKind};
50use char_class::{CharClass, CharGroup};
51use compile::CompileState;
52use error::{CompileError, ParseError};
53use grapheme::Grapheme;
54use options::{CompileOptions, ParseOptions};
55use repetition::RegexQuantifier;
56use rule::Rule;
57use span::Span;
58
59pub mod error;
60pub mod features;
61pub mod options;
62
63mod alternation;
64mod boundary;
65mod char_class;
66mod compile;
67mod grapheme;
68mod group;
69mod literal;
70mod lookaround;
71mod parse;
72mod range;
73mod reference;
74mod regex;
75mod repetition;
76mod rule;
77mod span;
78mod stmt;
79mod var;
80
81/// A parsed rulex expression, which might contain more sub-expressions.
82#[derive(Clone)]
83#[deprecated(
84    since = "0.4.4",
85    note = "This entire crate is deprecated. Use the `pomsky` crate instead."
86)]
87pub struct Rulex<'i>(Rule<'i>);
88
89impl<'i> Rulex<'i> {
90    /// Parse a `Rulex` without generating code.
91    ///
92    /// The parsed `Rulex` can be displayed with `Debug` if the `dbg` feature is
93    /// enabled.
94    pub fn parse(input: &'i str, options: ParseOptions) -> Result<Self, ParseError> {
95        let rule = parse::parse(input, 256)?;
96        rule.validate(&options)?;
97        Ok(Rulex(rule))
98    }
99
100    /// Compile a `Rulex` that has been parsed, to a regex
101    pub fn compile(&self, options: CompileOptions) -> Result<String, CompileError> {
102        let mut used_names = HashMap::new();
103        let mut groups_count = 0;
104        self.0.get_capturing_groups(&mut groups_count, &mut used_names, false)?;
105
106        let empty_span = Span::new(0, 0);
107
108        let start = Rule::Boundary(Boundary::new(BoundaryKind::Start, empty_span));
109        let end = Rule::Boundary(Boundary::new(BoundaryKind::End, empty_span));
110        let grapheme = Rule::Grapheme(Grapheme { span: empty_span });
111        let codepoint = Rule::CharClass(CharClass::new(CharGroup::CodePoint, empty_span));
112
113        let builtins = vec![
114            ("Start", &start),
115            ("End", &end),
116            ("Grapheme", &grapheme),
117            ("G", &grapheme),
118            ("Codepoint", &codepoint),
119            ("C", &codepoint),
120        ];
121
122        let mut state = CompileState {
123            next_idx: 1,
124            used_names,
125            groups_count,
126            default_quantifier: RegexQuantifier::Greedy,
127            variables: builtins,
128            current_vars: Default::default(),
129        };
130        let compiled = self.0.comp(options, &mut state)?;
131
132        let mut buf = String::new();
133        compiled.codegen(&mut buf, options.flavor);
134        Ok(buf)
135    }
136
137    /// Parse a string to a `Rulex` and compile it to a regex.
138    pub fn parse_and_compile(
139        input: &'i str,
140        parse_options: ParseOptions,
141        compile_options: CompileOptions,
142    ) -> Result<String, CompileError> {
143        let parsed = Self::parse(input, parse_options)?;
144        parsed.compile(compile_options)
145    }
146}
147
148#[cfg(feature = "dbg")]
149impl core::fmt::Debug for Rulex<'_> {
150    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
151        self.0.fmt(f)
152    }
153}