rdf_types/
macro.rs

1#[macro_export]
2#[doc(hidden)]
3macro_rules! unexpected_token {
4	() => {};
5}
6
7/// Creates a gRDF triple.
8#[macro_export]
9macro_rules! grdf_triple {
10	// Parse a triple.
11	{
12		@from ($($acc:tt)*) $id:ident $($rest:tt)*
13	} => {
14		$crate::grdf_triple!(@from ($($acc)* $id,) $($rest)*)
15	};
16	{
17		@from ($($acc:tt)*) < $iri:literal > $($rest:tt)*
18	} => {
19		$crate::grdf_triple!(@from ($($acc)* <$crate::Term>::iri($crate::static_iref::iri!($iri).to_owned()),) $($rest)*)
20	};
21	{
22		@from ($($acc:tt)*) _ : $id:literal $($rest:tt)*
23	} => {
24		$crate::grdf_triple!(@from ($($acc)* <$crate::Term>::blank($crate::BlankIdBuf::from_suffix($id).unwrap()),) $($rest)*)
25	};
26	{
27		@from ($($acc:tt)*) $value:literal ^^ $ty:literal $($rest:tt)*
28	} => {
29		$crate::grdf_triple!(@from ($($acc)* <$crate::Term>::Literal($crate::Literal::new(
30			$value.to_owned(),
31			$crate::LiteralType::Any(
32				$crate::static_iref::iri!($ty).to_owned()
33			)
34		)),) $($rest)*)
35	};
36	{
37		@from ($($acc:tt)*) $value:literal $($rest:tt)*
38	} => {
39		$crate::grdf_triple!(@from ($($acc)* <$crate::Term>::Literal($crate::Literal::new(
40			$value.to_owned(),
41			$crate::LiteralType::Any(
42				$crate::XSD_STRING.to_owned()
43			)
44		)),) $($rest)*)
45	};
46	{
47		@from ($($acc:tt)*)
48	} => {
49		<$crate::Triple>::new($($acc)*)
50	};
51	{
52		@from ($($acc:tt)*) $t:tt $($rest:tt)*
53	} => {
54		$crate::unexpected_token!($t)
55	};
56	// Main rule
57	{
58		$($t:tt)*
59	} => {
60		$crate::grdf_triple!(@from () $($t)*)
61	};
62}
63
64/// Creates an array of triples.
65#[macro_export]
66macro_rules! grdf_triples {
67	// Tokenize the triples.
68	{
69		@tokenize [$($acc:tt)*] [$($current:tt)*] $i:ident $($rest:tt)*
70	} => {
71		$crate::grdf_triples!(@tokenize [$($acc)*] [$($current)* $i] $($rest)*)
72	};
73	{
74		@tokenize [$($acc:tt)*] [$($current:tt)*] < $($rest:tt)*
75	} => {
76		$crate::grdf_triples!(@tokenize [$($acc)*] [$($current)* <] $($rest)*)
77	};
78	{
79		@tokenize [$($acc:tt)*] [$($current:tt)*] > $($rest:tt)*
80	} => {
81		$crate::grdf_triples!(@tokenize [$($acc)*] [$($current)* >] $($rest)*)
82	};
83	{
84		@tokenize [$($acc:tt)*] [$($current:tt)*] _ $($rest:tt)*
85	} => {
86		$crate::grdf_triples!(@tokenize [$($acc)*] [$($current)* _] $($rest)*)
87	};
88	{
89		@tokenize [$($acc:tt)*] [$($current:tt)*] : $($rest:tt)*
90	} => {
91		$crate::grdf_triples!(@tokenize [$($acc)*] [$($current)* :] $($rest)*)
92	};
93	{
94		@tokenize [$($acc:tt)*] [$($current:tt)*] ^ $($rest:tt)*
95	} => {
96		$crate::grdf_triples!(@tokenize [$($acc)*] [$($current)* ^] $($rest)*)
97	};
98	{
99		@tokenize [$($acc:tt)*] [$($current:tt)*] $l:literal $($rest:tt)*
100	} => {
101		$crate::grdf_triples!(@tokenize [$($acc)*] [$($current)* $l] $($rest)*)
102	};
103	{
104		@tokenize [$($acc:tt)*] [$($current:tt)*] . $($rest:tt)*
105	} => {
106		$crate::grdf_triples!(@tokenize [$($acc)* ( $($current)* )] [] $($rest)*)
107	};
108	{
109		@tokenize [$($acc:tt)*] []
110	} => {
111		$crate::grdf_triples!(@triples_from [] $($acc)*)
112	};
113	{
114		@tokenize [$($acc:tt)*] [$($current:tt)*] $t:tt $($rest:tt)*
115	} => {
116		$crate::unexpected_token!($t)
117	};
118	// Parse a tokenized triple list.
119	{
120		@triples_from [$($acc:tt)*] ($($triple:tt)*) $($rest:tt)*
121	} => {
122		$crate::grdf_triples!(@triples_from [$($acc)* $crate::grdf_triple!($($triple)*),] $($rest)*)
123	};
124	{
125		@triples_from [$($acc:tt)*]
126	} => {
127		[$($acc)*]
128	};
129
130	// Main rule.
131	{
132		$($t:tt)*
133	} => {
134		$crate::grdf_triples!(@tokenize [] [] $($t)*)
135	};
136}
137
138/// Creates a gRDF quad.
139#[macro_export]
140macro_rules! grdf_quad {
141	// Parse a quad.
142	{
143		@from ($($acc:tt)*) $id:ident $($rest:tt)*
144	} => {
145		$crate::grdf_quad!(@from ($($acc)* $id,) $($rest)*)
146	};
147	{
148		@from ($($acc:tt)*) < $iri:literal > $($rest:tt)*
149	} => {
150		$crate::grdf_quad!(@from ($($acc)* <$crate::Term>::iri($crate::static_iref::iri!($iri).to_owned()),) $($rest)*)
151	};
152	{
153		@from ($($acc:tt)*) _ : $id:literal $($rest:tt)*
154	} => {
155		$crate::grdf_quad!(@from ($($acc)* <$crate::Term>::blank($crate::BlankIdBuf::from_suffix($id).unwrap()),) $($rest)*)
156	};
157	{
158		@from ($($acc:tt)*) $value:literal ^^ $ty:literal $($rest:tt)*
159	} => {
160		$crate::grdf_quad!(@from ($($acc)* <$crate::Term>::Literal($crate::Literal::new(
161			$value.to_owned(),
162			$crate::LiteralType::Any(
163				$crate::static_iref::iri!($ty).to_owned()
164			)
165		)),) $($rest)*)
166	};
167	{
168		@from ($($acc:tt)*) $value:literal $($rest:tt)*
169	} => {
170		$crate::grdf_quad!(@from ($($acc)* <$crate::Term>::Literal($crate::Literal::new(
171			$value.to_owned(),
172			$crate::LiteralType::Any(
173				$crate::XSD_STRING.to_owned()
174			)
175		)),) $($rest)*)
176	};
177	{
178		@from ($s:expr, $p:expr, $o:expr,)
179	} => {
180		<$crate::Quad>::new($s, $p, $o, None)
181	};
182	{
183		@from ($s:expr, $p:expr, $o:expr, $g:expr,)
184	} => {
185		<$crate::Quad>::new($s, $p, $o, Some($g))
186	};
187	{
188		@from ($($acc:tt)*) $t:tt $($rest:tt)*
189	} => {
190		$crate::unexpected_token!($t)
191	};
192	// Main rule
193	{
194		$($t:tt)*
195	} => {
196		$crate::grdf_quad!(@from () $($t)*)
197	};
198}
199
200/// Creates a gRDF quad pattern.
201///
202/// The type of the returned value is `Quad<ResourceOrVar<Term, _>>`.
203///
204/// This is similar to [`grdf_quad`], but with the addition of variables, which
205/// can be introduced using the syntax `?ident`. The variable `ident` must be
206/// an identifier to some Rust variable holding the pattern variable's value.
207#[macro_export]
208macro_rules! grdf_quad_pattern {
209	// Parse a quad pattern.
210	{
211		@from ($($acc:tt)*) ? $id:ident $($rest:tt)*
212	} => {
213		$crate::grdf_quad_pattern!(@from ($($acc)* $crate::pattern::ResourceOrVar::Var($id),) $($rest)*)
214	};
215	{
216		@from ($($acc:tt)*) $id:ident $($rest:tt)*
217	} => {
218		$crate::grdf_quad_pattern!(@from ($($acc)* $crate::pattern::ResourceOrVar::Resource($id),) $($rest)*)
219	};
220	{
221		@from ($($acc:tt)*) < $iri:literal > $($rest:tt)*
222	} => {
223		$crate::grdf_quad_pattern!(@from ($($acc)* $crate::pattern::ResourceOrVar::Resource(<$crate::Term>::iri($crate::static_iref::iri!($iri).to_owned())),) $($rest)*)
224	};
225	{
226		@from ($($acc:tt)*) _ : $id:literal $($rest:tt)*
227	} => {
228		$crate::grdf_quad_pattern!(@from ($($acc)* $crate::pattern::ResourceOrVar::Resource(<$crate::Term>::blank($crate::BlankIdBuf::from_suffix($id).unwrap())),) $($rest)*)
229	};
230	{
231		@from ($($acc:tt)*) $value:literal ^^ $ty:literal $($rest:tt)*
232	} => {
233		$crate::grdf_quad_pattern!(@from ($($acc)* $crate::pattern::ResourceOrVar::Resource(<$crate::Term>::Literal($crate::Literal::new(
234			$value.to_owned(),
235			$crate::LiteralType::Any(
236				$crate::static_iref::iri!($ty).to_owned()
237			)
238		))),) $($rest)*)
239	};
240	{
241		@from ($($acc:tt)*) $value:literal $($rest:tt)*
242	} => {
243		$crate::grdf_quad_pattern!(@from ($($acc)* $crate::pattern::ResourceOrVar::Resource(<$crate::Term>::Literal($crate::Literal::new(
244			$value.to_owned(),
245			$crate::LiteralType::Any(
246				$crate::XSD_STRING.to_owned()
247			)
248		))),) $($rest)*)
249	};
250	{
251		@from ($s:expr, $p:expr, $o:expr,)
252	} => {
253		<$crate::Quad<$crate::pattern::ResourceOrVar<$crate::Term, _>>>::new($s, $p, $o, None)
254	};
255	{
256		@from ($s:expr, $p:expr, $o:expr, $g:expr,)
257	} => {
258		<$crate::Quad<$crate::pattern::ResourceOrVar<$crate::Term, _>>>::new($s, $p, $o, Some($g))
259	};
260	{
261		@from ($($acc:tt)*) $t:tt $($rest:tt)*
262	} => {
263		$crate::unexpected_token!($t)
264	};
265	// Main rule
266	{
267		$($t:tt)*
268	} => {
269		$crate::grdf_quad_pattern!(@from () $($t)*)
270	};
271}
272
273/// Creates an array of quads.
274#[macro_export]
275macro_rules! grdf_quads {
276	// Tokenize the quads.
277	{
278		@tokenize [$($acc:tt)*] [$($current:tt)*] $i:ident $($rest:tt)*
279	} => {
280		$crate::grdf_quads!(@tokenize [$($acc)*] [$($current)* $i] $($rest)*)
281	};
282	{
283		@tokenize [$($acc:tt)*] [$($current:tt)*] < $($rest:tt)*
284	} => {
285		$crate::grdf_quads!(@tokenize [$($acc)*] [$($current)* <] $($rest)*)
286	};
287	{
288		@tokenize [$($acc:tt)*] [$($current:tt)*] > $($rest:tt)*
289	} => {
290		$crate::grdf_quads!(@tokenize [$($acc)*] [$($current)* >] $($rest)*)
291	};
292	{
293		@tokenize [$($acc:tt)*] [$($current:tt)*] _ $($rest:tt)*
294	} => {
295		$crate::grdf_quads!(@tokenize [$($acc)*] [$($current)* _] $($rest)*)
296	};
297	{
298		@tokenize [$($acc:tt)*] [$($current:tt)*] : $($rest:tt)*
299	} => {
300		$crate::grdf_quads!(@tokenize [$($acc)*] [$($current)* :] $($rest)*)
301	};
302	{
303		@tokenize [$($acc:tt)*] [$($current:tt)*] ^ $($rest:tt)*
304	} => {
305		$crate::grdf_quads!(@tokenize [$($acc)*] [$($current)* ^] $($rest)*)
306	};
307	{
308		@tokenize [$($acc:tt)*] [$($current:tt)*] $l:literal $($rest:tt)*
309	} => {
310		$crate::grdf_quads!(@tokenize [$($acc)*] [$($current)* $l] $($rest)*)
311	};
312	{
313		@tokenize [$($acc:tt)*] [$($current:tt)*] . $($rest:tt)*
314	} => {
315		$crate::grdf_quads!(@tokenize [$($acc)* ( $($current)* )] [] $($rest)*)
316	};
317	{
318		@tokenize [$($acc:tt)*] []
319	} => {
320		$crate::grdf_quads!(@quads_from [] $($acc)*)
321	};
322	{
323		@tokenize [$($acc:tt)*] [$($current:tt)*] $t:tt $($rest:tt)*
324	} => {
325		$crate::unexpected_token!($t)
326	};
327	// Parse a tokenized triple list.
328	{
329		@quads_from [$($acc:tt)*] ($($triple:tt)*) $($rest:tt)*
330	} => {
331		$crate::grdf_quads!(@quads_from [$($acc)* $crate::grdf_quad!($($triple)*),] $($rest)*)
332	};
333	{
334		@quads_from [$($acc:tt)*]
335	} => {
336		[$($acc)*]
337	};
338
339	// Main rule.
340	{
341		$($t:tt)*
342	} => {
343		$crate::grdf_quads!(@tokenize [] [] $($t)*)
344	};
345}
346
347#[cfg(test)]
348mod tests {
349	use static_iref::iri;
350
351	#[test]
352	fn grdf_triple_macro() {
353		let _ = grdf_triple! [
354			_:"foo" <"https://example.org/#foo"> "foo"
355		];
356	}
357
358	#[test]
359	fn grdf_triples_macro() {
360		let term = <crate::Term>::iri(iri!("https://example.org/#iri").to_owned());
361		let _ = grdf_triples! [
362			_:"foo" <"https://example.org/#foo"> "foo" .
363			<"https://example.org/#bar"> _:"bar" "bar"^^"https://example.org/#datatype" .
364			<"https://example.org/#baz"> term "value" .
365		];
366	}
367
368	#[test]
369	fn grdf_quad_macro() {
370		let _ = grdf_quad! [
371			_:"foo" <"https://example.org/#foo"> "foo"
372		];
373	}
374
375	#[test]
376	fn grdf_quads_macro() {
377		let term = <crate::Term>::iri(iri!("https://example.org/#iri").to_owned());
378		let _ = grdf_quads! [
379			_:"foo" <"https://example.org/#foo"> "foo" .
380			<"https://example.org/#bar"> _:"bar" "bar"^^"https://example.org/#datatype" .
381			<"https://example.org/#baz"> term "value" <"https://example.org/#graph"> .
382		];
383	}
384}