mirror of
https://github.com/Noratrieb/regex.git
synced 2026-01-16 17:35:01 +01:00
fixed stackoverflow
This commit is contained in:
parent
87f9f80e5e
commit
d9a115917c
1 changed files with 32 additions and 10 deletions
42
src/parse.rs
42
src/parse.rs
|
|
@ -20,13 +20,14 @@
|
||||||
use std::iter::Peekable;
|
use std::iter::Peekable;
|
||||||
use std::str::Chars;
|
use std::str::Chars;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Regex {
|
pub enum Regex {
|
||||||
Choice(Box<Regex>, Box<Regex>),
|
Choice(Box<Regex>, Box<Regex>),
|
||||||
Term(Vec<Regex>),
|
Sequence(Box<Regex>, Box<Regex>),
|
||||||
Repetition(Box<Regex>),
|
Repetition(Box<Regex>),
|
||||||
Primitive(char),
|
Primitive(char),
|
||||||
Char(char),
|
Char(char),
|
||||||
|
Blank,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -66,6 +67,7 @@ impl<'a> Parser<'a> {
|
||||||
fn regex(&mut self) -> RegexResult {
|
fn regex(&mut self) -> RegexResult {
|
||||||
let term = self.term()?;
|
let term = self.term()?;
|
||||||
if let Some('|') = self.peek() {
|
if let Some('|') = self.peek() {
|
||||||
|
let _ = self.next();
|
||||||
let rhs = self.regex()?;
|
let rhs = self.regex()?;
|
||||||
Ok(Regex::Choice(Box::new(term), Box::new(rhs)))
|
Ok(Regex::Choice(Box::new(term), Box::new(rhs)))
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -74,17 +76,17 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn term(&mut self) -> RegexResult {
|
fn term(&mut self) -> RegexResult {
|
||||||
let mut factors = Vec::new();
|
let mut factor = Regex::Blank;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match self.peek() {
|
if let None | Some(')') | Some('|') = self.peek() {
|
||||||
None | Some('(') | Some('|') => break,
|
break;
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
let next_factor = self.factor()?;
|
let next_factor = self.factor()?;
|
||||||
factors.push(next_factor);
|
factor = Regex::Sequence(Box::new(factor), Box::new(next_factor));
|
||||||
}
|
}
|
||||||
Ok(Regex::Term(factors))
|
|
||||||
|
Ok(factor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn factor(&mut self) -> RegexResult {
|
fn factor(&mut self) -> RegexResult {
|
||||||
|
|
@ -97,6 +99,7 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
Ok(base)
|
Ok(base)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn base(&mut self) -> RegexResult {
|
fn base(&mut self) -> RegexResult {
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some('(') => {
|
Some('(') => {
|
||||||
|
|
@ -107,7 +110,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
Some('\\') => {
|
Some('\\') => {
|
||||||
let _ = self.next();
|
let _ = self.next();
|
||||||
let esc = self.next().ok_or_else(|| ())?;
|
let esc = self.next().ok_or(())?;
|
||||||
Ok(Regex::Primitive(esc))
|
Ok(Regex::Primitive(esc))
|
||||||
}
|
}
|
||||||
Some(char) => {
|
Some(char) => {
|
||||||
|
|
@ -120,4 +123,23 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {}
|
mod test {
|
||||||
|
use crate::parse::{Parser, Regex};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn simple_choice() {
|
||||||
|
let regex = "a|b";
|
||||||
|
let parsed = Parser::parse(regex).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
parsed,
|
||||||
|
Regex::Choice(Box::new(Regex::Char('a')), Box::new(Regex::Char('b')))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn repetition() {
|
||||||
|
let regex = "a*";
|
||||||
|
let parsed = Parser::parse(regex).unwrap();
|
||||||
|
assert_eq!(parsed, Regex::Repetition(Box::new(Regex::Char('a'))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue