From 8051e1d330a59a303af5ccaf24e6880e5672a851 Mon Sep 17 00:00:00 2001 From: fizy069 Date: Fri, 24 Jan 2025 22:25:29 +0530 Subject: [PATCH 1/4] Indented printing for nested constructors --- src/data.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/data.rs b/src/data.rs index fc1ad38..6e5509c 100644 --- a/src/data.rs +++ b/src/data.rs @@ -131,6 +131,7 @@ pub struct ProgLoc { line: String, char_range: (usize, usize), desc: Option, + depth : usize, } impl ProgLoc { @@ -143,9 +144,11 @@ impl ProgLoc { return false; } - let line_text = &loc.line; + let depth_spaces = " ".repeat(loc.depth * 2); + let line_text = format!("{}{}", depth_spaces, loc.line); let max_padding = 7; let mut itr_space = 0; + if format!("{itr}").len() == 1 { itr_space = format!("[{}] |", itr).len().min(max_padding); } else { @@ -167,10 +170,12 @@ impl ProgLoc { line_text ); } + let start = loc.char_range.0 + (loc.depth*2); + let end = loc.char_range.1 + (loc.depth*2); let mut highlight = String::with_capacity(line_text.len()); for i in 1..(line_text.len() + 1) { - if i >= loc.char_range.0 && i < loc.char_range.1 { + if i >= start && i < end { highlight.push('^'); } else { highlight.push(' '); From 9f5ceb2d69cd539663c39ca858f517592a421f39 Mon Sep 17 00:00:00 2001 From: fizy069 Date: Sat, 25 Jan 2025 09:07:58 +0530 Subject: [PATCH 2/4] Bracketed filter for queries --- src/data.rs | 107 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 93 insertions(+), 14 deletions(-) diff --git a/src/data.rs b/src/data.rs index 6e5509c..a4f0c6d 100644 --- a/src/data.rs +++ b/src/data.rs @@ -11,6 +11,13 @@ pub struct Database { type_vars: BTreeSet, } +#[derive(Debug)] +pub struct MatchResult<'a> { + pub success: bool, + pub flows: Vec<&'a UnitFlow>, + pub collecting: bool +} + impl Database { pub fn load_from_json(path: &str) -> Self { #[derive(Deserialize)] @@ -66,7 +73,15 @@ impl Database { } pub fn match_flow(&self, flow: &[UnitFlow], query: &[QueryOps]) -> bool { - match (flow, query) { + println!("original query - {:?}", query); + let filtered_query: Vec<_> = query + .iter() + .filter(|op| !matches!(op, QueryOps::BracketOpen | QueryOps::BracketClose)) + .cloned() + .collect(); + + println!("filtered query - {:?}", filtered_query); + match (flow, &filtered_query[..]) { // Wildcard matches all remaining flows (_, [QueryOps::Wildcard]) => true, (f, [QueryOps::Wildcard, next_query, rest @ ..]) => { @@ -108,6 +123,38 @@ impl Database { }) .count() } + + pub fn match_flow_with_collection<'a>(flow: &'a [UnitFlow], query: &[QueryOps]) -> Vec<&'a UnitFlow> { + let mut matched_flows = Vec::new(); + let has_brackets = query.iter().any(|op| matches!(op, QueryOps::BracketOpen | QueryOps::BracketClose)); + let mut collecting = !has_brackets; + println!("collecting - {:?}", collecting); + let mut bracket_depth = 0; + + for (i, op) in query.iter().enumerate() { + match op { + QueryOps::BracketOpen => { + bracket_depth += 1; + if bracket_depth == 1 { + collecting = true; + } + }, + QueryOps::BracketClose => { + bracket_depth -= 1; + if bracket_depth == 0 { + collecting = false; + } + }, + _ => { + if collecting && i < flow.len() { + matched_flows.push(&flow[i]); + } + } + } + } + println!("matched flows - {:?}", matched_flows); + matched_flows + } } type DataFlow = Vec; @@ -119,14 +166,14 @@ pub struct Type { desc: Option, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct ConstructorArg { name: String, arg_index: usize, desc: Option, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct ProgLoc { line: String, char_range: (usize, usize), @@ -189,13 +236,13 @@ impl ProgLoc { } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub struct TypeVar { name: String, desc: Option, } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] pub enum UnitFlow { Type(Type), ConstructorArg(ConstructorArg), @@ -203,7 +250,7 @@ pub enum UnitFlow { ProgLoc(ProgLoc), } -#[derive(serde::Deserialize, Debug, PartialEq, Eq)] +#[derive(serde::Deserialize, Debug, PartialEq, Eq, Clone)] /// Match constructor argument in the data flow by name pub struct QConstructorArg { pub name: String, @@ -213,7 +260,7 @@ pub struct QConstructorArg { pub desc: Option, } -#[derive(serde::Deserialize, Debug, PartialEq, Eq)] +#[derive(serde::Deserialize, Debug, PartialEq, Eq, Clone)] /// Match type by name pub struct QType { pub name: String, @@ -221,7 +268,7 @@ pub struct QType { pub desc: Option, } -#[derive(serde::Deserialize, Debug, PartialEq, Eq)] +#[derive(serde::Deserialize, Debug, PartialEq, Eq, Clone)] pub enum QueryOps { /// Match type variable by in-degree QTypeVar(usize), @@ -233,6 +280,8 @@ pub enum QueryOps { QDesc(String), /// Match any unit flow Wildcard, + BracketOpen, + BracketClose, } /// A simplified parser for query language @@ -248,7 +297,8 @@ pub enum QueryOps { impl QueryOps { fn parse_token(token: &str) -> Result { match token.trim() { - "*" => Ok(QueryOps::Wildcard), + "(" => Ok(QueryOps::BracketOpen), + ")" => Ok(QueryOps::BracketClose), // Handle type variable count: #2 s if s.starts_with('#') => s[1..] @@ -305,12 +355,41 @@ impl QueryOps { } pub fn parse_query(input: &str) -> Result, String> { - input - .split(',') - .map(str::trim) + let mut tokens = Vec::new(); + let mut current = String::new(); + + for c in input.chars() { + match c { + ',' => { + if !current.is_empty() { + tokens.push(current.trim().to_string()); + current.clear(); + } + } + '(' | ')' => { + if !current.is_empty() { + tokens.push(current.trim().to_string()); + current.clear(); + } + tokens.push(c.to_string()); + } + _ => current.push(c) + } + } + + if !current.is_empty() { + tokens.push(current.trim().to_string()); + } + + // Then parse each token + let x = tokens + .into_iter() .filter(|s| !s.is_empty()) - .map(Self::parse_token) - .collect() + .map(|s| Self::parse_token(&s)) + .collect(); + + println!("query - {:?}", x); + x } } From c5b5aeb891cef8178e013c3698966b4bd8f9bb14 Mon Sep 17 00:00:00 2001 From: fizy069 Date: Sat, 25 Jan 2025 11:32:39 +0530 Subject: [PATCH 3/4] bracket support --- src/data.rs | 74 ++++++++++++++++++++++++++++++----------------------- src/main.rs | 23 ++++++++++++++++- 2 files changed, 64 insertions(+), 33 deletions(-) diff --git a/src/data.rs b/src/data.rs index ce8dd5d..4c27422 100644 --- a/src/data.rs +++ b/src/data.rs @@ -13,9 +13,9 @@ pub struct Database { #[derive(Debug)] pub struct MatchResult<'a> { - pub success: bool, + pub success: bool, pub flows: Vec<&'a UnitFlow>, - pub collecting: bool + pub collecting: bool, } impl Database { @@ -74,14 +74,12 @@ impl Database { } pub fn match_flow(&self, flow: &[UnitFlow], query: &[QueryOps]) -> bool { - println!("original query - {:?}", query); let filtered_query: Vec<_> = query - .iter() - .filter(|op| !matches!(op, QueryOps::BracketOpen | QueryOps::BracketClose)) - .cloned() - .collect(); + .iter() + .filter(|op| !matches!(op, QueryOps::BracketOpen | QueryOps::BracketClose)) + .cloned() + .collect(); - println!("filtered query - {:?}", filtered_query); match (flow, &filtered_query[..]) { (f, [next_query, rest @ ..]) => { // Try each position until we find a match for the next query item @@ -116,36 +114,46 @@ impl Database { .count() } - pub fn match_flow_with_collection<'a>(flow: &'a [UnitFlow], query: &[QueryOps]) -> Vec<&'a UnitFlow> { + pub fn match_flow_collect<'a>( + &self, + flow: &'a [UnitFlow], + filtered_query: &[QueryOps], + ) -> (bool, Vec<&'a UnitFlow>) { + if !self.match_flow(flow, filtered_query) { + return (false, Vec::new()); + } + let mut matched_flows = Vec::new(); - let has_brackets = query.iter().any(|op| matches!(op, QueryOps::BracketOpen | QueryOps::BracketClose)); - let mut collecting = !has_brackets; - println!("collecting - {:?}", collecting); + let mut collecting = false; let mut bracket_depth = 0; - - for (i, op) in query.iter().enumerate() { - match op { + let mut current_pos = 0; + + for query_op in filtered_query { + match query_op { QueryOps::BracketOpen => { bracket_depth += 1; if bracket_depth == 1 { collecting = true; } - }, + } QueryOps::BracketClose => { bracket_depth -= 1; if bracket_depth == 0 { - collecting = false; + collecting = false; } - }, + } _ => { - if collecting && i < flow.len() { - matched_flows.push(&flow[i]); + while current_pos < flow.len() { + if collecting { + matched_flows.push(&flow[current_pos]); + } + current_pos += 1; + break; } } } } - println!("matched flows - {:?}", matched_flows); - matched_flows + (true, matched_flows) } } type DataFlow = Vec; @@ -170,7 +178,7 @@ pub struct ProgLoc { line: String, char_range: (usize, usize), desc: Option, - depth : usize, + depth: usize, } impl ProgLoc { @@ -209,8 +217,8 @@ impl ProgLoc { line_text ); } - let start = loc.char_range.0 + (loc.depth*2); - let end = loc.char_range.1 + (loc.depth*2); + let start = loc.char_range.0 + (loc.depth * 2); + let end = loc.char_range.1 + (loc.depth * 2); let mut highlight = String::with_capacity(line_text.len()); for i in 1..(line_text.len() + 1) { @@ -275,7 +283,6 @@ pub enum QueryOps { /// Match based on string description for a [UnitFlow] QDesc(String), /// Match any unit flow - Wildcard, BracketOpen, BracketClose, } @@ -290,6 +297,12 @@ pub enum QueryOps { /// @x:desc -> QConstructorArg(x) with description /// "desc" -> QDesc(desc) impl QueryOps { + pub fn has_brackets(query: &[QueryOps]) -> bool { + query + .iter() + .any(|op| matches!(op, QueryOps::BracketOpen | QueryOps::BracketClose)) + } + fn parse_token(token: &str) -> Result { match token.trim() { "(" => Ok(QueryOps::BracketOpen), @@ -352,7 +365,7 @@ impl QueryOps { pub fn parse_query(input: &str) -> Result, String> { let mut tokens = Vec::new(); let mut current = String::new(); - + for c in input.chars() { match c { ',' => { @@ -368,22 +381,19 @@ impl QueryOps { } tokens.push(c.to_string()); } - _ => current.push(c) + _ => current.push(c), } } - + if !current.is_empty() { tokens.push(current.trim().to_string()); } - // Then parse each token let x = tokens .into_iter() .filter(|s| !s.is_empty()) .map(|s| Self::parse_token(&s)) .collect(); - - println!("query - {:?}", x); x } } diff --git a/src/main.rs b/src/main.rs index e57c107..9c509a5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,11 @@ fn main() { let db = Database::load_from_json(&config.data_json); let query = config.query; - let results = search_dataflows(&db, &query); + let results = if QueryOps::has_brackets(&query) { + search_and_collect_dataflows(&db, &query) + } else { + search_dataflows(&db, &query) + }; println!("\n{}", "━".repeat(80).bright_black()); if results.is_empty() { println!("{}", "No data flows matched the query.\n".bright_red()); @@ -29,6 +33,23 @@ fn search_dataflows<'a>(db: &'a Database, query: &'a [QueryOps]) -> Vec<&'a Vec< .collect() } +fn search_and_collect_dataflows<'a>( + db: &'a Database, + query: &'a [QueryOps], +) -> Vec<&'a Vec> { + db.data_flows + .iter() + .filter_map(|flow| { + let (matched, collected) = db.match_flow_collect(flow, query); + if matched && !collected.is_empty() { + Some(flow) + } else { + None + } + }) + .collect() +} + fn print_results(results: &[&Vec]) { for (flow_idx, flow) in results.iter().enumerate() { let prog_locs: Vec<_> = flow From 42f15d7fc7d7bed00ac94d94a51df888aa29c7f9 Mon Sep 17 00:00:00 2001 From: fizy069 Date: Sat, 25 Jan 2025 12:00:27 +0530 Subject: [PATCH 4/4] Cleanup --- src/data.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/data.rs b/src/data.rs index 4c27422..a830c7f 100644 --- a/src/data.rs +++ b/src/data.rs @@ -11,13 +11,6 @@ pub struct Database { type_vars: BTreeSet, } -#[derive(Debug)] -pub struct MatchResult<'a> { - pub success: bool, - pub flows: Vec<&'a UnitFlow>, - pub collecting: bool, -} - impl Database { pub fn load_from_json(path: &str) -> Self { #[derive(Deserialize)]