New parser #2
84
src/main.rs
84
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<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();
|
||||
|
|
|
@ -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
188
src/vcd/parse.rs
Normal 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);
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
use super::*;
|
||||
|
||||
use std::fs::File;
|
||||
use std::collections::VecDeque;
|
||||
use std::slice;
|
||||
|
|
59
src/vcd/types.rs
Normal file
59
src/vcd/types.rs
Normal 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()}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue