Skip to content

Stage 1: ISO 10303-21 STEP text parser (kofem-geom crate) #9

Description

@mkofler96

Goal

Create the kofem-geom crate and implement a parser for the ISO 10303-21 exchange format used by all STEP files.

Background

new_bracket_2.stp (72 765 lines) is our reference file. Analysis shows it contains:

  • 26 691 CARTESIAN_POINT entities
  • 486 ADVANCED_FACE entities
  • 1 133 EDGE_CURVE entities
  • 651 VERTEX_POINT entities
  • 520 B_SPLINE_CURVE_WITH_KNOTS, 15 B_SPLINE_SURFACE_WITH_KNOTS

What to build

File: crates/kofem-geom/src/step/parser.rs

Parse the ASCII exchange format:

ISO-10303-21;
HEADER; … ENDSEC;
DATA;
#1 = CARTESIAN_POINT('', (0., 0., 0.));
#2 = LINE('label', #1, #3);
ENDSEC;
END-ISO-10303-21;

Each entity is #id = TYPE(arg, arg, …); and may span multiple lines.

Output types:

pub struct StepEntity {
    pub id: u64,
    pub type_name: String,
    pub args: Vec<Arg>,
}

pub enum Arg {
    String(String),
    Real(f64),
    Integer(i64),
    Ref(u64),       // #42
    List(Vec<Arg>), // (a, b, c)
    Enum(String),   // .FORWARD.
    Omitted,        // $
}

pub type StepFile = HashMap<u64, StepEntity>;

pub fn parse(text: &str) -> Result<StepFile, ParseError>;

TDD test cases

// RED → GREEN 1: entity count
#[test]
fn parses_bracket_entity_count() {
    let file = parse(include_str!("../../../test_files/new_bracket_2.stp")).unwrap();
    assert!(file.len() > 30_000);
}

// RED → GREEN 2: CARTESIAN_POINT args
#[test]
fn parses_cartesian_point_coords() {
    let snippet = "ISO-10303-21;\nHEADER;\nFILE_DESCRIPTION((''));\nENDSEC;\nDATA;\n\
        #97=CARTESIAN_POINT('',(4.388981755810E-8,1.467728130595E1,3.159218055376E1));\n\
        ENDSEC;\nEND-ISO-10303-21;";
    let file = parse(snippet).unwrap();
    let e = file.get(&97).unwrap();
    assert_eq!(e.type_name, "CARTESIAN_POINT");
    if let Arg::List(coords) = &e.args[1] {
        assert_eq!(coords.len(), 3);
        if let Arg::Real(x) = coords[0] { assert!((x - 4.388981755810E-8).abs() < 1e-15); }
    } else { panic!("expected List"); }
}

// RED → GREEN 3: count faces
#[test]
fn bracket_has_486_advanced_faces() {
    let file = parse(include_str!("../../../test_files/new_bracket_2.stp")).unwrap();
    let n = file.values().filter(|e| e.type_name == "ADVANCED_FACE").count();
    assert_eq!(n, 486);
}

Implementation notes

  • Handle multi-line entities by stripping \n from the DATA section before splitting on ;
  • String literals use '' for an escaped apostrophe
  • Enums look like .FORWARD.
  • $ means omitted / null
  • Ref: #\d+

Acceptance criteria

  • All three tests pass
  • cargo test -p kofem-geom is clean
  • cargo clippy -p kofem-geom -- -D warnings is clean

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions