Skip to main content

step_p21/parser/
mod.rs

1//! Tokenize exchange structure string into [ast]
2//!
3//! ASCII encoding of exchange structure, a.k.a. STEP file, consists of
4//! following sections:
5//!
6//! - HEADER
7//! - ANCHOR (optional)
8//! - REFERENCE (optional)
9//! - DATA
10//! - SIGNATURE (optional)
11//!
12//! ANCHOR, REFERENCE, and SIGNATURE sections are optional.
13//! The syntax of STEP-file is common through schemas,
14//! i.e. the tokenize of STEP-file can be done without reading any EXPRESS
15//! schema. A target schema is specified in the HEADER section,
16//! and it determines how we should understand AST.
17//!
18//! Example
19//! --------
20//!
21//! ```
22//! use std::{fs, path::*};
23//!
24//! // Read ABC Dataset's STEP file format example
25//! let step_file = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
26//!     .join("tests/steps/00000050_80d90bfdd2e74e709956122a_step_000.step");
27//! let step_str = fs::read_to_string(step_file).unwrap();
28//!
29//! // Parse STEP file into `Exchange` struct
30//! let ex = step_p21::parser::parse(&step_str).unwrap();
31//! ```
32
33pub mod basic;
34pub mod combinator;
35pub mod exchange;
36pub mod token;
37
38use crate::{
39    ast,
40    error::{Result, TokenizeFailed},
41};
42use nom::Finish;
43
44/// Parse HEADER section
45///
46/// Example
47/// --------
48///
49/// ```
50/// let step_str = r#"
51/// HEADER;
52///   FILE_DESCRIPTION(('叛逆の物語', '魔法少女まどか☆マギカ'), '4;3');
53///   FILE_NAME(
54///     '/madoka/magica/rebellion.step',
55///     '2013-10-26T10:30:00+09:00',
56///     ('Mami Tomoe', 'Madoka Kaname', 'Sayaka Miki', 'Kyoko Sakura', 'Homura Akemi'),
57///     ('Puella Magi Holy Quintet'),
58///     'homu',
59///     'Magica Quartet',
60///     'qb@incubator.com'
61///   );
62///   FILE_SCHEMA(('MAGICAL_GIRL'));
63/// ENDSEC;
64/// "#.trim();
65///
66/// let (residual, header) = step_p21::parser::parse_header(&step_str).unwrap();
67/// assert_eq!(residual, ""); // consume HEADER section of `step_str`
68/// ```
69pub fn parse_header(input: &str) -> Result<(&str, Vec<ast::Record>)> {
70    match exchange::header_section(input).finish() {
71        Ok((input, records)) => Ok((input, records)),
72        Err(e) => Err(TokenizeFailed::new(input, e).into()),
73    }
74}
75
76/// Parse entire STEP file
77pub fn parse(input: &str) -> Result<ast::Exchange> {
78    match exchange::exchange_file(input).finish() {
79        Ok((_residual, ex)) => Ok(ex),
80        Err(e) => Err(TokenizeFailed::new(input, e).into()),
81    }
82}