diff --git a/src/regexp/token.rs b/src/regexp/token.rs --- a/src/regexp/token.rs +++ b/src/regexp/token.rs @@ -1,3 +1,32 @@ +use std::fmt; + +#[derive(Debug, Clone)] +pub enum ParsingError { + Asterisk {s: String, pos: usize}, + Plus {s: String, pos: usize}, + OpeningParenthesis {s: String, pos: usize}, + ClosingParenthesis {s: String, pos: usize} +} + +impl fmt::Display for ParsingError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + ParsingError::Asterisk {s, pos} => { + write!(f, "The asterisk operator is missing an argument. Pattern \"{s}\", position {pos}") + }, + ParsingError::Plus {s, pos} => { + write!(f, "The plus operator is missing an argument. Pattern \"{s}\", position {pos}") + }, + ParsingError::OpeningParenthesis {s, pos} => { + write!(f, "An opening parenthesis not found. Pattern \"{s}\", position {pos}") + }, + ParsingError::ClosingParenthesis {s, pos} => { + write!(f, "An closing parenthesis not found. Pattern \"{s}\", position {pos}") + } + } + } +} + pub trait Token { fn is_skippable(&self) -> bool {false} fn list_first(&self) -> Vec; @@ -144,7 +173,7 @@ fn find_closing_parenthesis(s: &String) return None; } -pub fn parse(pattern: &String, offset: usize) -> Chain { +pub fn parse(pattern: &String, offset: usize) -> Result { let chars: Vec = pattern.chars().collect(); let mut res: Vec> = Vec::new(); let mut i = 0; @@ -152,21 +181,24 @@ pub fn parse(pattern: &String, offset: u let c = chars[i]; match c { '(' => { - let j = find_closing_parenthesis(&pattern[i..].to_string()).unwrap() + i; - let inner_content = parse(&pattern[i+1..j].to_string(), offset+i+1); + let j = find_closing_parenthesis(&pattern[i..].to_string()).ok_or(ParsingError::ClosingParenthesis {s: pattern.clone(), pos: i})? + i; + let inner_content = parse(&pattern[i+1..j].to_string(), offset+i+1)?; res.push(Box::new(inner_content)); i = j+1; } '*' => { - let token = res.pop().unwrap(); + let token = res.pop().ok_or(ParsingError::Asterisk{s: pattern.clone(), pos: i})?; res.push(Box::new(Asterisk{content: token})); i += 1; } '+' => { - let token = res.pop().unwrap(); + let token = res.pop().ok_or(ParsingError::Plus{s: pattern.clone(), pos: i})?; res.push(Box::new(Plus{content: token})); i += 1; } + ')' => { + return Err(ParsingError::OpeningParenthesis {s: pattern.clone(), pos: i}); + } c => { res.push(Box::new(Symbol{position: i+offset, value: c})); i += 1; @@ -174,7 +206,7 @@ pub fn parse(pattern: &String, offset: u } } - return Chain{content: res}; + return Ok(Chain{content: res}); } mod test {