shex_compact/
shapemap_parser.rs1use crate::shapemap_grammar::shapemap_statement;
2use crate::shapemap_grammar::ShapeMapStatement;
3use crate::shapemap_grammar::{node_selector, shape_spec};
4use crate::shex_grammar::iri;
5use crate::tws0;
6use crate::ParseError;
7use crate::Span;
8use nom::Err;
9use prefixmap::IriRef;
10use prefixmap::PrefixMap;
11use shapemap::query_shape_map::QueryShapeMap;
12use shapemap::NodeSelector;
13use shapemap::ShapeSelector;
14use std::fs;
15use std::path::Path;
16use tracing::debug;
17
18type Result<A> = std::result::Result<A, ParseError>;
19
20pub struct ShapeMapParser<'a> {
21 shapemap_statement_iterator: ShapeMapStatementIterator<'a>,
22}
23
24impl ShapeMapParser<'_> {
25 pub fn parse(
28 src: &str,
29 nodes_prefixmap: &Option<PrefixMap>,
30 shapes_prefixmap: &Option<PrefixMap>,
31 ) -> Result<QueryShapeMap> {
32 let mut query_shapemap = QueryShapeMap::new();
33 if let Some(pm) = nodes_prefixmap {
34 query_shapemap = query_shapemap.with_nodes_prefixmap(pm)
35 };
36 if let Some(pm) = shapes_prefixmap {
37 query_shapemap = query_shapemap.with_shapes_prefixmap(pm)
38 };
39 let mut parser = ShapeMapParser {
40 shapemap_statement_iterator: ShapeMapStatementIterator::new(Span::new(src))?,
41 };
42 for ss in parser.shapemap_statement_iterator.by_ref() {
43 let statements = ss?;
44 for s in statements {
45 match s {
46 ShapeMapStatement::Association {
47 node_selector,
48 shape_selector,
49 } => {
50 tracing::debug!("Association {node_selector:?}@{shape_selector:?}");
51 query_shapemap.add_association(node_selector, shape_selector);
52 }
53 }
54 }
55 }
56 Ok(query_shapemap)
57 }
58
59 pub fn parse_buf(
60 path: &Path,
61 nodes_prefixmap: &Option<PrefixMap>,
62 shapes_prefixmap: &Option<PrefixMap>,
63 ) -> Result<QueryShapeMap> {
64 let data = fs::read_to_string(path)?;
65 let query_shapemap = ShapeMapParser::parse(&data, nodes_prefixmap, shapes_prefixmap)?;
66 Ok(query_shapemap)
67 }
68
69 pub fn parse_shape_selector(str: &str) -> Result<ShapeSelector> {
70 let span = Span::new(str);
71 let (_, ss) = shape_spec()(span).map_err(|e| match e {
72 Err::Incomplete(s) => ParseError::Custom {
73 msg: format!("Incomplete input: needed {s:?}"),
74 },
75 Err::Error(e) => ParseError::NomError { err: Box::new(e) },
76 Err::Failure(f) => ParseError::NomError { err: Box::new(f) },
77 })?;
78 Ok(ss)
79 }
80
81 pub fn parse_node_selector(str: &str) -> Result<NodeSelector> {
82 let span = Span::new(str);
83 let (_, ns) = node_selector()(span).map_err(|e| match e {
84 Err::Incomplete(s) => ParseError::Custom {
85 msg: format!("Incomplete input parsing node selector {str}: needed {s:?}"),
86 },
87 Err::Error(e) => ParseError::NodeSelectorNomError {
88 str: str.to_string(),
89 err: Box::new(e),
90 },
91 Err::Failure(f) => ParseError::NodeSelectorNomError {
92 str: str.to_string(),
93 err: Box::new(f),
94 },
95 })?;
96 Ok(ns)
97 }
98
99 pub fn parse_iri_ref(str: &str) -> Result<IriRef> {
100 let span = Span::new(str);
101 let (_, iri_ref) = iri(span).map_err(|e| match e {
102 Err::Incomplete(s) => ParseError::Custom {
103 msg: format!("Incomplete input: needed {s:?}"),
104 },
105 Err::Error(e) => ParseError::NomError { err: Box::new(e) },
106 Err::Failure(f) => ParseError::NomError { err: Box::new(f) },
107 })?;
108 Ok(iri_ref)
109 }
110}
111
112struct ShapeMapStatementIterator<'a> {
113 src: Span<'a>,
114 done: bool,
115}
116
117impl ShapeMapStatementIterator<'_> {
118 pub fn new(src: Span) -> Result<ShapeMapStatementIterator> {
119 match tws0(src) {
120 Ok((left, _)) => Ok(ShapeMapStatementIterator {
121 src: left,
122 done: false,
123 }),
124 Err(Err::Incomplete(_)) => Ok(ShapeMapStatementIterator { src, done: false }),
125 Err(e) => Err(ParseError::Custom {
126 msg: format!("cannot start parsing. Error: {}", e),
127 }),
128 }
129 }
130}
131
132impl Iterator for ShapeMapStatementIterator<'_> {
133 type Item = Result<Vec<ShapeMapStatement>>;
134
135 fn next(&mut self) -> Option<Self::Item> {
136 if self.done {
137 return None;
138 }
139 let mut r;
140 match shapemap_statement()(self.src) {
141 Ok((left, s)) => {
142 if s.is_empty() {
143 r = None;
144 } else {
145 r = Some(Ok(s));
146 }
147 self.src = left;
148 }
149 Err(Err::Incomplete(_)) => {
150 debug!("Incomplete! shapemap_statement");
151 self.done = true;
152 r = None;
153 }
154 Err(Err::Error(e)) | Err(Err::Failure(e)) => {
155 r = Some(Err(ParseError::NomError { err: Box::new(e) }));
156 self.done = true;
157 }
158 }
159 if self.src.is_empty() {
160 self.done = true;
161 }
162 if r.is_none() && !self.src.is_empty() {
163 r = Some(Err(ParseError::Custom {
164 msg: format!("trailing bytes {}", self.src),
165 }));
166 }
167 r
168 }
169}
170
171#[cfg(test)]
172mod tests {
173
174 use iri_s::IriS;
175 use shapemap::{NodeSelector, ShapeSelector};
176
177 use super::*;
178
179 #[test]
180 fn test_prefix() {
181 let str = r#":a@:S"#;
182 let mut nodes_prefixmap = PrefixMap::new();
183 nodes_prefixmap
184 .insert("", &IriS::new_unchecked("http://example.org/"))
185 .unwrap();
186
187 let mut shapes_prefixmap = PrefixMap::new();
188 shapes_prefixmap
189 .insert("", &IriS::new_unchecked("http://example.org/shapes/"))
190 .unwrap();
191
192 let parsed_shapemap = ShapeMapParser::parse(
193 str,
194 &Some(nodes_prefixmap.clone()),
195 &Some(shapes_prefixmap.clone()),
196 )
197 .unwrap();
198
199 let mut expected = QueryShapeMap::new()
200 .with_nodes_prefixmap(&nodes_prefixmap)
201 .with_shapes_prefixmap(&shapes_prefixmap);
202
203 expected.add_association(
204 NodeSelector::prefixed("", "a"),
205 ShapeSelector::prefixed("", "S"),
206 );
207 assert_eq!(parsed_shapemap, expected)
208 }
209}