Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/regex-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ edition.workspace = true
[dependencies]
clap = { version = "4.5.11", features = ["derive"] }
regex-core = { path = "../regex-core" }
thiserror = "1.0"
thiserror = "2.0.18"

[dev-dependencies]
tempfile = "3.0"
Expand Down
13 changes: 1 addition & 12 deletions crates/regex-core/src/engine/ast.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//! AST definitions for the regex engine.
#![allow(dead_code)]

/// Inclusive character range.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand All @@ -10,17 +9,6 @@ pub struct CharRange {
pub end: char,
}

Comment thread
shu-kitamura marked this conversation as resolved.
impl CharRange {
/// Creates a range when `start <= end`; otherwise returns `None`.
pub fn new(start: char, end: char) -> Option<Self> {
if start <= end {
Some(Self { start, end })
} else {
None
}
}
}

/// Character class.
///
/// `ranges` represents inclusive `[start, end]` spans.
Expand All @@ -41,6 +29,7 @@ impl CharClass {
}

/// Zero-width assertion kinds.
#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Predicate {
/// Line start assertion (`^`).
Expand Down
1 change: 0 additions & 1 deletion crates/regex-core/src/engine/compiler.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//! Compile an AST into an instruction sequence (`Instruction`).
#![allow(dead_code)]

use thiserror::Error;

Expand Down
1 change: 0 additions & 1 deletion crates/regex-core/src/engine/evaluator.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//! Evaluate an instruction sequence.
#![allow(dead_code)]

use std::collections::HashSet;

Expand Down
1 change: 0 additions & 1 deletion crates/regex-core/src/engine/instruction.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//! Instruction set used by the compiler and evaluator.
#![allow(dead_code)]

use std::fmt::{self, Display};

Expand Down
42 changes: 23 additions & 19 deletions crates/regex-core/src/engine/parser.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Recursive-descent parser for regex patterns.
//!
//! The parser converts a pattern string into an `Ast` used by the compiler.
#![allow(dead_code)]

use crate::engine::ast::{Ast, CharClass, CharRange, Predicate};
use thiserror::Error;
Expand Down Expand Up @@ -53,9 +52,9 @@ struct Parser {
captures: usize,
}

/// Parses `regex` and returns its AST representation.
pub fn parse(regex: &str) -> Result<Ast, ParseError> {
let mut parser = Parser::new(regex);
/// Parses `pattern` and returns its AST representation.
pub fn parse(pattern: &str) -> Result<Ast, ParseError> {
let mut parser = Parser::new(pattern);
let ast = parser.parse_expression()?;
if parser.peek().is_some() {
return Err(ParseError::UnexpectedChar(parser.peek().unwrap()));
Expand All @@ -65,9 +64,9 @@ pub fn parse(regex: &str) -> Result<Ast, ParseError> {

impl Parser {
/// Creates a parser from a pattern string.
fn new(regex: &str) -> Self {
fn new(pattern: &str) -> Self {
Self {
input: regex.chars().collect(),
input: pattern.chars().collect(),
pos: 0,
captures: 1,
}
Expand Down Expand Up @@ -205,10 +204,7 @@ impl Parser {
Some(ch) if Self::is_special_char(ch) => Err(ParseError::UnexpectedChar(ch)),
Some(_) => {
let ch = self.next().ok_or(ParseError::UnexpectedEnd)?;
Ok(Ast::CharClass(CharClass::new(
vec![CharRange { start: ch, end: ch }],
false,
)))
Ok(Self::parse_single_char(ch))
}
None => Err(ParseError::UnexpectedEnd),
}
Expand Down Expand Up @@ -287,7 +283,7 @@ impl Parser {
}
Ast::Backreference(num as usize)
}
_ => single_char_class(ch),
_ => Self::parse_single_char(ch),
};
Ok(ast)
}
Expand Down Expand Up @@ -369,21 +365,29 @@ impl Parser {
false
}
}
}

/// Builds an `Ast::CharClass` representing exactly one literal character.
fn single_char_class(ch: char) -> Ast {
Ast::CharClass(CharClass::new(
vec![CharRange { start: ch, end: ch }],
false,
))
/// Builds an `Ast::CharClass` that matches exactly one literal character.
fn parse_single_char(ch: char) -> Ast {
Ast::CharClass(CharClass::new(
vec![CharRange { start: ch, end: ch }],
false,
))
}
}

#[cfg(test)]
mod tests {
use super::{ParseError, Parser, parse, single_char_class};
use super::{ParseError, Parser, parse};
use crate::engine::ast::{Ast, CharClass, CharRange, Predicate};

/// helper to build a single-character class AST
fn single_char_class(ch: char) -> Ast {
Ast::CharClass(CharClass::new(
vec![CharRange { start: ch, end: ch }],
false,
))
}

Comment thread
shu-kitamura marked this conversation as resolved.
Outdated
#[test]
fn test_parse_abc() {
let actual = parse("abc").unwrap();
Expand Down