From 01c7ba6e2a5393fec655f3ca3b3f63b3d3973772 Mon Sep 17 00:00:00 2001 From: elkowar <5300871+elkowar@users.noreply.github.com> Date: Tue, 27 Jul 2021 00:11:16 +0200 Subject: [PATCH] Add alternative string syntax with single quotes and backticks --- crates/simplexpr/src/parser/lexer.rs | 3 +++ crates/yuck/src/parser/lexer.rs | 17 +++++++++++++---- .../yuck__parser__lexer__yuck_lexer-5.snap | 16 ++++++++++++++++ examples/eww-bar/eww.yuck | 2 +- 4 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 crates/yuck/src/parser/snapshots/yuck__parser__lexer__yuck_lexer-5.snap diff --git a/crates/simplexpr/src/parser/lexer.rs b/crates/simplexpr/src/parser/lexer.rs index 166befc..b9bd352 100644 --- a/crates/simplexpr/src/parser/lexer.rs +++ b/crates/simplexpr/src/parser/lexer.rs @@ -40,7 +40,10 @@ pub enum Token { Ident(String), #[regex(r"[+-]?(?:[0-9]+[.])?[0-9]+", |x| x.slice().to_string())] NumLit(String), + #[regex(r#""(?:[^"\\]|\\.)*""#, |x| ESCAPE_REPLACE_REGEX.replace_all(x.slice(), "$1").to_string())] + #[regex(r#"`(?:[^`\\]|\\.)*`"#, |x| ESCAPE_REPLACE_REGEX.replace_all(x.slice(), "$1").to_string())] + #[regex(r#"'(?:[^'\\]|\\.)*'"#, |x| ESCAPE_REPLACE_REGEX.replace_all(x.slice(), "$1").to_string())] StrLit(String), diff --git a/crates/yuck/src/parser/lexer.rs b/crates/yuck/src/parser/lexer.rs index 1d7dac5..222a8de 100644 --- a/crates/yuck/src/parser/lexer.rs +++ b/crates/yuck/src/parser/lexer.rs @@ -70,6 +70,8 @@ regex_rules! { r"true" => |_| Token::True, r"false" => |_| Token::False, r#""(?:[^"\\]|\\.)*""# => |x| Token::StrLit(ESCAPE_REPLACE_REGEX.replace_all(&x, "$1").to_string()), + r#"`(?:[^`\\]|\\.)*`"# => |x| Token::StrLit(ESCAPE_REPLACE_REGEX.replace_all(&x, "$1").to_string()), + r#"'(?:[^'\\]|\\.)*'"# => |x| Token::StrLit(ESCAPE_REPLACE_REGEX.replace_all(&x, "$1").to_string()), r#"[+-]?(?:[0-9]+[.])?[0-9]+"# => |x| Token::NumLit(x), r#":[^\s\)\]}]+"# => |x| Token::Keyword(x), r#"[a-zA-Z_!\?<>/\.\*-\+\-][^\s{}\(\)\[\](){}]*"# => |x| Token::Symbol(x), @@ -102,7 +104,7 @@ impl Iterator for Lexer { if string.starts_with('{') { let expr_start = self.pos; - let mut in_string = false; + let mut in_string = None; loop { if self.pos >= self.source.len() { return None; @@ -112,13 +114,19 @@ impl Iterator for Lexer { } let string = &self.source[self.pos..]; - if string.starts_with('}') && !in_string { + if string.starts_with('}') && in_string.is_none() { self.pos += 1; let tok_str = &self.source[expr_start..self.pos]; return Some(Ok((expr_start, Token::SimplExpr(tok_str.to_string()), self.pos - 1))); - } else if string.starts_with('"') { + } else if string.starts_with('"') || string.starts_with('\'') || string.starts_with('`') { + if let Some(quote) = in_string { + if string.starts_with(quote) { + in_string = None; + } + } else { + in_string = Some(string.chars().next().unwrap()); + } self.pos += 1; - in_string = !in_string; } else if string.starts_with("\\\"") { self.pos += 2; } else { @@ -165,4 +173,5 @@ fn test_yuck_lexer() { insta::assert_debug_snapshot!(Lexer::new(0, r#"{ bla "} \" }" " \" "}"#.to_string()).collect_vec()); insta::assert_debug_snapshot!(Lexer::new(0, r#""< \" >""#.to_string()).collect_vec()); insta::assert_debug_snapshot!(Lexer::new(0, r#"{ " " + music}"#.to_string()).collect_vec()); + insta::assert_debug_snapshot!(Lexer::new(0, r#"{ " } ' }" }"#.to_string()).collect_vec()); } diff --git a/crates/yuck/src/parser/snapshots/yuck__parser__lexer__yuck_lexer-5.snap b/crates/yuck/src/parser/snapshots/yuck__parser__lexer__yuck_lexer-5.snap new file mode 100644 index 0000000..0e4ea1b --- /dev/null +++ b/crates/yuck/src/parser/snapshots/yuck__parser__lexer__yuck_lexer-5.snap @@ -0,0 +1,16 @@ +--- +source: crates/yuck/src/parser/lexer.rs +expression: "Lexer::new(0, r#\"{ \" } ' }\" }\"#.to_string()).collect_vec()" + +--- +[ + Ok( + ( + 0, + SimplExpr( + "{ \" } ' }\" }", + ), + 11, + ), + ), +] diff --git a/examples/eww-bar/eww.yuck b/examples/eww-bar/eww.yuck index 1c769f0..d21e6e0 100644 --- a/examples/eww-bar/eww.yuck +++ b/examples/eww-bar/eww.yuck @@ -24,7 +24,7 @@ (defwidget music [] (box :class "music" :orientation "h" :space-evenly false :halign "center" - { " " + music})) + { ' ' + music})) (defwidget slider-vol [] (box :class "slider-vol" :orientation "h" :space-evenly "false"