shex_compact/
shapemap_grammar.rs1use crate::{
2 grammar::{map_error, tag_no_case_tws, token_tws, traced, tws0},
3 iri, literal,
4 shex_grammar::shape_expr_label,
5 IRes, ParseError, Span,
6};
7use nom::{
8 branch::alt,
9 character::complete::char,
10 combinator::{all_consuming, map, opt},
11 multi::many0,
12 sequence::tuple,
13};
14use shapemap::{NodeSelector, ShapeSelector};
15
16#[derive(Debug, PartialEq)]
17pub(crate) enum ShapeMapStatement {
18 Association {
19 node_selector: NodeSelector,
20 shape_selector: ShapeSelector,
21 },
22}
23
24pub(crate) fn shapemap_statement<'a>() -> impl FnMut(Span<'a>) -> IRes<'a, Vec<ShapeMapStatement>> {
25 traced(
26 "shapemap_statement",
27 map_error(
28 move |i| {
29 let (i, (a, _, ass, _, _)) = all_consuming(tuple((
30 association,
31 tws0,
32 rest_associations,
33 tws0,
34 opt(char(',')),
35 )))(i)?;
36 let mut rs = vec![a];
37 for a in ass {
38 rs.push(a);
39 }
40 Ok((i, rs))
41 },
42 || ParseError::ExpectedShapeMapAssociation,
43 ),
44 )
45}
46
47fn association(i: Span) -> IRes<ShapeMapStatement> {
49 let (i, (ns, _, sl)) = tuple((node_selector(), token_tws("@"), shape_spec()))(i)?;
50 let s = ShapeMapStatement::Association {
51 node_selector: ns,
52 shape_selector: sl,
53 };
54 Ok((i, s))
55}
56
57fn rest_associations(i: Span) -> IRes<Vec<ShapeMapStatement>> {
58 let (i, ass) = many0(tuple((token_tws(","), tws0, association)))(i)?;
59 let r = ass.into_iter().map(|(_, _, a)| a).collect();
60 Ok((i, r))
61}
62
63pub(crate) fn shape_spec<'a>() -> impl FnMut(Span<'a>) -> IRes<'a, ShapeSelector> {
64 traced(
65 "shape_spec",
66 map_error(
67 move |i| {
68 alt((
69 map(shape_expr_label, ShapeSelector::Label),
70 map(tag_no_case_tws("START"), |_| ShapeSelector::Start),
71 ))(i)
72 },
73 || ParseError::ExpectedShapeSpec,
74 ),
75 )
76}
77
78pub(crate) fn node_selector<'a>() -> impl FnMut(Span<'a>) -> IRes<'a, NodeSelector> {
80 traced(
81 "node_selector",
82 map_error(move |i| object_term(i), || ParseError::ExpectedNodeSpec),
83 )
84}
85
86fn object_term(i: Span) -> IRes<NodeSelector> {
87 alt((subject_term, literal_selector))(i)
88}
89
90fn subject_term(i: Span) -> IRes<NodeSelector> {
91 let (i, iri) = iri(i)?;
92 Ok((i, NodeSelector::iri_ref(iri)))
93}
94
95fn literal_selector(i: Span) -> IRes<NodeSelector> {
96 let (i, lit) = literal()(i)?;
97 Ok((i, NodeSelector::literal(lit)))
98}
99
100#[cfg(test)]
101mod tests {
102 use shapemap::ShapeSelector;
103
104 use super::*;
105
106 #[test]
107 fn example_shapemap() {
108 let input = Span::new(":a@:label");
109 let (_, shape_map) = association(input).unwrap();
110 let expected = ShapeMapStatement::Association {
111 node_selector: NodeSelector::prefixed("", "a"),
112 shape_selector: ShapeSelector::prefixed("", "label"),
113 };
114 assert_eq!(shape_map, expected);
115 }
116
117 }