diff options
author | Titus Wormer <tituswormer@gmail.com> | 2022-06-21 17:24:56 +0200 |
---|---|---|
committer | Titus Wormer <tituswormer@gmail.com> | 2022-06-21 17:24:56 +0200 |
commit | 56ff5c73c7ec19b349e7d60d04ce1057c006d6ec (patch) | |
tree | b4107ae0e0219f871a2f2764215ad979b2b0d75f /src/construct/partial_data.rs | |
parent | 7effd171218fff68f051671f1373cee467a8f921 (diff) | |
download | markdown-rs-56ff5c73c7ec19b349e7d60d04ce1057c006d6ec.tar.gz markdown-rs-56ff5c73c7ec19b349e7d60d04ce1057c006d6ec.tar.bz2 markdown-rs-56ff5c73c7ec19b349e7d60d04ce1057c006d6ec.zip |
Make data a construct
Diffstat (limited to 'src/construct/partial_data.rs')
-rw-r--r-- | src/construct/partial_data.rs | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/construct/partial_data.rs b/src/construct/partial_data.rs new file mode 100644 index 0000000..d83787a --- /dev/null +++ b/src/construct/partial_data.rs @@ -0,0 +1,69 @@ +//! Data occurs in [text][] and [string][]. +//! +//! It can include anything (including line endings), and stops at certain +//! characters. +//! +//! [string]: crate::content::string +//! [text]: crate::content::text + +// To do: pass token types in? + +use crate::tokenizer::{Code, State, StateFnResult, TokenType, Tokenizer}; + +/// At the beginning of data. +/// +/// ```markdown +/// |&qwe +/// ``` +pub fn start(tokenizer: &mut Tokenizer, code: Code, stop: Vec<Code>) -> StateFnResult { + if stop.contains(&code) { + tokenizer.enter(TokenType::Data); + tokenizer.consume(code); + (State::Fn(Box::new(|t, c| data(t, c, stop))), None) + } else { + at_break(tokenizer, code, stop) + } +} + +/// Before something. +/// +/// ```markdown +/// |qwe| |& +/// ``` +fn at_break(tokenizer: &mut Tokenizer, code: Code, stop: Vec<Code>) -> StateFnResult { + match code { + Code::None => (State::Ok, None), + Code::CarriageReturnLineFeed | Code::Char('\r' | '\n') => { + tokenizer.enter(TokenType::LineEnding); + tokenizer.consume(code); + tokenizer.exit(TokenType::LineEnding); + (State::Fn(Box::new(|t, c| at_break(t, c, stop))), None) + } + _ if stop.contains(&code) => (State::Ok, Some(vec![code])), + _ => { + tokenizer.enter(TokenType::Data); + data(tokenizer, code, stop) + } + } +} + +/// In data. +/// +/// ```markdown +/// q|w|e +/// ``` +fn data(tokenizer: &mut Tokenizer, code: Code, stop: Vec<Code>) -> StateFnResult { + let done = match code { + Code::None | Code::CarriageReturnLineFeed | Code::Char('\r' | '\n') => true, + _ if stop.contains(&code) => true, + _ => false, + }; + + if done { + tokenizer.exit(TokenType::Data); + at_break(tokenizer, code, stop) + } else { + tokenizer.consume(code); + (State::Fn(Box::new(|t, c| data(t, c, stop))), None) + } +} |