From 660f892d6cbd63076a98a6a906a2b71f0bcb7d5a Mon Sep 17 00:00:00 2001 From: Shautvast Date: Sun, 26 Jan 2025 12:36:27 +0100 Subject: [PATCH] test parsing styles and wiring them up with the structure elements --- src/lib.rs | 34 ++++++++++++++++++--------- src/parse/parser.rs | 57 +++++++++++++++++++++++++++++++-------------- 2 files changed, 63 insertions(+), 28 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 816299d..c778df9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,7 @@ use crate::parse::tokens::TokenType; use std::collections::HashMap; use std::fmt::Display; +#[derive(Debug)] pub struct Vis { pub structure: VisNode, pub styles: Vec, @@ -24,17 +25,28 @@ impl Vis { None } - pub fn get_style(&self, node: &VisNode) -> Option<&StyleNode> { - let style = self.styles.iter().find(|s| s.id_ref == node.id); - if style.is_none() && node.id != "structure" { - for child in &node.children { - if let Some(style) = self.get_style(child) { - return Some(style); - } + pub fn get_styles(&self, id: &str) -> HashMap { + // println!("get_styles {:?}", id); + let mut styles = HashMap::new(); + self.get_styles2(id, &mut styles); + styles + } + + fn get_styles2(&self, id: &str, styles: &mut HashMap) { + let node = self.get_node(id); + if let Some(node) = node { + // println!("node {:?}", node); + let style = self.styles.iter().find(|s| s.id_ref == node.id); + if let Some(style) = style { + style.attributes.iter().for_each(|(k, v)| { + if !styles.contains_key(k) { + styles.insert(k.clone(), v.clone()); + }; + }); + } + if let Some(parent) = &node.parent { + self.get_styles2(parent, styles); } - None - } else { - None } } } @@ -135,5 +147,5 @@ pub struct StyleNode { #[derive(Debug, Clone)] pub enum ContainerType { NonGroup, // needs thinking about - Group, + Group, // the idea is that group nodes don't have style, they just bequeath it to their children } diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 6fd31a3..5aa44af 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -14,13 +14,14 @@ pub fn parse_vis(contents: &str) -> anyhow::Result { let mut parser = Parser::new(tokens); let structure = parser.structure()?; - + let styles = parser.styles()?; + // println!("parsed styles{:?}", styles); let mut vis = Vis { structure: VisNode::new_node("structure", None::, structure), - styles: parser.styles()?, + styles, }; - // add bottom up references (sorry no actual refs, but clones) + // add bottom up references vis.structure.children.iter_mut().for_each(|node| { let c = node.clone(); node.children.iter_mut().for_each(|child| { @@ -44,6 +45,7 @@ impl Parser { if self.match_token(Structure) { self.elements() } else { + println!("No structure found"); Ok(vec![]) } } @@ -59,9 +61,7 @@ impl Parser { } fn element(&mut self) -> anyhow::Result { - // println!("node {:?}", self.peek()); let id = self.id()?; - // println!("id {}", id); let current = self.peek().clone(); if self.match_tokens(vec![ ArrowRight, @@ -72,7 +72,6 @@ impl Parser { self.edge(id, current) } else { let title = self.title()?; - // println!("title {:?}", title); let children = if self.check(&LeftBrace) { self.elements()? } else { @@ -104,7 +103,7 @@ impl Parser { fn string(&mut self) -> anyhow::Result { let text = self.peek().clone(); - let text = text.lexeme[1..text.lexeme.len() - 1].to_owned(); + let text = strip_surrounding(text.lexeme); self.consume(Str, "Expected quoted string")?; Ok(text) } @@ -116,6 +115,7 @@ impl Parser { } fn styles(&mut self) -> anyhow::Result> { + // println!("styles {:?}", self.peek()); if self.match_token(Styles) { self.consume(LeftBrace, "Expected '{'")?; let mut styles = vec![]; @@ -130,6 +130,7 @@ impl Parser { } fn style(&mut self) -> anyhow::Result { + // println!("style {:?}", self.peek()); if self.check(&Identifier) || self.check(&Structure) { let idref = if self.check(&Structure) { // only structure element can also be referenced @@ -137,10 +138,17 @@ impl Parser { } else { self.peek().lexeme.to_owned() }; + // println!("idref {:?}", idref); self.advance(); let containertype = self.containertype()?; + // println!("containertype {:?}", containertype); self.consume(RightParen, "Expected ')'")?; + if self.peek().tokentype == Colon { + // optional + self.advance(); + } self.consume(LeftBrace, "Expected '{'")?; + // println!("attributes {:?}", self.peek()); let attributes = self.style_elements()?; self.consume(RightBrace, "Expected '}'")?; @@ -155,13 +163,14 @@ impl Parser { } fn style_elements(&mut self) -> anyhow::Result> { + // println!("read attributes {:?}", self.peek()); let mut elements = HashMap::new(); let mut key = self.peek().clone(); while key.tokentype != RightBrace { self.advance(); self.consume(Colon, "Expected ':'")?; let value = self.advance().clone(); - elements.insert(key.lexeme.to_owned(), value.lexeme); + elements.insert(key.lexeme.to_owned(), strip_surrounding(value.lexeme)); key = self.peek().clone(); } Ok(elements) @@ -241,24 +250,34 @@ impl Parser { } } +fn strip_surrounding(s: String) -> String { + s[1..s.len() - 1].to_owned() +} + #[cfg(test)] mod tests { use crate::NodeType::Node; #[test] fn test_parse() { - let contents = r#"structure { + let vis_source = r#" + structure { top: "top-node" { child: "child-node" { } } - }"#; - let vis = crate::parse::parser::parse_vis(contents).ok(); + } + styles { + top(group) { + orientation: "vertical"; + } + } + "#; + let vis = crate::parse::parser::parse_vis(vis_source).ok(); assert!(vis.is_some(), "Parsed structure should not be None"); if let Some(vis) = vis { - // Validate the parsed structure by asserting its elements assert_eq!( vis.structure.children.len(), 1, @@ -266,15 +285,15 @@ mod tests { ); if vis.structure.children[0].node_type == Node { - let node = &vis.structure.children[0]; - assert_eq!(node.id, "top", "The ID of the first node should be 'top'"); + let top = &vis.structure.children[0]; + assert_eq!(top.id, "top", "The ID of the first node should be 'top'"); assert_eq!( - node.label.as_ref().unwrap(), + top.label.as_ref().unwrap(), &"top-node".to_owned(), "The title of the first node should be 'top-node'" ); - assert_eq!(node.children.len(), 1); - let child = &node.children[0]; + assert_eq!(top.children.len(), 1); + let child = &top.children[0]; if child.node_type == Node { assert_eq!( child.id, "child", @@ -290,6 +309,10 @@ mod tests { } else { panic!("The top-level element should be a Node"); } + assert_eq!(vis.styles.len(), 1); + let styles = vis.get_styles("top"); + assert_eq!(styles.len(), 1); + assert_eq!(styles["orientation"], "vertical"); } else { panic!("Parsed structure was unexpectedly None"); }