Crate regex_literal
source ·Expand description
§regex-literal - regex literal enclosed by delimiters
This crate provides a quick approach of creating regular expression Regex
and sequence ReSequence
from delimited literals at runtime. Its aim is to
formalize regex literal in Rust computing.
§Background
In Rust Reference1, primitive types (boolean, numeric and textual) have own literal expressions that are evaluated as single tokens in source code at compile time. But it is not the case for regular expression (abbr. regex).
In many scripting languages that implement PCRE library2, a regex pattern
is enclosed by a pair of delimiters, for example,/pattern/im
in JavaScript.
Regex engines in Rust crate regex-automata,
can only receive a general literal (&str) in building a one-pattern regex.
In the interface of Regex::new_many,
an array of many pattern strings is required, as there is no syntax
for one string literal representing a compound regex.
§Features
The crate delivers literal formats for regex and regex sets with the following punctuations:
-
//
(a pair of forward slashes) as the default delimiters that enclose a pattern. -
[]
(a pair of square brackets) that hold a union of multiple patterns (abbr. as ‘ReU’). -
<>
(a pair of angle brackets) that hold a sequence of regex patterns and/or pattern unions (abbr. as ‘ReS’) that iterates over consecutive matchings. -
,
(comma) serves as seperator in between regex pattern literals, while any whitespace unicode character3 is skipped in parsing.
§Samples of regex literals
- a simple pattern :
r#"/ab+c/"#
- a regex union literal:
r#"[/(?i)ab+c/,/(?u)\s{2}D+/]"#
- a regex sequence literal:
r#"</(?i)ab+c/,/(?u)\s{2}D+/>"#
- another regex sequence literal:
r#"<[/(?i)ab+c/,/(?u)\s{2}D+/],/\s*\w+/>"#
Note that crate::delimited::set_delimiter()
allows choosing a customized
delimiter from crate::delimited::DELIMITER_CHARS
.
In addition, crate::util
module provides public functions of text
convertion between undelimited and delimited patterns.
§Building Regex structs from regex-literal
The regular expression structs can be constructed via either
crate::XRegex::from_str
or crate::XRegex::new
. The former uses the
default regex literal delimiter (“/” transcoded in crate::delimited::DELIMITER
);
the latter allows a customised delimiter. An easy alternative is to use macro
xregex!
crate::xregex
when constructing XRegex with literals.
§Examples
use regex_literal::{XRegex,FromStr,Regex,Match,PatternID,Input,Anchored,xregex};
//example 0: create a XRegex structs from a one-pattern literal by xregex!()
let text = "abc123";
//construct XRegex
let mut xre = xregex!(r"/^[a-z]+\d{3}$/");
//get Regex from XRegex struct
let re = xre.get_regex().unwrap();
//check if the one pattern regex matches with the target text
assert!(re.is_match(text));
//example 1: create a XRegex struct from a one-pattern literal
let text0 = "abc123";
//create one-pattern literal
let re0 = r#"/^[a-z]+\d{3}$/"#;
//construct XRegex
let mut x = XRegex::from_str(re0).unwrap();
//get Regex from XRegex struct
let x_one_pattern = x.get_regex().unwrap();
//check if the one pattern regex matches with the target text
assert!(x_one_pattern.is_match(text0));
//find the first match if it exists
let m = x_one_pattern.find(text0);
assert_eq!(m,Some(Match::must(0,0..6)));
//example 2: create a XRegex struct from a one-pattern literal
let text1 = "ABBBC abc123";
let re1 = "!!!!(?i)ab+c!!!!";
//construct XRegex
let mut y = XRegex::new(re1,b"!!!!").unwrap();
//get Regex from XRegex struct
let y_one_pattern = y.get_regex().unwrap();
// check if this one pattern regex matches with the input
assert!(y_one_pattern.is_match(text1));
//find all non-overlapping leftmost matches
let matches:Vec<Match> = y_one_pattern.find_iter(text1).collect();
assert_eq!(matches,vec![Match::must(0,0..5),Match::must(0,6..9),]);
//example 3: create a XRegex struct from a multiple-pattern literal
let reu = r"[/(?i)ab+c/,/\w+/]";
let mut m1 = XRegex::from_str(reu).unwrap();
//get Regex from XRegex struct
let m_patterns = m1.get_regex().unwrap();
assert!(m_patterns.is_match(text1));
let m_matches:Vec<Match> = m_patterns.find_iter(text1).collect();
assert_eq!(m_matches,vec![Match::must(0,0..5),Match::must(0,6..9),Match::must(1,9..12)]); //non-overlapping leftmost matches
let expected = Some(Match::must(1,0..7));
let input = Input::new("23ABBBC abc&").anchored(Anchored::Pattern(PatternID::must(1)));//choose the specific pattern for input
let n_patterns = XRegex::from_str(reu).unwrap().get_regex().unwrap();
let mut caps = n_patterns.create_captures();
n_patterns.search_captures(&input,&mut caps);
assert_eq!(expected, caps.get_match());
//example 4: create a XRegex struct from a regex sequence literal
let xre2 = XRegex::from_str(r"</(?i)ab+c/,/^\w+?\d+$/>").unwrap();
let seq_slice = xre2.as_slice().unwrap();
let child_regex = &seq_slice[0];
assert!(child_regex.is_match("abc333"));
§Conversion of regex literals
crate::util::delimit
andcrate::util::undelimit
provide regex literal conversion between undelimited and delimited forms.
§Examples
let delimiter = "/";
// a regex literal that includes delimiter(forward slash `/`)
let re1 = r"\d{2}/\d{2}/\d{4}";
let delimited1 = delimit(re1,delimiter);
let string1 = r"/\d{2}\/\d{2}\/\d{4}/";
assert_eq!(&delimited1[..],string1);
let undelimited = undelimit(&delimited1[..],delimiter).unwrap();
assert_eq!(&undelimited[..], re1);
crate::assembly::into_reu
andcrate::assembly::into_res
annotate patterns with default delimiters into delimited literals of regular expression union and sequence accordingly. Note the transformations require feature “w”.
§Examples
let re1 = "(?i)ab+c";
let re2 = r"\w+";
let re_set = [re1,re2];
let reu = into_reu(&re_set);
assert_eq!(reu,r"[/(?i)ab+c/,/\w+/]".to_owned());
§Acknowledgements
[regex-literal
] has adopted PCRE-style delimiters on top of regex engines in Rust crate regex-automata.
§Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Types of changes:
- Added for new features.
- Changed for changes in existing functionality.
- Deprecated for soon-to-be removed features.
- Removed for now removed features.
- Fixed for any bug fixes.
- Security in case of vulnerabilities.
§[unreleased]
- A show case of integration testing, knowledge from https://doc.rust-lang.org/rust-by-example/testing/integration_testing.html
- A show case of performance (benchmark) testing, knowledge from https://doc.rust-lang.org/rust-by-example/testing/integration_testing.html and https://crates.io/crates/criterion
- create custom literal/ or macro for regex_literal tokens https://blog.jetbrains.com/rust/2022/03/18/procedural-macros-under-the-hood-part-i/ https://stackoverflow.com/questions/60790226/custom-literals-via-rust-macros https://internals.rust-lang.org/t/pre-rfc-custom-literals-via-traits/8050 */
§[1.2.0] -2024-5-5
§Added
- macro xregex!()
§[1.1.1] -2024-4-28
§Added
- is_empty() method created for XRegex and ReSequence
§Fixed
- improve source code according to lint warnings.
§[1.1.0] -2024-4-26
§Added
- Patterns can be annotated into regex sets by into_reu and into_res functions in module assembly.
§Fixed
- example documentation in lib.rs and README.md
§[1.0.2] -2024-4-19
§Fixed
- samples of regex literals
§[1.0.1] -2024-3-17
§Fixed
- README.md
§[1.0.0] -2024-3-1
§Added
- module assembly in
w
feature - documentation test and unit test
§[0.9.8] - 2024-1-4
§Added
- Module delimited defines the core data structures ReSequence, XRegex, and the
associated intermediate data (LiteralForm and Meta); it also includes the
execution procedures of
parse
andcompile
for converting literals of regular expressions and sets to regular expression structures.
Re-exports§
pub use delimited::*;
Modules§
- feature
w
for “wiring” - The core module of delimited literals
- A collection of helper functions that process literal conversions.
Macros§
- construct XRegex with the following arguments: $l - regex string literal, $d_bytes - the byte string literal of delimiter
Traits§
- Parse a value from a string