1use crate::graph::{Loaded, term_to_node};
5use crate::vocab;
6use oxrdf::Term;
7use shifty_algebra::Path;
8
9pub fn parse_path(g: &Loaded, term: &Term) -> Result<Path, String> {
11 match term {
12 Term::NamedNode(n) => Ok(Path::Pred(n.clone())),
13 Term::Literal(_) => Err("sh:path value is a literal".to_string()),
14 Term::BlankNode(_) => {
15 let node = term_to_node(term).expect("blank node is a node");
16
17 if g.object(&node, vocab::RDF_FIRST).is_some() {
20 let members = g.read_list(term);
21 let parts = members
22 .iter()
23 .map(|m| parse_path(g, m))
24 .collect::<Result<Vec<_>, _>>()?;
25 return Ok(Path::seq(parts));
26 }
27 if let Some(x) = g.object(&node, vocab::SH_INVERSE_PATH) {
28 return Ok(parse_path(g, &x)?.inverse());
29 }
30 if let Some(list) = g.object(&node, vocab::SH_ALTERNATIVE_PATH) {
31 let members = g.read_list(&list);
32 let parts = members
33 .iter()
34 .map(|m| parse_path(g, m))
35 .collect::<Result<Vec<_>, _>>()?;
36 return Ok(Path::alt(parts));
37 }
38 if let Some(x) = g.object(&node, vocab::SH_ZERO_OR_MORE_PATH) {
39 return Ok(parse_path(g, &x)?.star());
40 }
41 if let Some(x) = g.object(&node, vocab::SH_ONE_OR_MORE_PATH) {
42 return Ok(parse_path(g, &x)?.one_or_more());
43 }
44 if let Some(x) = g.object(&node, vocab::SH_ZERO_OR_ONE_PATH) {
45 return Ok(parse_path(g, &x)?.zero_or_one());
46 }
47 Err("unrecognized blank-node path expression".to_string())
48 }
49 }
50}