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 {
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
}

View file

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

View file

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

View file

@ -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>,
}

View file

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