diff options
author | Titus Wormer <tituswormer@gmail.com> | 2022-06-21 16:06:50 +0200 |
---|---|---|
committer | Titus Wormer <tituswormer@gmail.com> | 2022-06-21 16:06:50 +0200 |
commit | c6f92eaedf197beafef461ee6c2bd067e7160c49 (patch) | |
tree | c919113a51065c5d8126991cde1edf7fd6609e8b /src/construct/partial_label.rs | |
parent | bcc4676b84a06af5e38ebaa31f0217cae090be08 (diff) | |
download | markdown-rs-c6f92eaedf197beafef461ee6c2bd067e7160c49.tar.gz markdown-rs-c6f92eaedf197beafef461ee6c2bd067e7160c49.tar.bz2 markdown-rs-c6f92eaedf197beafef461ee6c2bd067e7160c49.zip |
Refactor to improve a bunch of states
* Improve passing stuff around
* Add traits to enums for markers and such
* Fix “life time” stuff I didn’t understand
Diffstat (limited to 'src/construct/partial_label.rs')
-rw-r--r-- | src/construct/partial_label.rs | 111 |
1 files changed, 52 insertions, 59 deletions
diff --git a/src/construct/partial_label.rs b/src/construct/partial_label.rs index 55efd13..194165c 100644 --- a/src/construct/partial_label.rs +++ b/src/construct/partial_label.rs @@ -60,6 +60,17 @@ use crate::construct::partial_space_or_tab::space_or_tab_opt; use crate::tokenizer::{Code, State, StateFnResult, TokenType, Tokenizer}; use crate::util::link::link; +/// State needed to parse labels. +#[derive(Debug)] +struct Info { + /// Whether we’ve seen our first `ChunkString`. + connect: bool, + /// Whether there are non-blank characters in the label. + data: bool, + /// Number of characters in the label. + size: usize, +} + /// Before a label. /// /// ```markdown @@ -73,10 +84,12 @@ pub fn start(tokenizer: &mut Tokenizer, code: Code) -> StateFnResult { tokenizer.consume(code); tokenizer.exit(TokenType::DefinitionLabelMarker); tokenizer.enter(TokenType::DefinitionLabelData); - ( - State::Fn(Box::new(|t, c| at_break(t, c, false, 0, false))), - None, - ) + let info = Info { + connect: false, + data: false, + size: 0, + }; + (State::Fn(Box::new(|t, c| at_break(t, c, info))), None) } _ => (State::Nok, None), } @@ -88,17 +101,11 @@ pub fn start(tokenizer: &mut Tokenizer, code: Code) -> StateFnResult { /// [|a] /// [a|] /// ``` -fn at_break( - tokenizer: &mut Tokenizer, - code: Code, - data: bool, - size: usize, - connect: bool, -) -> StateFnResult { +fn at_break(tokenizer: &mut Tokenizer, code: Code, info: Info) -> StateFnResult { match code { Code::None | Code::Char('[') => (State::Nok, None), - Code::Char(']') if !data => (State::Nok, None), - _ if size > LINK_REFERENCE_SIZE_MAX => (State::Nok, None), + Code::Char(']') if !info.data => (State::Nok, None), + _ if info.size > LINK_REFERENCE_SIZE_MAX => (State::Nok, None), Code::Char(']') => { tokenizer.exit(TokenType::DefinitionLabelData); tokenizer.enter(TokenType::DefinitionLabelMarker); @@ -110,12 +117,12 @@ fn at_break( _ => { tokenizer.enter(TokenType::ChunkString); - if connect { + if info.connect { let index = tokenizer.events.len() - 1; link(&mut tokenizer.events, index); } - label(tokenizer, code, data, size) + label(tokenizer, code, info) } } } @@ -126,16 +133,8 @@ fn at_break( /// [a /// |b] /// ``` -fn line_start( - tokenizer: &mut Tokenizer, - code: Code, - data: bool, - size: usize, - connect: bool, -) -> StateFnResult { - tokenizer.go(space_or_tab_opt(), move |t, c| { - line_begin(t, c, data, size, connect) - })(tokenizer, code) +fn line_start(tokenizer: &mut Tokenizer, code: Code, info: Info) -> StateFnResult { + tokenizer.go(space_or_tab_opt(), |t, c| line_begin(t, c, info))(tokenizer, code) } /// After a line ending, after optional whitespace. @@ -144,17 +143,11 @@ fn line_start( /// [a /// |b] /// ``` -fn line_begin( - tokenizer: &mut Tokenizer, - code: Code, - data: bool, - size: usize, - connect: bool, -) -> StateFnResult { +fn line_begin(tokenizer: &mut Tokenizer, code: Code, info: Info) -> StateFnResult { match code { // Blank line not allowed. Code::CarriageReturnLineFeed | Code::Char('\r' | '\n') => (State::Nok, None), - _ => at_break(tokenizer, code, data, size, connect), + _ => at_break(tokenizer, code, info), } } @@ -163,44 +156,46 @@ fn line_begin( /// ```markdown /// [a|b] /// ``` -fn label(tokenizer: &mut Tokenizer, code: Code, data: bool, size: usize) -> StateFnResult { +fn label(tokenizer: &mut Tokenizer, code: Code, mut info: Info) -> StateFnResult { + if !info.connect { + info.connect = true; + } + match code { Code::None | Code::Char('[' | ']') => { tokenizer.exit(TokenType::ChunkString); - at_break(tokenizer, code, data, size, true) + at_break(tokenizer, code, info) } - _ if size > LINK_REFERENCE_SIZE_MAX => { + _ if info.size > LINK_REFERENCE_SIZE_MAX => { tokenizer.exit(TokenType::ChunkString); - at_break(tokenizer, code, data, size, true) + at_break(tokenizer, code, info) } Code::CarriageReturnLineFeed | Code::Char('\r' | '\n') => { tokenizer.consume(code); + info.size += 1; tokenizer.exit(TokenType::ChunkString); - ( - State::Fn(Box::new(move |t, c| line_start(t, c, data, size + 1, true))), - None, - ) + (State::Fn(Box::new(|t, c| line_start(t, c, info))), None) } Code::VirtualSpace | Code::Char('\t' | ' ') => { tokenizer.consume(code); - ( - State::Fn(Box::new(move |t, c| label(t, c, data, size + 1))), - None, - ) + info.size += 1; + (State::Fn(Box::new(|t, c| label(t, c, info))), None) } Code::Char('/') => { tokenizer.consume(code); - ( - State::Fn(Box::new(move |t, c| escape(t, c, true, size + 1))), - None, - ) + info.size += 1; + if !info.data { + info.data = true; + } + (State::Fn(Box::new(|t, c| escape(t, c, info))), None) } Code::Char(_) => { tokenizer.consume(code); - ( - State::Fn(Box::new(move |t, c| label(t, c, true, size + 1))), - None, - ) + info.size += 1; + if !info.data { + info.data = true; + } + (State::Fn(Box::new(|t, c| label(t, c, info))), None) } } } @@ -210,15 +205,13 @@ fn label(tokenizer: &mut Tokenizer, code: Code, data: bool, size: usize) -> Stat /// ```markdown /// [a\|[b] /// ``` -fn escape(tokenizer: &mut Tokenizer, code: Code, data: bool, size: usize) -> StateFnResult { +fn escape(tokenizer: &mut Tokenizer, code: Code, mut info: Info) -> StateFnResult { match code { Code::Char('[' | '\\' | ']') => { tokenizer.consume(code); - ( - State::Fn(Box::new(move |t, c| label(t, c, true, size + 1))), - None, - ) + info.size += 1; + (State::Fn(Box::new(|t, c| label(t, c, info))), None) } - _ => label(tokenizer, code, data, size), + _ => label(tokenizer, code, info), } } |