1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
mod algorithm;
mod entity;
mod expression;
mod schema;
mod types;
pub use algorithm::*;
pub use entity::*;
pub use expression::*;
pub use schema::*;
pub use types::*;
use crate::parser::{combinator::*, *};
use nom::Finish;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Remark {
pub tag: Option<Vec<String>>,
pub remark: String,
}
#[derive(Debug, Clone, PartialEq)]
pub struct SyntaxTree {
pub schemas: Vec<Schema>,
pub remarks: Vec<Remark>,
}
impl SyntaxTree {
pub fn parse(input: &str) -> Result<Self, nom::error::VerboseError<&str>> {
let (residual, (schemas, remarks)) = tuple((spaces, many1(schema_decl), spaces))
.map(|(_start_space, schemas, _end_space)| schemas)
.parse(input)
.finish()?;
assert!(residual.is_empty());
Ok(SyntaxTree { schemas, remarks })
}
#[allow(dead_code)]
pub(crate) fn example() -> Self {
Self::parse(
r#"
SCHEMA one;
ENTITY first;
m_ref : second;
fattr : STRING;
END_ENTITY;
ENTITY second;
sattr : STRING;
END_ENTITY;
END_SCHEMA;
SCHEMA geometry0;
ENTITY point;
x, y, z: REAL;
END_ENTITY;
END_SCHEMA;
"#
.trim(),
)
.unwrap()
}
}
#[cfg(test)]
mod tests {
#[test]
fn parse_remarks() {
let st = super::SyntaxTree::parse(
r#"
SCHEMA one;
ENTITY first;
m_ref : second;
fattr : STRING;
END_ENTITY; -- first
ENTITY second;
sattr : STRING;
END_ENTITY; -- second
(* this is the example! *)
END_SCHEMA;
(* Hey! *)
SCHEMA geometry0;
ENTITY point;
x, (* y, *) z: REAL; -- skip y
END_ENTITY;
END_SCHEMA;
"#,
)
.unwrap();
dbg!(&st);
assert_eq!(st.remarks.len(), 6);
}
}