shex_compact/
shapemap_grammar.rs

1use 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
47/// `association ::= node_spec @ shape_spec`
48fn 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
78/// nodeSelector     : objectTerm | triplePattern | extended ;
79pub(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    /*    #[test_log::test]
118    fn example_shapemap_failed () {
119        let input = Span::new("\n @START \n # Comment \n@STRT\n");
120        let shape_map = parse_shapemap(input).unwrap();
121        let expected = InputShapeMap::new();
122        assert_eq!(shape_map, expected);
123    } */
124}