restructuring and WIP

This commit is contained in:
Yehowshua Immanuel 2022-06-03 21:06:46 -04:00
parent c65bdfefac
commit 1c006441fb
5 changed files with 270 additions and 71 deletions

View file

@ -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<DateTime<Utc>>,
version : Option<Version>,
timescale : (Option<u32>, Timescale)}
#[derive(Debug)]
struct Scope_Idx(usize);
#[derive(Debug)]
struct Signal_Idx(usize);
#[derive(Debug)]
enum SignalGeneric{
Signal{
name : String,
timeline : BTreeMap<BigInt, BigInt>,
scope_parent : Scope_Idx},
SignalAlias{
name : String,
signal_alias : Signal_Idx}
}
#[derive(Debug)]
struct Scope {
name : String,
child_signals : Vec<Signal_Idx>,
child_scopes : Vec<Scope_Idx>}
#[derive(Debug)]
struct VCD {
metadata : Metadata,
all_signals : Vec<SignalGeneric>,
// the root scope should always be placed at index 0
all_scopes : Vec<Scope>}
impl VCD {
pub fn new() -> Self {
let metadata = Metadata {
date : None,
version : None,
timescale : (None, Timescale::unit)};
VCD {
metadata : metadata,
all_signals : Vec::<SignalGeneric>::new(),
all_scopes : Vec::<Scope>::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();

View file

@ -1,2 +1,8 @@
mod reader;
pub use reader::*;
mod types;
pub use types::*;
mod parse;
pub use parse::*;

188
src/vcd/parse.rs Normal file
View file

@ -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);
}

View file

@ -1,5 +1,3 @@
use super::*;
use std::fs::File;
use std::collections::VecDeque;
use std::slice;

59
src/vcd/types.rs Normal file
View file

@ -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<DateTime<Utc>>,
version : Option<Version>,
timescale : (Option<u32>, Timescale)}
#[derive(Debug)]
struct Scope_Idx(usize);
#[derive(Debug)]
struct Signal_Idx(usize);
#[derive(Debug)]
enum SignalGeneric{
Signal{
name : String,
timeline : BTreeMap<BigInt, BigInt>,
scope_parent : Scope_Idx},
SignalAlias{
name : String,
signal_alias : Signal_Idx}
}
#[derive(Debug)]
struct Scope {
name : String,
child_signals : Vec<Signal_Idx>,
child_scopes : Vec<Scope_Idx>}
#[derive(Debug)]
struct VCD {
metadata : Metadata,
all_signals : Vec<SignalGeneric>,
// the root scope should always be placed at index 0
all_scopes : Vec<Scope>}
impl VCD {
pub fn new() -> Self {
let metadata = Metadata {
date : None,
version : None,
timescale : (None, Timescale::unit)};
VCD {
metadata : metadata,
all_signals : Vec::<SignalGeneric>::new(),
all_scopes : Vec::<Scope>::new()}
}
}