aboutsummaryrefslogtreecommitdiffstats
path: root/src/read_ntriples.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/read_ntriples.c')
-rw-r--r--src/read_ntriples.c52
1 files changed, 51 insertions, 1 deletions
diff --git a/src/read_ntriples.c b/src/read_ntriples.c
index da726658..bec59c13 100644
--- a/src/read_ntriples.c
+++ b/src/read_ntriples.c
@@ -520,6 +520,51 @@ read_HEX(SerdReader* const reader)
return 0;
}
+/**
+ Read a variable name, starting after the '?' or '$'.
+
+ This is an extension that serd uses in certain contexts to support patterns.
+
+ Restricted version of SPARQL 1.1: [166] VARNAME
+*/
+static SerdStatus
+read_VARNAME(SerdReader* const reader, SerdNode** const dest)
+{
+ // Simplified from SPARQL: VARNAME ::= (PN_CHARS_U | [0-9])+
+ SerdNode* n = *dest;
+ SerdStatus st = SERD_SUCCESS;
+ int c = 0;
+
+ while ((c = peek_byte(reader))) {
+ if (is_digit(c) || c == '_') {
+ st = push_byte(reader, n, eat_byte_safe(reader, c));
+ } else if ((st = read_PN_CHARS(reader, n))) {
+ st = st > SERD_FAILURE ? st : SERD_SUCCESS;
+ break;
+ }
+ }
+
+ return st;
+}
+
+SerdStatus
+read_Var(SerdReader* const reader, SerdNode** const dest)
+{
+ if (!(reader->flags & SERD_READ_VARIABLES)) {
+ return r_err(reader, SERD_BAD_SYNTAX, "syntax does not support variables");
+ }
+
+ const int c = peek_byte(reader);
+ assert(c == '$' || c == '?');
+ skip_byte(reader, c);
+
+ if (!(*dest = push_node(reader, SERD_VARIABLE, "", 0))) {
+ return SERD_BAD_STACK;
+ }
+
+ return read_VARNAME(reader, dest);
+}
+
// Nonterminals
// comment ::= '#' ( [^#xA #xD] )*
@@ -576,6 +621,8 @@ read_nt_subject(SerdReader* const reader, SerdNode** const dest)
switch (peek_byte(reader)) {
case '<':
return read_IRI(reader, dest);
+ case '?':
+ return read_Var(reader, dest);
case '_':
return read_BLANK_NODE_LABEL(reader, dest, &ate_dot);
default:
@@ -589,7 +636,8 @@ read_nt_subject(SerdReader* const reader, SerdNode** const dest)
SerdStatus
read_nt_predicate(SerdReader* const reader, SerdNode** const dest)
{
- return read_IRI(reader, dest);
+ return (peek_byte(reader) == '?') ? read_Var(reader, dest)
+ : read_IRI(reader, dest);
}
/// [4] object
@@ -605,6 +653,8 @@ read_nt_object(SerdReader* const reader,
return read_literal(reader, dest);
case '<':
return read_IRI(reader, dest);
+ case '?':
+ return read_Var(reader, dest);
case '_':
return read_BLANK_NODE_LABEL(reader, dest, ate_dot);
default: