From 21d84d46b55bd7df1153570969aebe9d11c64cd0 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Tue, 31 May 2022 10:05:29 -0400 Subject: [PATCH 1/2] now parsing date with nom --- Cargo.toml | 4 ++ src/main.rs | 172 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 146 insertions(+), 30 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 494728b..321546a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,7 @@ edition = "2021" [dependencies] num = "0.4" clap = { version = "3.1.8", features = ["derive"] } +chrono = "0.4" +nom = "7.1.1" +genawaiter = "0.99.1" +nom-bufreader = "0.2.0" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 5423c94..8711738 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,8 +2,25 @@ use std::io::prelude::*; use std::io; use std::fs::File; +use genawaiter::{sync::gen, yield_}; use num::*; use clap::Parser; +use chrono::prelude::*; +use std::collections::BTreeMap; + +use nom_bufreader::bufreader::BufReader; +use nom_bufreader::{Error, Parse}; +use nom::{ + branch::alt, + bytes::streaming::{tag, take_until, take_while1}, + character::streaming::{space0,alpha1, multispace1, digit1}, + combinator::map_res, + IResult, + sequence::tuple +}; + +// TODO : Remove +use std::str::from_utf8; #[derive(Parser)] struct Cli { @@ -17,44 +34,139 @@ struct Timestamp{ timestamp: BigInt } +// TODO: implement any timescales greater than a second +#[derive(Debug)] +enum Timescale {ps, ns, us, ms, s, unit} + +#[derive(Debug)] +struct Scope_Idx(usize); + +#[derive(Debug)] +struct Signal_Idx(usize); + +#[derive(Debug)] +struct Version(String); + +#[derive(Debug)] +struct Metadata { + date : Option>, + version : Option, + timescale : (Option, Timescale)} + +#[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} + +fn method(i: &[u8]) -> IResult<&[u8], String, ()> { + map_res(alt((tag("GET"), tag("POST"), tag("HEAD"))), |s| { + from_utf8(s).map(|s| s.to_string()) + })(i) +} + +fn path(i: &[u8]) -> IResult<&[u8], String, ()> { + map_res(take_until(" "), |s| from_utf8(s).map(|s| s.to_string()))(i) +} + +fn date(i: &[u8]) -> IResult<&[u8], DateTime, ()> { + let (i, _) = tag("$date")(i)?; + + let (i, _) = multispace1(i)?; + let (i, weekday) = alt(( + tag("Mon"), tag("Tue"), tag("Wed"), tag("Thu"), + tag("Fri"), tag("Sat"), tag("Sun")))(i)?; + + let (i, _) = multispace1(i)?; + let (i, month) = alt(( + tag("Jan"), tag("Feb"), tag("Mar"), tag("Apr"), + tag("May"), tag("Jun"), tag("July"), tag("Sept"), + tag("Oct"), tag("Nov"), tag("Dec")))(i)?; + + let (i, _) = multispace1(i)?; + let (i, day) = digit1(i)?; + + let (i, _) = multispace1(i)?; + let (i, hour) = digit1(i)?; + + let (i, _) = tag(":")(i)?; + let (i, minute) = digit1(i)?; + + let (i, _) = tag(":")(i)?; + let (i, second) = digit1(i)?; + + let (i, _) = multispace1(i)?; + let (i, year) = digit1(i)?; + + let (i, _) = multispace1(i)?; + let (i, _) = tag("$end")(i)?; + + let (weekday, month, day, hour, minute, second, year) = ( + from_utf8(weekday).unwrap(), + from_utf8(month).unwrap(), + from_utf8(day).unwrap(), + from_utf8(hour).unwrap(), + from_utf8(minute).unwrap(), + from_utf8(second).unwrap(), + from_utf8(year).unwrap(), + ); + + let dt = Utc.datetime_from_str( + format!("{weekday} {month} {day} {hour}:{minute}:{second} {year}") + .as_str(), "%a %b %e %T %Y") + .unwrap(); + + Ok((i, dt)) + +} + +fn space(i: &[u8]) -> IResult<&[u8], (), ()> { + let (i, _) = space0(i)?; + Ok((i, ())) +} + fn main() -> std::io::Result<()> { let args = Cli::parse(); let file = File::open(&args.path)?; - let mut reader = io::BufReader::new(file); + let mut reader = BufReader::new(file); + let m = reader.parse(date).expect("failed to parse date"); + dbg!(m.to_rfc2822()); - let mut buffer = String::new(); - let mut timestamp_offsets = Vec::new(); - let mut timestamps = Vec::new(); + // let mut file_by_line = gen!({ + // while { + // let bytes_read = reader.read_line(&mut buffer).unwrap(); + // bytes_read > 0 + // } { + // yield_!(buffer.as_bytes()); + // buffer.clear() + // } + // }); - while { - let bytes_read = reader.read_line(&mut buffer).unwrap(); - bytes_read > 0 - } { - if &buffer[0..1] == "#" { - let pos = reader.stream_position().unwrap(); - timestamp_offsets.push(pos); + // for line in file_by_line { + // dbg!(&line); + // } - let timestamp = { - let len = buffer.len(); - let str_val = &buffer[1..(len - 1)].as_bytes(); - BigInt::parse_bytes(str_val, 10).unwrap() - }; - timestamps.push(timestamp); - } - buffer.clear() - } - let index = 4; - let timestamp_offset = timestamp_offsets.get(index).unwrap(); - let timestamp = timestamps.get(index).unwrap(); - dbg!((timestamp_offset, timestamp)); - - // seek to where we found the first timestamp and read - // out the next line - reader.seek(io::SeekFrom::Start(*timestamp_offset)); - reader.read_line(&mut buffer); - dbg!(buffer); Ok(()) } From 4478d023792c52edf943851b671a4b0c35a74d88 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Tue, 31 May 2022 17:50:46 -0400 Subject: [PATCH 2/2] now parsing timelines with nom --- Cargo.toml | 1 - src/main.rs | 124 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 88 insertions(+), 37 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 321546a..ee63622 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,5 +10,4 @@ num = "0.4" clap = { version = "3.1.8", features = ["derive"] } chrono = "0.4" nom = "7.1.1" -genawaiter = "0.99.1" nom-bufreader = "0.2.0" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 8711738..f6d5982 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,6 @@ use std::io::prelude::*; use std::io; use std::fs::File; -use genawaiter::{sync::gen, yield_}; use num::*; use clap::Parser; use chrono::prelude::*; @@ -13,10 +12,15 @@ use nom_bufreader::{Error, Parse}; use nom::{ branch::alt, bytes::streaming::{tag, take_until, take_while1}, - character::streaming::{space0,alpha1, multispace1, digit1}, + character::is_alphanumeric, + character::complete::none_of, + character::streaming::{ + space0, alpha1, multispace0, + multispace1, digit1, line_ending, + alphanumeric1}, combinator::map_res, IResult, - sequence::tuple + sequence::{tuple, delimited, terminated, preceded} }; // TODO : Remove @@ -29,11 +33,6 @@ struct Cli { path: std::path::PathBuf, } -struct Timestamp{ - file_offset: u64, - timestamp: BigInt -} - // TODO: implement any timescales greater than a second #[derive(Debug)] enum Timescale {ps, ns, us, ms, s, unit} @@ -78,16 +77,6 @@ struct VCD { // the root scope should always be placed at index 0 all_scopes : Vec} -fn method(i: &[u8]) -> IResult<&[u8], String, ()> { - map_res(alt((tag("GET"), tag("POST"), tag("HEAD"))), |s| { - from_utf8(s).map(|s| s.to_string()) - })(i) -} - -fn path(i: &[u8]) -> IResult<&[u8], String, ()> { - map_res(take_until(" "), |s| from_utf8(s).map(|s| s.to_string()))(i) -} - fn date(i: &[u8]) -> IResult<&[u8], DateTime, ()> { let (i, _) = tag("$date")(i)?; @@ -139,34 +128,97 @@ fn date(i: &[u8]) -> IResult<&[u8], DateTime, ()> { } -fn space(i: &[u8]) -> IResult<&[u8], (), ()> { - let (i, _) = space0(i)?; +fn version(i: &[u8]) -> IResult<&[u8], String, ()> { + let (i, _) = tag("$version")(i)?; + let (mut i, _) = multispace1(i)?; + + let mut version = "".to_string(); + let mut reached_end = false; + + while (reached_end == false) { + let (_i, next_word) = take_while1( + |c| + c != 36 && // not $ + c >= 33 && // between ! and ~ + c <= 126 + )(i)?; + i = _i; + let next_word = from_utf8(next_word).unwrap(); + + version = format!("{version} {next_word}"); + let (_i, _) = multispace1(i)?; + i = _i; + + match tag::<&str, &[u8], ()>("$end")(i) { + Ok((_i, _)) => { + i = _i; + reached_end = true; + } + Err(_) => {} + }; + + } + + // strip the initial space + version = version[1..].to_string(); + + Ok((i, version)) + +} + +fn timescale(i: &[u8]) -> IResult<&[u8], (Option, Timescale), ()> { + let (i, _) = tag("$timescale")(i)?; + dbg!("here"); + let (i, _) = multispace1(i)?; + + let (i, scale) = digit1(i)?; + let (i, _) = multispace1(i)?; + + let (i, unit) = alpha1(i)?; + let (i, _) = multispace1(i)?; + + let (i, _) = tag("$end")(i)?; + + let scale = from_utf8(scale).unwrap().to_string(); + let scale = scale.parse::().unwrap(); + + let unit = match from_utf8(unit).unwrap() { + "ps" => Ok(Timescale::ps), + "ns" => Ok(Timescale::ns), + "us" => Ok(Timescale::us), + "ms" => Ok(Timescale::ms), + "s" => Ok(Timescale::s), + _ => Err(()) + }.unwrap(); + + + Ok((i, (Some(scale), unit))) + +} + +fn f_multispace0(i: &[u8]) -> IResult<&[u8], (), ()> { + let (i, _) = multispace0(i)?; Ok((i, ())) } -fn main() -> std::io::Result<()> { +fn main() -> Result<(), Error<()>> { let args = Cli::parse(); let file = File::open(&args.path)?; let mut reader = BufReader::new(file); - let m = reader.parse(date).expect("failed to parse date"); - dbg!(m.to_rfc2822()); - // let mut file_by_line = gen!({ - // while { - // let bytes_read = reader.read_line(&mut buffer).unwrap(); - // bytes_read > 0 - // } { - // yield_!(buffer.as_bytes()); - // buffer.clear() - // } - // }); + reader.parse(f_multispace0).unwrap(); + let date = reader.parse(date).expect("failed to parse date"); - // for line in file_by_line { - // dbg!(&line); - // } + reader.parse(f_multispace0).unwrap(); + let version = reader.parse(version).expect("failed to parse version"); + reader.parse(f_multispace0).unwrap(); + let timescale = reader.parse(timescale).expect("failed to parse timescale"); + dbg!(date.to_rfc2822()); + dbg!(version); + dbg!(timescale); Ok(()) -} +} \ No newline at end of file