working on c37.118 forma

This commit is contained in:
Wintermute 2025-06-30 10:13:29 +02:00
parent 7883b42d13
commit f86a6bf9f4
6 changed files with 53 additions and 74 deletions

9
.mise.toml Normal file
View file

@ -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"

View file

@ -1,11 +1,15 @@
#= Bigendian #= BigEndian
CFGFRAME { CFGFRAME {
0-1 bytes: field "SYNC" { 0-1 bytes: field "SYNC" {
0 byte: const "magic_number" u8 0xAA 0 byte: const "sync" u8 0xAA
1 byte: const "ver_number" u8 0x31 1 byte: field "type_ver" {}
} }
3-4 bytes: field "TIME BASE" u16 2-3 bytes: field "framesize" u16
5-6 bytes: field "NUM_PMU" 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
} }

View file

@ -1,4 +1,4 @@
use crate::ir::{Atom, OwnedAtom}; use crate::ir::OwnedAtom;
pub(crate) mod parser; pub(crate) mod parser;
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
@ -53,4 +53,4 @@ pub(crate) enum Type {
} }
/// position of field relative to parent /// position of field relative to parent
type Range = (usize, usize); pub type Range = (usize, usize);

View file

@ -1,3 +1,5 @@
use crate::ir::Atom;
use nom::character::complete::space0;
use std::error::Error; use std::error::Error;
use nom::IResult; use nom::IResult;
@ -14,8 +16,6 @@ use nom::character::complete::digit1;
use nom::character::complete::hex_digit1; use nom::character::complete::hex_digit1;
use nom::character::complete::line_ending; use nom::character::complete::line_ending;
use nom::character::complete::multispace0; use nom::character::complete::multispace0;
use nom::character::complete::newline;
use nom::character::complete::space0;
use nom::character::streaming::multispace1; use nom::character::streaming::multispace1;
use nom::combinator::map; use nom::combinator::map;
use nom::combinator::map_res; use nom::combinator::map_res;
@ -31,8 +31,6 @@ use nom::sequence::pair;
use nom::sequence::preceded; use nom::sequence::preceded;
use nom::sequence::terminated; use nom::sequence::terminated;
use crate::ir::Atom;
use super::FieldRegion; use super::FieldRegion;
use super::Module; use super::Module;
use super::Options; use super::Options;
@ -117,7 +115,6 @@ fn identifier_test() {
/// A combinator that parses primitive types. /// A combinator that parses primitive types.
pub fn parse_type(input: &str) -> IResult<&str, Type> { pub fn parse_type(input: &str) -> IResult<&str, Type> {
println!("type: {:?}", input);
alt(( alt((
(map(tag("bool"), |_| Type::Bool)), (map(tag("bool"), |_| Type::Bool)),
(map(tag("u8"), |_| Type::U8)), (map(tag("u8"), |_| Type::U8)),
@ -196,7 +193,6 @@ fn range_test() {
} }
pub fn parse_field_entry(input: &str) -> IResult<&str, (Range, FieldRegion)> { pub fn parse_field_entry(input: &str) -> IResult<&str, (Range, FieldRegion)> {
println!("field_entry{:?}", input);
map( map(
( (
parse_range, 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> { pub fn parse_region(input: &str) -> IResult<&str, Region> {
println!("Region: {:?}", input);
alt(( alt((
map( map(
( (
multispace0, multispace0,
char('{'), char('{'),
multispace1, multispace0,
separated_list0(multispace1, parse_field_entry), separated_list0(multispace1, parse_field_entry),
multispace1, multispace0,
char('}'), char('}'),
), ),
|(_, _, _, field_list, _, _)| Region::Fields(field_list), |(_, _, _, 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> { pub fn parse_module(input: &str) -> IResult<&str, Module> {
println!("{}", input);
map( map(
( (
parse_options, parse_options,
@ -402,62 +396,22 @@ pub fn parse_module(input: &str) -> IResult<&str, Module> {
fn module_test() { fn module_test() {
let module = "#= BigEndian\n\n\nCFGFRAME { 0-1 bytes: field \"SYNC\" u16 }"; let module = "#= BigEndian\n\n\nCFGFRAME { 0-1 bytes: field \"SYNC\" u16 }";
let (_, module) = parse_module(module).unwrap(); let (_, module) = parse_module(module).unwrap();
assert_eq!(module.opts, Options(vec!["BigEndian".to_owned()])); assert_eq!(
assert_eq!(module.objs[0].0, "CFGFRAME"); module,
} Module {
objs: vec![(
#[test] "CFGFRAME".to_owned(),
fn c37118_test() { Region::Fields(vec![(
let brin = include_str!("../../formats/c37118.brin"); (0, 15),
let (_, module) = parse_module(brin).unwrap(); FieldRegion::Subfield {
assert_eq!(module.opts, Options(vec!["Bigendian".to_owned()])); name: "SYNC".to_owned(),
assert_eq!(module.objs[0].0, "CFGFRAME"); content: Region::Atom { ty: Type::U16 }
}
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 { opts: Options(vec!["BigEndian".to_owned()])
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!(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] #[test]
@ -476,7 +430,7 @@ fn test_field_entry() {
} }
#[test] #[test]
fn test_region_good() { fn test_region_god() {
let region = "{ let region = "{
3-4 byte: field \"time base\" u16 3-4 byte: field \"time base\" u16
5-6 byte: field \"magic number\" { 5-6 byte: field \"magic number\" {

View file

@ -1,6 +1,8 @@
//use nanoid::nanoid; //use nanoid::nanoid;
use std::borrow::Cow; use std::borrow::Cow;
use crate::grammar::Range;
/* Any format will be parsed into an intermediate, json-like object. /* Any format will be parsed into an intermediate, json-like object.
Where possible, zero-copying should be done (???!); 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>,
}

View file

@ -1,6 +1,10 @@
use grammar::parser::parse_module;
mod grammar; mod grammar;
mod ir; mod ir;
mod parser;
fn main() { fn main() {
println!("Hello, world!"); let m = include_str!("../formats/c37118.brin");
println!("{:?}", parse_module(m));
} }