From 1c006441fb14a9a03db61f1b11acd84a4c5577a0 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Fri, 3 Jun 2022 21:06:46 -0400 Subject: [PATCH] restructuring and WIP --- src/main.rs | 84 ++++----------------- src/vcd.rs | 8 +- src/vcd/parse.rs | 188 ++++++++++++++++++++++++++++++++++++++++++++++ src/vcd/reader.rs | 2 - src/vcd/types.rs | 59 +++++++++++++++ 5 files changed, 270 insertions(+), 71 deletions(-) create mode 100644 src/vcd/parse.rs create mode 100644 src/vcd/types.rs diff --git a/src/main.rs b/src/main.rs index 6b37eff..b98e7eb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,4 @@ use std::fs::File; -use std::collections::BTreeMap; -use chrono::prelude::*; -use ::function_name::named; - -use num::*; use clap::Parser; pub mod vcd; @@ -15,74 +10,27 @@ struct Cli { #[clap(parse(from_os_str))] path: std::path::PathBuf} -#[derive(Debug)] -struct Version(String); - -#[derive(Debug)] -enum Timescale {ps, ns, us, ms, s, unit} - -#[derive(Debug)] -struct Metadata { - date : Option>, - version : Option, - timescale : (Option, Timescale)} - -#[derive(Debug)] -struct Scope_Idx(usize); - -#[derive(Debug)] -struct Signal_Idx(usize); - -#[derive(Debug)] -enum SignalGeneric{ - Signal{ - name : String, - timeline : BTreeMap, - scope_parent : Scope_Idx}, - SignalAlias{ - name : String, - signal_alias : Signal_Idx} -} - -#[derive(Debug)] -struct Scope { - name : String, - child_signals : Vec, - child_scopes : Vec} - - -#[derive(Debug)] -struct VCD { - metadata : Metadata, - all_signals : Vec, - // the root scope should always be placed at index 0 - all_scopes : Vec} - -impl VCD { - pub fn new() -> Self { - let metadata = Metadata { - date : None, - version : None, - timescale : (None, Timescale::unit)}; - VCD { - metadata : metadata, - all_signals : Vec::::new(), - all_scopes : Vec::::new()} - } - } - - fn main() -> std::io::Result<()> { let args = Cli::parse(); let file = File::open(&args.path)?; - let mut word_gen = WordReader::new(file); - let mut word_count = 0; + dbg!(["hello", "goodbye", "myworld"].contains(&"myworlde")); + // let mut word_gen = WordReader::new(file); + // let mut word_count = 0; + + // while word_gen.next_word().is_some() { + // word_count += 1; + // } + // dbg!(word_count); + + // let word1 = "hello world"; + // let word2 = "hello planet"; + // dbg!(&word1[0..6].len()); + dbg!(take_until("tea time now: and later", b':')); + // parse_vcd(file); + + // tag("my oh my"); - while word_gen.next_word().is_some() { - word_count += 1; - } - dbg!(word_count); // loop { // let word = word_gen.next_word(); diff --git a/src/vcd.rs b/src/vcd.rs index 50db179..19f1a6c 100644 --- a/src/vcd.rs +++ b/src/vcd.rs @@ -1,2 +1,8 @@ mod reader; -pub use reader::*; \ No newline at end of file +pub use reader::*; + +mod types; +pub use types::*; + +mod parse; +pub use parse::*; \ No newline at end of file diff --git a/src/vcd/parse.rs b/src/vcd/parse.rs new file mode 100644 index 0000000..9771b07 --- /dev/null +++ b/src/vcd/parse.rs @@ -0,0 +1,188 @@ +use super::*; +use std::fs::File; +use ::function_name::named; + +#[derive(Debug)] +pub struct Residual<'a>(&'a str); + +pub fn take_until<'a>(word : &'a str, pattern : u8) -> Option<(&'a str, Residual)> { + let mut new_start = 0; + + for chr in word.as_bytes() { + if (*chr == pattern) { + return Some((&word[0..new_start], Residual(&word[new_start..]))); + } + else { + new_start += 1; + } + } + + None +} + +fn tag<'a>(word : &'a str, pattern : &'a str) -> Option<&'a str> { + let lhs = word.as_bytes().iter(); + let rhs = pattern.as_bytes(); + let iter = lhs.zip(rhs); + let mut new_start = 0; + + let mut res = true; + for (c_lhs, c_rhs) in iter { + res = res && (c_lhs == c_rhs); + if !res {return None} + new_start += 1; + } + + Some(&word[new_start..]) +} + +#[named] +fn parse_date(word_reader : &mut WordReader) -> Result<(), String> { + let mut parsed_day = false; + let mut parsed_month = false; + let mut parsed_date = false; + let mut parsed_hh = false; + let mut parsed_mm = false; + let mut parsed_ss = false; + let mut parsed_year = false; + let mut parsed_end = false; + + let day = { + // check for another word in the file + let (word, cursor) = word_reader.next_word().expect( + format!("reached end of file without parser leaving {}", function_name!()).as_str() + ); + + let days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; + if !days.contains(&word) { + let msg = format!("reached end of file without parser leaving {}\n", function_name!()); + let msg2 = format!("{word} is not a valid weekday : expected one of {days:?}\n"); + let msg3 = format!("failure location: {cursor:?}"); + return Err(format!("{}{}{}", msg, msg2, msg3)) + } + + word.to_string() + }; + + let month = { + // check for another word in the file + let (word, cursor) = word_reader.next_word().expect( + format!("reached end of file without parser leaving {}", function_name!()).as_str() + ); + + let months = [ + "Jan", "Feb", "Mar", "Apr", + "May", "Jun", "Jul", "Aug", + "Sept", "Oct", "Nov", "Dec", + ]; + + if !months.contains(&word) { + let msg = format!("reached end of file without parser leaving {}\n", function_name!()); + let msg2 = format!("{word} is not a valid month : expected one of {months:?}\n"); + let msg3 = format!("failure location: {cursor:?}"); + return Err(format!("{}{}{}", msg, msg2, msg3)) + } + + word.to_string() + }; + + let date = { + // check for another word in the file + let (word, cursor) = word_reader.next_word().expect( + format!("reached end of file without parser leaving {}", function_name!()).as_str() + ); + + let date : u8 = word.to_string().parse().unwrap(); + + if date > 31 { + let msg = format!("reached end of file without parser leaving {}\n", function_name!()); + let msg2 = format!("{word} is not a valid date : must be between 0 and 31\n"); + let msg3 = format!("failure location: {cursor:?}"); + return Err(format!("{}{}{}", msg, msg2, msg3)) + + } + + word.to_string() + }; + + let (hh, mm, ss) = { + // check for another word in the file + let (word, cursor) = word_reader.next_word().expect( + format!("reached end of file without parser leaving {}", function_name!()).as_str() + ); + + let date : u8 = word.to_string().parse().unwrap(); + // let hh = take_until(word, b':').unwrap(); + + if date > 31 { + let msg = format!("reached end of file without parser leaving {}\n", function_name!()); + let msg2 = format!("{word} is not a valid date : must be between 0 and 31\n"); + let msg3 = format!("failure location: {cursor:?}"); + return Err(format!("{}{}{}", msg, msg2, msg3)) + + } + ("", "", "") + }; + + // else if !parsed_date { + + // } + // else if !parsed_hh { + + // } + // else if !parsed_mm { + + // } + // else if !parsed_ss { + + // } + // else if !parsed_year { + + // } + // else if !parsed_end { + + // } + + Ok(()) +} + +#[named] +fn parse_header(word_reader : &mut WordReader) -> Result<(), String> { + loop { + // check for another word in the file + let word = word_reader.next_word(); + + // if there isn't another word left in the file, then we exit + if word.is_none() { + return Err(format!("reached end of file without parser leaving {}", function_name!())) + } + + // destructure + let (word, cursor) = word.unwrap(); + let ident = tag(word, "$"); + + match tag(word, "$") { + // we hope that this word stars with a `$` + Some(ident) => { + match ident { + "date" => {println!("got date")} + "version" => {println!("got version")} + "timescale" => {println!("got timescale")} + "scope" => {return Ok(())} + _ => {} + } + } + // if not, then we keep looping + None => {} + } + + + } + // Ok() +} + +pub fn parse_vcd(file : File) { + let mut word_gen = WordReader::new(file); + + parse_header(&mut word_gen); +} \ No newline at end of file diff --git a/src/vcd/reader.rs b/src/vcd/reader.rs index f6fc275..b9c85e4 100644 --- a/src/vcd/reader.rs +++ b/src/vcd/reader.rs @@ -1,5 +1,3 @@ -use super::*; - use std::fs::File; use std::collections::VecDeque; use std::slice; diff --git a/src/vcd/types.rs b/src/vcd/types.rs new file mode 100644 index 0000000..336601a --- /dev/null +++ b/src/vcd/types.rs @@ -0,0 +1,59 @@ +use std::collections::BTreeMap; +use chrono::prelude::*; +use num::BigInt; + +#[derive(Debug)] +struct Version(String); + +#[derive(Debug)] +enum Timescale {ps, ns, us, ms, s, unit} + +#[derive(Debug)] +pub(super) struct Metadata { + date : Option>, + version : Option, + timescale : (Option, Timescale)} + +#[derive(Debug)] +struct Scope_Idx(usize); + +#[derive(Debug)] +struct Signal_Idx(usize); + +#[derive(Debug)] +enum SignalGeneric{ + Signal{ + name : String, + timeline : BTreeMap, + scope_parent : Scope_Idx}, + SignalAlias{ + name : String, + signal_alias : Signal_Idx} +} + +#[derive(Debug)] +struct Scope { + name : String, + child_signals : Vec, + child_scopes : Vec} + + +#[derive(Debug)] +struct VCD { + metadata : Metadata, + all_signals : Vec, + // the root scope should always be placed at index 0 + all_scopes : Vec} + +impl VCD { + pub fn new() -> Self { + let metadata = Metadata { + date : None, + version : None, + timescale : (None, Timescale::unit)}; + VCD { + metadata : metadata, + all_signals : Vec::::new(), + all_scopes : Vec::::new()} + } + }