aboutsummaryrefslogtreecommitdiffstats
path: root/src/construct/partial_space_or_tab.rs
diff options
context:
space:
mode:
authorLibravatar Titus Wormer <tituswormer@gmail.com>2022-08-02 14:27:31 +0200
committerLibravatar Titus Wormer <tituswormer@gmail.com>2022-08-02 14:27:31 +0200
commit8ffed1822bcbc1b6ce6647b840fb03996b0635ea (patch)
treedc01319d360b6e5ec08c893413ff056d3abd43bc /src/construct/partial_space_or_tab.rs
parent13cf914b5162fb12c842e983538b42d4b60cdcb8 (diff)
downloadmarkdown-rs-8ffed1822bcbc1b6ce6647b840fb03996b0635ea.tar.gz
markdown-rs-8ffed1822bcbc1b6ce6647b840fb03996b0635ea.tar.bz2
markdown-rs-8ffed1822bcbc1b6ce6647b840fb03996b0635ea.zip
Refactor to remove most closures
Diffstat (limited to 'src/construct/partial_space_or_tab.rs')
-rw-r--r--src/construct/partial_space_or_tab.rs191
1 files changed, 113 insertions, 78 deletions
diff --git a/src/construct/partial_space_or_tab.rs b/src/construct/partial_space_or_tab.rs
index f31cbc6..e3eac45 100644
--- a/src/construct/partial_space_or_tab.rs
+++ b/src/construct/partial_space_or_tab.rs
@@ -32,26 +32,6 @@ pub struct EolOptions {
pub content_type: Option<ContentType>,
}
-/// State needed to parse `space_or_tab`.
-#[derive(Debug)]
-struct Info {
- /// Current size.
- size: usize,
- /// Configuration.
- options: Options,
-}
-
-/// State needed to parse `space_or_tab_eol`.
-#[derive(Debug)]
-struct EolInfo {
- /// Whether to connect the next whitespace to the event before.
- connect: bool,
- /// Whether there was initial whitespace.
- ok: bool,
- /// Configuration.
- options: EolOptions,
-}
-
/// One or more `space_or_tab`.
///
/// ```bnf
@@ -78,7 +58,14 @@ pub fn space_or_tab_min_max(min: usize, max: usize) -> Box<StateFn> {
/// `space_or_tab`, with the given options.
pub fn space_or_tab_with_options(options: Options) -> Box<StateFn> {
- Box::new(|t| start(t, Info { size: 0, options }))
+ Box::new(|tokenizer| {
+ tokenizer.tokenize_state.space_or_tab_connect = options.connect;
+ tokenizer.tokenize_state.space_or_tab_content_type = options.content_type;
+ tokenizer.tokenize_state.space_or_tab_min = options.min;
+ tokenizer.tokenize_state.space_or_tab_max = options.max;
+ tokenizer.tokenize_state.space_or_tab_token = options.kind;
+ start(tokenizer)
+ })
}
/// `space_or_tab`, or optionally `space_or_tab`, one `eol`, and
@@ -97,30 +84,28 @@ pub fn space_or_tab_eol() -> Box<StateFn> {
/// `space_or_tab_eol`, with the given options.
pub fn space_or_tab_eol_with_options(options: EolOptions) -> Box<StateFn> {
Box::new(move |tokenizer| {
- let mut info = EolInfo {
- connect: options.connect,
- ok: false,
- options,
- };
+ tokenizer.tokenize_state.space_or_tab_eol_content_type = options.content_type;
+ tokenizer.tokenize_state.space_or_tab_eol_connect = options.connect;
tokenizer.attempt(
space_or_tab_with_options(Options {
kind: Token::SpaceOrTab,
min: 1,
max: usize::MAX,
- content_type: info.options.content_type.clone(),
- connect: info.options.connect,
+ content_type: tokenizer
+ .tokenize_state
+ .space_or_tab_eol_content_type
+ .clone(),
+ connect: tokenizer.tokenize_state.space_or_tab_eol_connect,
}),
move |ok| {
- if ok {
- info.ok = ok;
-
- if info.options.content_type.is_some() {
- info.connect = true;
+ Box::new(move |tokenizer| {
+ if ok {
+ tokenizer.tokenize_state.space_or_tab_eol_ok = ok;
}
- }
- Box::new(|t| after_space_or_tab(t, info))
+ after_space_or_tab(tokenizer)
+ })
},
)(tokenizer)
})
@@ -132,28 +117,24 @@ pub fn space_or_tab_eol_with_options(options: EolOptions) -> Box<StateFn> {
/// > | a␠␠b
/// ^
/// ```
-fn start(tokenizer: &mut Tokenizer, mut info: Info) -> State {
+fn start(tokenizer: &mut Tokenizer) -> State {
match tokenizer.current {
- Some(b'\t' | b' ') if info.options.max > 0 => {
- tokenizer
- .enter_with_content(info.options.kind.clone(), info.options.content_type.clone());
+ Some(b'\t' | b' ') if tokenizer.tokenize_state.space_or_tab_max > 0 => {
+ tokenizer.enter_with_content(
+ tokenizer.tokenize_state.space_or_tab_token.clone(),
+ tokenizer.tokenize_state.space_or_tab_content_type.clone(),
+ );
- if info.options.content_type.is_some() {
+ if tokenizer.tokenize_state.space_or_tab_connect {
let index = tokenizer.events.len() - 1;
link(&mut tokenizer.events, index);
+ } else if tokenizer.tokenize_state.space_or_tab_content_type.is_some() {
+ tokenizer.tokenize_state.space_or_tab_connect = true;
}
- tokenizer.consume();
- info.size += 1;
- State::Fn(Box::new(|t| inside(t, info)))
- }
- _ => {
- if info.options.min == 0 {
- State::Ok
- } else {
- State::Nok
- }
+ inside(tokenizer)
}
+ _ => after(tokenizer),
}
}
@@ -163,24 +144,46 @@ fn start(tokenizer: &mut Tokenizer, mut info: Info) -> State {
/// > | a␠␠b
/// ^
/// ```
-fn inside(tokenizer: &mut Tokenizer, mut info: Info) -> State {
+fn inside(tokenizer: &mut Tokenizer) -> State {
match tokenizer.current {
- Some(b'\t' | b' ') if info.size < info.options.max => {
+ Some(b'\t' | b' ')
+ if tokenizer.tokenize_state.space_or_tab_size
+ < tokenizer.tokenize_state.space_or_tab_max =>
+ {
tokenizer.consume();
- info.size += 1;
- State::Fn(Box::new(|t| inside(t, info)))
+ tokenizer.tokenize_state.space_or_tab_size += 1;
+ State::Fn(Box::new(inside))
}
_ => {
- tokenizer.exit(info.options.kind.clone());
- if info.size >= info.options.min {
- State::Ok
- } else {
- State::Nok
- }
+ tokenizer.exit(tokenizer.tokenize_state.space_or_tab_token.clone());
+ after(tokenizer)
}
}
}
+/// After `space_or_tab`.
+///
+/// ```markdown
+/// > | a␠␠b
+/// ^
+/// ```
+fn after(tokenizer: &mut Tokenizer) -> State {
+ let state = if tokenizer.tokenize_state.space_or_tab_size
+ >= tokenizer.tokenize_state.space_or_tab_min
+ {
+ State::Ok
+ } else {
+ State::Nok
+ };
+ tokenizer.tokenize_state.space_or_tab_connect = false;
+ tokenizer.tokenize_state.space_or_tab_content_type = None;
+ tokenizer.tokenize_state.space_or_tab_size = 0;
+ tokenizer.tokenize_state.space_or_tab_max = 0;
+ tokenizer.tokenize_state.space_or_tab_min = 0;
+ tokenizer.tokenize_state.space_or_tab_token = Token::SpaceOrTab;
+ state
+}
+
/// `space_or_tab_eol`: after optionally first `space_or_tab`.
///
/// ```markdown
@@ -188,24 +191,49 @@ fn inside(tokenizer: &mut Tokenizer, mut info: Info) -> State {
/// ^
/// | b
/// ```
-fn after_space_or_tab(tokenizer: &mut Tokenizer, mut info: EolInfo) -> State {
- match tokenizer.current {
- Some(b'\n') => {
- tokenizer.enter_with_content(Token::LineEnding, info.options.content_type.clone());
+fn after_space_or_tab(tokenizer: &mut Tokenizer) -> State {
+ if tokenizer.tokenize_state.space_or_tab_eol_ok
+ && tokenizer
+ .tokenize_state
+ .space_or_tab_eol_content_type
+ .is_some()
+ {
+ tokenizer.tokenize_state.space_or_tab_eol_connect = true;
+ }
- if info.connect {
- let index = tokenizer.events.len() - 1;
- link(&mut tokenizer.events, index);
- } else if info.options.content_type.is_some() {
- info.connect = true;
- }
+ if let Some(b'\n') = tokenizer.current {
+ tokenizer.enter_with_content(
+ Token::LineEnding,
+ tokenizer
+ .tokenize_state
+ .space_or_tab_eol_content_type
+ .clone(),
+ );
- tokenizer.consume();
- tokenizer.exit(Token::LineEnding);
- State::Fn(Box::new(|t| after_eol(t, info)))
+ if tokenizer.tokenize_state.space_or_tab_eol_connect {
+ let index = tokenizer.events.len() - 1;
+ link(&mut tokenizer.events, index);
+ } else if tokenizer
+ .tokenize_state
+ .space_or_tab_eol_content_type
+ .is_some()
+ {
+ tokenizer.tokenize_state.space_or_tab_eol_connect = true;
}
- _ if info.ok => State::Ok,
- _ => State::Nok,
+
+ tokenizer.consume();
+ tokenizer.exit(Token::LineEnding);
+ State::Fn(Box::new(after_eol))
+ } else {
+ let state = if tokenizer.tokenize_state.space_or_tab_eol_ok {
+ State::Ok
+ } else {
+ State::Nok
+ };
+ tokenizer.tokenize_state.space_or_tab_eol_content_type = None;
+ tokenizer.tokenize_state.space_or_tab_eol_connect = false;
+ tokenizer.tokenize_state.space_or_tab_eol_ok = false;
+ state
}
}
@@ -217,14 +245,17 @@ fn after_space_or_tab(tokenizer: &mut Tokenizer, mut info: EolInfo) -> State {
/// ^
/// ```
#[allow(clippy::needless_pass_by_value)]
-fn after_eol(tokenizer: &mut Tokenizer, info: EolInfo) -> State {
+fn after_eol(tokenizer: &mut Tokenizer) -> State {
tokenizer.attempt_opt(
space_or_tab_with_options(Options {
kind: Token::SpaceOrTab,
min: 1,
max: usize::MAX,
- content_type: info.options.content_type,
- connect: info.connect,
+ content_type: tokenizer
+ .tokenize_state
+ .space_or_tab_eol_content_type
+ .clone(),
+ connect: tokenizer.tokenize_state.space_or_tab_eol_connect,
}),
after_more_space_or_tab,
)(tokenizer)
@@ -238,6 +269,10 @@ fn after_eol(tokenizer: &mut Tokenizer, info: EolInfo) -> State {
/// ^
/// ```
fn after_more_space_or_tab(tokenizer: &mut Tokenizer) -> State {
+ tokenizer.tokenize_state.space_or_tab_eol_content_type = None;
+ tokenizer.tokenize_state.space_or_tab_eol_connect = false;
+ tokenizer.tokenize_state.space_or_tab_eol_ok = false;
+
// Blank line not allowed.
if matches!(tokenizer.current, None | Some(b'\n')) {
State::Nok