diff --git a/.mise.toml b/.mise.toml new file mode 100644 index 0000000..f433e3d --- /dev/null +++ b/.mise.toml @@ -0,0 +1,9 @@ +[tools] +rust = "stable" +jj = "latest" + +[tasks] +run = "cargo run" +test = "cargo test" +watch-run = "cargo watch -x run --why" +watch-test = "cargo watch -x test --why" diff --git a/formats/c37118.brin b/formats/c37118.brin index c37d9a8..95a5b5a 100644 --- a/formats/c37118.brin +++ b/formats/c37118.brin @@ -1,11 +1,15 @@ -#= Bigendian +#= BigEndian CFGFRAME { 0-1 bytes: field "SYNC" { - 0 byte: const "magic_number" u8 0xAA - 1 byte: const "ver_number" u8 0x31 + 0 byte: const "sync" u8 0xAA + 1 byte: field "type_ver" {} } - 3-4 bytes: field "TIME BASE" u16 - 5-6 bytes: field "NUM_PMU" u16 + 2-3 bytes: field "framesize" u16 + 4-5 bytes: field "idcode" u16 + 6-7 bytes: field "soc" u16 + 8-9 bytes: field "fracsec" u16 + 10-11 bytes: field "time base" u16 } + diff --git a/src/grammar/mod.rs b/src/grammar/mod.rs index 79a292e..d1c03ab 100644 --- a/src/grammar/mod.rs +++ b/src/grammar/mod.rs @@ -1,4 +1,4 @@ -use crate::ir::{Atom, OwnedAtom}; +use crate::ir::OwnedAtom; pub(crate) mod parser; #[derive(PartialEq, Debug)] @@ -53,4 +53,4 @@ pub(crate) enum Type { } /// position of field relative to parent -type Range = (usize, usize); +pub type Range = (usize, usize); diff --git a/src/grammar/parser.rs b/src/grammar/parser.rs index a8a867a..8054f60 100644 --- a/src/grammar/parser.rs +++ b/src/grammar/parser.rs @@ -1,3 +1,5 @@ +use crate::ir::Atom; +use nom::character::complete::space0; use std::error::Error; use nom::IResult; @@ -14,8 +16,6 @@ use nom::character::complete::digit1; use nom::character::complete::hex_digit1; use nom::character::complete::line_ending; use nom::character::complete::multispace0; -use nom::character::complete::newline; -use nom::character::complete::space0; use nom::character::streaming::multispace1; use nom::combinator::map; use nom::combinator::map_res; @@ -31,8 +31,6 @@ use nom::sequence::pair; use nom::sequence::preceded; use nom::sequence::terminated; -use crate::ir::Atom; - use super::FieldRegion; use super::Module; use super::Options; @@ -117,7 +115,6 @@ fn identifier_test() { /// A combinator that parses primitive types. pub fn parse_type(input: &str) -> IResult<&str, Type> { - println!("type: {:?}", input); alt(( (map(tag("bool"), |_| Type::Bool)), (map(tag("u8"), |_| Type::U8)), @@ -196,7 +193,6 @@ fn range_test() { } pub fn parse_field_entry(input: &str) -> IResult<&str, (Range, FieldRegion)> { - println!("field_entry{:?}", input); map( ( parse_range, @@ -229,15 +225,14 @@ pub fn parse_field_entry(input: &str) -> IResult<&str, (Range, FieldRegion)> { } pub fn parse_region(input: &str) -> IResult<&str, Region> { - println!("Region: {:?}", input); alt(( map( ( multispace0, char('{'), - multispace1, + multispace0, separated_list0(multispace1, parse_field_entry), - multispace1, + multispace0, char('}'), ), |(_, _, _, field_list, _, _)| Region::Fields(field_list), @@ -386,7 +381,6 @@ fn parse_named_region(input: &str) -> IResult<&str, (String, Region)> { } pub fn parse_module(input: &str) -> IResult<&str, Module> { - println!("{}", input); map( ( parse_options, @@ -402,62 +396,22 @@ pub fn parse_module(input: &str) -> IResult<&str, Module> { fn module_test() { let module = "#= BigEndian\n\n\nCFGFRAME { 0-1 bytes: field \"SYNC\" u16 }"; let (_, module) = parse_module(module).unwrap(); - assert_eq!(module.opts, Options(vec!["BigEndian".to_owned()])); - assert_eq!(module.objs[0].0, "CFGFRAME"); -} - -#[test] -fn c37118_test() { - let brin = include_str!("../../formats/c37118.brin"); - let (_, module) = parse_module(brin).unwrap(); - assert_eq!(module.opts, Options(vec!["Bigendian".to_owned()])); - assert_eq!(module.objs[0].0, "CFGFRAME"); - - if let Region::Fields(fields) = &module.objs[0].1 { - assert_eq!(fields[0].0, (0, 15)); - if let FieldRegion::Subfield { name, content } = &fields[0].1 { - assert_eq!(name, "SYNC"); - if let Region::Fields(subfields) = content { - assert_eq!(subfields[0].0, (0, 7)); - if let FieldRegion::Const { name, value } = &subfields[0].1 { - assert_eq!(name, "magic_number"); - assert_eq!(*value, OwnedAtom::U8(0xAA)); - } - - assert_eq!(subfields[1].0, (8, 15)); - if let FieldRegion::Const { name, value } = &subfields[1].1 { - assert_eq!(name, "ver_number"); - assert_eq!(*value, OwnedAtom::U8(0x31)); - } - } + assert_eq!( + module, + Module { + objs: vec![( + "CFGFRAME".to_owned(), + Region::Fields(vec![( + (0, 15), + FieldRegion::Subfield { + name: "SYNC".to_owned(), + content: Region::Atom { ty: Type::U16 } + } + )]) + )], + opts: Options(vec!["BigEndian".to_owned()]) } - - assert_eq!(fields[1].0, (24, 39)); - if let FieldRegion::Subfield { name, content } = &fields[1].1 { - assert_eq!(*name, "TIME BASE"); - if let Region::Atom { ty } = content { - assert_eq!(*ty, Type::U16); - } else { - panic!("Incorrect content for TIME BASE"); - } - } else { - panic!("Incorrect field region for TIME BASE"); - } - - assert_eq!(fields[2].0, (40, 55)); - if let FieldRegion::Subfield { name, content } = &fields[2].1 { - assert_eq!(*name, "NUM_PMU"); - if let Region::Atom { ty } = content { - assert_eq!(*ty, Type::U16); - } else { - panic!("Incorrect content for NUM_PMU"); - } - } else { - panic!("Incorrect field region for NUM_PMU"); - } - } else { - panic!("Wrong region type"); - } + ); } #[test] @@ -476,7 +430,7 @@ fn test_field_entry() { } #[test] -fn test_region_good() { +fn test_region_god() { let region = "{ 3-4 byte: field \"time base\" u16 5-6 byte: field \"magic number\" { diff --git a/src/ir/mod.rs b/src/ir/mod.rs index d5f26ca..66d55f3 100644 --- a/src/ir/mod.rs +++ b/src/ir/mod.rs @@ -1,6 +1,8 @@ //use nanoid::nanoid; use std::borrow::Cow; +use crate::grammar::Range; + /* Any format will be parsed into an intermediate, json-like object. Where possible, zero-copying should be done (???!); @@ -77,3 +79,9 @@ impl<'a> Atom<'a> { } } } + +pub struct ParsedField<'a> { + span: Range, + name: FieldTag, + value: Atom<'a>, +} diff --git a/src/main.rs b/src/main.rs index dc52415..def3f9c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,10 @@ +use grammar::parser::parse_module; + mod grammar; mod ir; +mod parser; fn main() { - println!("Hello, world!"); + let m = include_str!("../formats/c37118.brin"); + println!("{:?}", parse_module(m)); }