From 56ff5c73c7ec19b349e7d60d04ce1057c006d6ec Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 21 Jun 2022 17:24:56 +0200 Subject: Make data a construct --- src/construct/partial_data.rs | 69 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/construct/partial_data.rs (limited to 'src/construct/partial_data.rs') 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) -> 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) -> 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) -> 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) + } +} -- cgit