Skip to content

Commit

Permalink
Change Regex flag to "" instead of None
Browse files Browse the repository at this point in the history
  • Loading branch information
kaleidawave committed Dec 30, 2024
1 parent 87ba562 commit 3aacc07
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 38 deletions.
40 changes: 16 additions & 24 deletions checker/src/features/regexp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,36 +21,31 @@ pub struct RegExp {
}

impl RegExp {
pub fn new(pattern: &str, flag_options: Option<&str>) -> Result<Self, String> {
let source = if let Some(flag_options) = flag_options {
format!("/{pattern}/{flag_options}")
} else {
format!("/{pattern}/")
};

pub fn new(pattern: &str, flag_options: &str) -> Result<Self, String> {
let source = format!("/{pattern}/{flag_options}");
let mut flags = Flags::default();
let mut flags_unsupported = false;

if let Some(flag_options) = flag_options {
for flag in flag_options.chars() {
#[allow(clippy::match_same_arms)]
match flag {
'd' => flags_unsupported = true, // indices for substring matches are not supported
'g' => flags_unsupported = true, // stateful regex is not supported
'i' => flags.icase = true,
'm' => flags.multiline = true,
's' => flags.dot_all = true,
'u' => flags.unicode = true,
'v' => flags.unicode_sets = true,
'y' => flags_unsupported = true, // sticky search is not supported
_ => panic!("Unknown flag: {flag:?}"),
}
for flag in flag_options.chars() {
#[allow(clippy::match_same_arms)]
match flag {
'd' => flags_unsupported = true, // indices for substring matches are not supported
'g' => flags_unsupported = true, // stateful regex is not supported
'i' => flags.icase = true,
'm' => flags.multiline = true,
's' => flags.dot_all = true,
'u' => flags.unicode = true,
'v' => flags.unicode_sets = true,
'y' => flags_unsupported = true, // sticky search is not supported
// Should be caught by parser errors
_ => panic!("Unknown flag: {flag:?}"),
}
}

let compiled_regex = {
let mut ire = backends::try_parse(pattern.chars().map(u32::from), flags)
.map_err(|err| err.text)?;

if !flags.no_opt {
backends::optimize(&mut ire);
}
Expand Down Expand Up @@ -316,10 +311,7 @@ impl BinarySerializable for RegExp {

fn deserialize<I: Iterator<Item = u8>>(iter: &mut I, source_id: SourceId) -> Self {
let source = String::deserialize(iter, source_id);

let (pattern, flags) = source[1..].rsplit_once('/').unwrap();
let flags = if flags.is_empty() { None } else { Some(flags) };

Self::new(pattern, flags).unwrap()
}
}
5 changes: 2 additions & 3 deletions checker/src/types/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,12 +497,11 @@ impl TypeStore {
pub fn new_regexp(
&mut self,
pattern: &str,
flags: &Option<String>,
flags: &str,
_position: &Span,
) -> Result<TypeId, String> {
let regexp = RegExp::new(pattern, flags.as_ref().map(String::as_str))?;
let regexp = RegExp::new(pattern, flags)?;
let ty = Type::SpecialObject(SpecialObject::RegularExpression(regexp));

Ok(self.register_type(ty))
}

Expand Down
11 changes: 5 additions & 6 deletions parser/src/expressions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ pub enum Expression {
BooleanLiteral(bool, Span),
RegexLiteral {
pattern: String,
flags: Option<String>,
/// Can be `""`
flags: String,
position: Span,
},
ArrayLiteral(Vec<ArrayElement>, Span),
Expand Down Expand Up @@ -283,10 +284,10 @@ impl Expression {
}
} else if reader.starts_with('/') {
let (pattern, flags) = reader.parse_regex_literal()?;
let position = start.with_length(2 + pattern.len() + flags.map_or(0, str::len));
let position = start.with_length(2 + pattern.len() + flags.len());
Expression::RegexLiteral {
pattern: pattern.to_owned(),
flags: flags.map(ToOwned::to_owned),
flags: flags.to_owned(),
position,
}
} else if reader.is_operator_advance("[") {
Expand Down Expand Up @@ -1093,9 +1094,7 @@ impl Expression {
buf.push('/');
buf.push_str(pattern);
buf.push('/');
if let Some(flags) = flags {
buf.push_str(flags);
}
buf.push_str(flags);
}
Self::BinaryOperation { lhs, operator, rhs, .. } => {
lhs.to_string_using_precedence(
Expand Down
18 changes: 13 additions & 5 deletions parser/src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,8 @@ impl<'a> Lexer<'a> {
Ok((number, length))
}

pub fn parse_regex_literal(&mut self) -> Result<(&'a str, Option<&'a str>), ParseError> {
/// Returns content and flags. Flags can be empty
pub fn parse_regex_literal(&mut self) -> Result<(&'a str, &'a str), ParseError> {
let mut escaped = false;
let mut after_last_slash = false;
let mut in_set = false;
Expand Down Expand Up @@ -776,15 +777,22 @@ impl<'a> Lexer<'a> {
}

let regex = &current[1..regex_content];
self.head += 2 + regex.len() as u32;
let regex_end = regex_content + '/'.len_utf8();

let first_non_char = chars
.find_map(|(idx, chr)| (!chr.is_alphabetic()).then_some(idx))
.unwrap_or(current.len());
let regex_flag = &current[regex_end..first_non_char];

self.head += (2 + regex.len() + regex_flag.len()) as u32;

Ok((regex, (!regex_flag.is_empty()).then_some(regex_flag)))
let regex_flags = &current[regex_end..first_non_char];

let invalid_flag = regex_flags.chars().any(|chr| !matches!(chr, 'd' | 'g' | 'i' | 'm' | 's' | 'u' | 'y'));
if invalid_flag {
Err(ParseError::new(ParseErrors::InvalidRegexFlag, self.get_start().with_length(regex_flags.len())))
} else {
self.head += regex_flags.len() as u32;
Ok((regex, regex_flags))
}
}

pub fn parse_comment_literal(&mut self, is_multiline: bool) -> Result<&str, ParseError> {
Expand Down

0 comments on commit 3aacc07

Please sign in to comment.