Skip to content

Commit

Permalink
refactor: simplify code structure with visitors
Browse files Browse the repository at this point in the history
  • Loading branch information
Aloso committed Nov 2, 2023
1 parent 19c8b5c commit bf78b88
Show file tree
Hide file tree
Showing 21 changed files with 402 additions and 383 deletions.
65 changes: 65 additions & 0 deletions pomsky-lib/src/capturing_groups.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use std::collections::HashMap;

use pomsky_syntax::exprs::{self, Capture, GroupKind};

use crate::{
diagnose::{CompileError, CompileErrorKind},
visitor::RuleVisitor,
};

#[derive(Default)]
pub(crate) struct CapturingGroupsCollector {
pub(crate) count: u32,
pub(crate) names: HashMap<String, u32>,
pub(crate) within_variable: bool,
}

impl CapturingGroupsCollector {
pub(crate) fn new() -> Self {
CapturingGroupsCollector::default()
}
}

impl RuleVisitor<CompileError> for CapturingGroupsCollector {
fn down(&mut self, kind: crate::visitor::NestingKind) {
if let crate::visitor::NestingKind::Let = kind {
self.within_variable = true;
}
}

fn visit_group(&mut self, group: &exprs::Group) -> Result<(), CompileError> {
match group.kind {
GroupKind::Capturing(Capture { name: Some(name) }) => {
if self.within_variable {
return Err(CompileErrorKind::CaptureInLet.at(group.span));
}

if self.names.contains_key(name) {
return Err(
CompileErrorKind::NameUsedMultipleTimes(name.to_string()).at(group.span)
);
}

self.count += 1;
self.names.insert(name.to_string(), self.count);
}
GroupKind::Capturing(Capture { name: None }) => {
if self.within_variable {
return Err(CompileErrorKind::CaptureInLet.at(group.span));
}

self.count += 1;
}
_ => {}
}

Ok(())
}

fn visit_reference(&mut self, reference: &exprs::Reference) -> Result<(), CompileError> {
if self.within_variable {
return Err(CompileErrorKind::ReferenceInLet.at(reference.span));
}
Ok(())
}
}
17 changes: 0 additions & 17 deletions pomsky-lib/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,3 @@ impl<'c, 'i> CompileState<'c, 'i> {
}
}
}

#[derive(Clone)]
pub(crate) struct ValidationState {
pub(crate) is_top_layer: bool,
}

impl ValidationState {
pub(crate) fn new() -> Self {
ValidationState { is_top_layer: true }
}

pub(crate) fn layer_down(&mut self) -> Self {
let mut new = self.clone();
new.is_top_layer = false;
new
}
}
28 changes: 1 addition & 27 deletions pomsky-lib/src/exprs/alternation.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,15 @@
//! Implements [alternation](https://www.regular-expressions.info/alternation.html):
//! `('alt1' | 'alt2' | 'alt3')`.

use std::collections::HashMap;

use crate::{
compile::{CompileResult, CompileState, ValidationState},
diagnose::CompileError,
compile::{CompileResult, CompileState},
options::{CompileOptions, RegexFlavor},
regex::Regex,
};

use super::{Alternation, RuleExt};

impl<'i> RuleExt<'i> for Alternation<'i> {
fn get_capturing_groups(
&self,
count: &mut u32,
map: &'i mut HashMap<String, u32>,
within_variable: bool,
) -> Result<(), CompileError> {
for rule in &self.rules {
rule.get_capturing_groups(count, map, within_variable)?;
}
Ok(())
}

fn compile<'c>(
&'c self,
options: CompileOptions,
Expand All @@ -38,17 +23,6 @@ impl<'i> RuleExt<'i> for Alternation<'i> {
.collect::<Result<_, _>>()?,
}))
}

fn validate(
&self,
options: &CompileOptions,
state: &mut ValidationState,
) -> Result<(), CompileError> {
for rule in &self.rules {
rule.validate(options, state)?;
}
Ok(())
}
}

#[cfg_attr(feature = "dbg", derive(Debug))]
Expand Down
13 changes: 2 additions & 11 deletions pomsky-lib/src/exprs/boundary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
use pomsky_syntax::exprs::{Boundary, BoundaryKind};

use crate::{
compile::{CompileResult, CompileState, ValidationState},
diagnose::{CompileError, CompileErrorKind},
features::PomskyFeatures,
compile::{CompileResult, CompileState},
diagnose::CompileErrorKind,
options::{CompileOptions, RegexFlavor},
regex::Regex,
};
Expand All @@ -31,14 +30,6 @@ impl<'i> RuleExt<'i> for Boundary {
Ok(Regex::Boundary(self.kind))
}
}

fn validate(
&self,
options: &CompileOptions,
_: &mut ValidationState,
) -> Result<(), CompileError> {
options.allowed_features.require(PomskyFeatures::BOUNDARIES, self.span)
}
}

pub(crate) fn boundary_kind_codegen(bk: BoundaryKind, buf: &mut String, flavor: RegexFlavor) {
Expand Down
12 changes: 1 addition & 11 deletions pomsky-lib/src/exprs/dot.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
//! Contains the [`Grapheme`] type, which matches a
//! [Unicode grapheme](https://www.regular-expressions.info/unicode.html#grapheme).

use pomsky_syntax::Span;

use crate::{
compile::CompileResult, diagnose::CompileError, features::PomskyFeatures,
options::CompileOptions, regex::Regex,
};
use crate::{compile::CompileResult, options::CompileOptions, regex::Regex};

/// The dot, matching anything except line breaks
#[derive(Clone, Copy, PartialEq, Eq)]
Expand All @@ -17,9 +12,4 @@ impl Dot {
pub(crate) fn compile(&self, _: CompileOptions) -> CompileResult<'static> {
Ok(Regex::Dot)
}

pub(crate) fn validate(&self, options: &CompileOptions) -> Result<(), CompileError> {
options.allowed_features.require(PomskyFeatures::DOT, Span::empty())?;
Ok(())
}
}
8 changes: 1 addition & 7 deletions pomsky-lib/src/exprs/grapheme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ use pomsky_syntax::Span;

use crate::{
compile::CompileResult,
diagnose::{CompileError, CompileErrorKind, Feature},
features::PomskyFeatures,
diagnose::{CompileErrorKind, Feature},
options::{CompileOptions, RegexFlavor},
regex::Regex,
};
Expand All @@ -25,9 +24,4 @@ impl Grapheme {
Err(CompileErrorKind::Unsupported(Feature::Grapheme, options.flavor).at(Span::empty()))
}
}

pub(crate) fn validate(&self, options: &CompileOptions) -> Result<(), CompileError> {
options.allowed_features.require(PomskyFeatures::GRAPHEME, Span::empty())?;
Ok(())
}
}
70 changes: 1 addition & 69 deletions pomsky-lib/src/exprs/group.rs
Original file line number Diff line number Diff line change
@@ -1,54 +1,14 @@
use std::collections::HashMap;

use pomsky_syntax::exprs::{Capture, Group, GroupKind};

use crate::{
compile::{CompileResult, CompileState, ValidationState},
diagnose::{CompileError, CompileErrorKind, Feature},
features::PomskyFeatures,
compile::{CompileResult, CompileState},
options::{CompileOptions, RegexFlavor},
regex::Regex,
};

use super::RuleExt;

impl<'i> RuleExt<'i> for Group<'i> {
fn get_capturing_groups(
&self,
count: &mut u32,
map: &mut HashMap<String, u32>,
within_variable: bool,
) -> Result<(), CompileError> {
match self.kind {
GroupKind::Capturing(Capture { name: Some(name) }) => {
if within_variable {
return Err(CompileErrorKind::CaptureInLet.at(self.span));
}

if map.contains_key(name) {
return Err(
CompileErrorKind::NameUsedMultipleTimes(name.to_string()).at(self.span)
);
}

*count += 1;
map.insert(name.to_string(), *count);
}
GroupKind::Capturing(Capture { name: None }) => {
if within_variable {
return Err(CompileErrorKind::CaptureInLet.at(self.span));
}

*count += 1;
}
_ => {}
};
for rule in &self.parts {
rule.get_capturing_groups(count, map, within_variable)?;
}
Ok(())
}

fn compile<'c>(
&'c self,
options: CompileOptions,
Expand All @@ -74,34 +34,6 @@ impl<'i> RuleExt<'i> for Group<'i> {
},
}))
}

fn validate(
&self,
options: &CompileOptions,
state: &mut ValidationState,
) -> Result<(), CompileError> {
if let GroupKind::Atomic = self.kind {
options.allowed_features.require(PomskyFeatures::ATOMIC_GROUPS, self.span)?;

if let RegexFlavor::JavaScript | RegexFlavor::Rust = options.flavor {
return Err(CompileErrorKind::Unsupported(Feature::AtomicGroups, options.flavor)
.at(self.span));
}
} else if let GroupKind::Capturing(c) = self.kind {
let feature = match &c.name {
Some(_) => PomskyFeatures::NAMED_GROUPS,
None => PomskyFeatures::NUMBERED_GROUPS,
};

options.allowed_features.require(feature, self.span)?;
}

let mut new_state = state.layer_down();
for rule in &self.parts {
rule.validate(options, &mut new_state)?;
}
Ok(())
}
}

#[cfg_attr(feature = "dbg", derive(Debug))]
Expand Down
40 changes: 4 additions & 36 deletions pomsky-lib/src/exprs/lookaround.rs
Original file line number Diff line number Diff line change
@@ -1,67 +1,35 @@
use std::collections::HashMap;

use pomsky_syntax::exprs::{Lookaround, LookaroundKind};

use crate::{
compile::{CompileResult, CompileState, ValidationState},
diagnose::{CompatWarning, CompileError, CompileErrorKind, CompileWarningKind, Feature},
features::PomskyFeatures,
compile::{CompileResult, CompileState},
diagnose::{CompatWarning, CompileWarningKind},
options::{CompileOptions, RegexFlavor},
regex::Regex,
};

use super::RuleExt;

impl<'i> RuleExt<'i> for Lookaround<'i> {
fn get_capturing_groups(
&self,
count: &mut u32,
map: &'i mut HashMap<String, u32>,
within_variable: bool,
) -> Result<(), CompileError> {
self.rule.get_capturing_groups(count, map, within_variable)
}

fn compile<'c>(
&'c self,
options: CompileOptions,
state: &mut CompileState<'c, 'i>,
) -> CompileResult<'i> {
match options.flavor {
RegexFlavor::Rust => {
return Err(CompileErrorKind::Unsupported(Feature::Lookaround, options.flavor)
.at(self.span));
}
RegexFlavor::JavaScript
if matches!(self.kind, LookaroundKind::Behind | LookaroundKind::BehindNegative) =>
{
if let RegexFlavor::JavaScript = options.flavor {
if let LookaroundKind::Behind | LookaroundKind::BehindNegative = self.kind {
state.diagnostics.push(
CompileWarningKind::Compat(CompatWarning::JsLookbehind)
.at(self.span)
.diagnostic(),
);
}
_ => (),
}

Ok(Regex::Lookaround(Box::new(RegexLookaround {
content: self.rule.compile(options, state)?,
kind: self.kind,
})))
}

fn validate(
&self,
options: &CompileOptions,
state: &mut ValidationState,
) -> Result<(), CompileError> {
let feature = match self.kind {
LookaroundKind::Ahead | LookaroundKind::AheadNegative => PomskyFeatures::LOOKAHEAD,
LookaroundKind::Behind | LookaroundKind::BehindNegative => PomskyFeatures::LOOKBEHIND,
};
options.allowed_features.require(feature, self.span)?;
self.rule.validate(options, &mut state.layer_down())
}
}

#[cfg_attr(feature = "dbg", derive(Debug))]
Expand Down
Loading

0 comments on commit bf78b88

Please sign in to comment.