From cc88a4240a8cced4f7c7ed2e334095ff982fd046 Mon Sep 17 00:00:00 2001 From: electria Date: Wed, 15 Jul 2026 23:13:09 -0700 Subject: [PATCH] docs: explain some of the string parsing --- src/nodes/from_str.rs | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/nodes/from_str.rs b/src/nodes/from_str.rs index 57bf3e3..17d1bf6 100644 --- a/src/nodes/from_str.rs +++ b/src/nodes/from_str.rs @@ -25,16 +25,30 @@ enum ParsingState { impl FromStr for Nodes { type Err = Error; fn from_str(s: &str) -> Result { + /// A superset of `char::is_numeric` + /// that includes other characters parseable into numbers, + /// such as `.` (for decimal) and `e` for scientific notation. + fn is_number_char(c: char) -> bool { + match c { + '.' | 'e' => true, + c => c.is_numeric(), + } + } + /// A function to check if the given `char` should be used by the parser. + /// + /// We ignore whitespace since it has no semantic significance in typst aside from variables, + /// (which are not implemented) + /// and `&` because it is only used for visual alignment. + /// + /// Newlines are also ignored because they're likely accidental; like in the case of `echo 1+1 | tylc`. + fn is_not_ignored_char(c: &char) -> bool { + !matches!(c, ' ' | '&' | '\n') + } + let mut nodes = Vec::new(); let mut state = ParsingState::default(); - let is_ignored_char = |c: &char| !matches!(c, ' ' | '&' | '\n'); - let is_numeric_char = |c: char| match c { - '.' | 'e' => true, - c => c.is_numeric(), - }; - - let filtered_string: String = s.chars().filter(is_ignored_char).collect(); + let filtered_string: String = s.chars().filter(is_not_ignored_char).collect(); for (i, c) in filtered_string.char_indices() { match state { @@ -51,7 +65,7 @@ impl FromStr for Nodes { } } ParsingState::ReadingNumber(start_index) => { - if !is_numeric_char(c) { + if !is_number_char(c) { nodes.push(Node::Number( Float::parse(&filtered_string[start_index..i]) .map_err(|e| { @@ -69,7 +83,7 @@ impl FromStr for Nodes { } if state == ParsingState::Start { - if is_numeric_char(c) { + if is_number_char(c) { state = ParsingState::ReadingNumber(i); } else if c.is_alphabetic() { state = ParsingState::ReadingFunctionName(i);