aboutsummaryrefslogtreecommitdiffstats
path: root/src/n3.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2019-12-18 19:09:49 -0500
committerDavid Robillard <d@drobilla.net>2022-01-13 23:05:26 -0500
commit5d43cb36087292a397992aa1b59326fc355d5247 (patch)
treef313f87fea160cd52af3bba8c3de77c25b0519bf /src/n3.c
parent55e28966226268a57edb07419ac419ef53ac437d (diff)
downloadserd-5d43cb36087292a397992aa1b59326fc355d5247.tar.gz
serd-5d43cb36087292a397992aa1b59326fc355d5247.tar.bz2
serd-5d43cb36087292a397992aa1b59326fc355d5247.zip
Add support for parsing variables
This adds a reader flag and serdi option for extending a syntax with support for SPARQL-like variables, for storing things like patterns or simple queries.
Diffstat (limited to 'src/n3.c')
-rw-r--r--src/n3.c81
1 files changed, 76 insertions, 5 deletions
diff --git a/src/n3.c b/src/n3.c
index a6aa71ba..517dce8f 100644
--- a/src/n3.c
+++ b/src/n3.c
@@ -963,10 +963,53 @@ read_literal(SerdReader* const reader,
}
static SerdStatus
-read_verb(SerdReader* const reader, SerdNode** const dest)
+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;
+ peek_byte(reader);
+ 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;
+}
+
+static SerdStatus
+read_Var(SerdReader* const reader, SerdNode** const dest)
+{
+ if (!(reader->flags & SERD_READ_VARIABLES)) {
+ return r_err(
+ reader, SERD_ERR_BAD_SYNTAX, "syntax does not support variables\n");
+ }
+
+ if (!(*dest = push_node(reader, SERD_VARIABLE, "", 0))) {
+ return SERD_ERR_OVERFLOW;
+ }
+
+ assert(peek_byte(reader) == '$' || peek_byte(reader) == '?');
+ serd_byte_source_advance(reader->source);
+
+ return read_VARNAME(reader, dest);
+}
+
+static SerdStatus
+read_verb(SerdReader* reader, SerdNode** dest)
{
const size_t orig_stack_size = reader->stack.size;
- if (peek_byte(reader) == '<') {
+
+ switch (peek_byte(reader)) {
+ case '$':
+ case '?':
+ return read_Var(reader, dest);
+ case '<':
return read_IRIREF(reader, dest);
}
@@ -1138,6 +1181,9 @@ read_object(SerdReader* const reader,
case '<':
case '_':
break;
+ case '$':
+ case '?':
+ break;
default:
return r_err(reader, SERD_ERR_BAD_SYNTAX, "expected: ':', '<', or '_'\n");
}
@@ -1147,6 +1193,10 @@ read_object(SerdReader* const reader,
case EOF:
case ')':
return r_err(reader, SERD_ERR_BAD_SYNTAX, "expected object\n");
+ case '$':
+ case '?':
+ ret = read_Var(reader, &o);
+ break;
case '[':
simple = false;
ret = read_anon(reader, *ctx, false, &o);
@@ -1375,6 +1425,10 @@ read_subject(SerdReader* const reader,
SerdStatus st = SERD_SUCCESS;
bool ate_dot = false;
switch ((*s_type = peek_byte(reader))) {
+ case '$':
+ case '?':
+ st = read_Var(reader, dest);
+ break;
case '[':
st = read_anon(reader, ctx, true, dest);
break;
@@ -1643,6 +1697,7 @@ read_n3_statement(SerdReader* const reader)
if (s_type == '(' || (s_type == '[' && !*ctx.flags)) {
return r_err(reader, SERD_ERR_BAD_SYNTAX, "invalid graph name\n");
}
+
ctx.graph = ctx.subject;
ctx.subject = NULL;
TRY(st, read_wrappedGraph(reader, &ctx));
@@ -1658,6 +1713,7 @@ read_n3_statement(SerdReader* const reader)
}
return st > SERD_FAILURE ? st : SERD_ERR_BAD_SYNTAX;
+
} else if (!ate_dot) {
read_ws_star(reader);
st = eat_byte_check(reader, '.');
@@ -1717,10 +1773,22 @@ read_nquadsDoc(SerdReader* const reader)
return SERD_ERR_BAD_SYNTAX;
}
- // subject predicate object
if ((st = read_subject(reader, ctx, &ctx.subject, &s_type)) ||
- !read_ws_star(reader) || (st = read_IRIREF(reader, &ctx.predicate)) ||
- !read_ws_star(reader) ||
+ !read_ws_star(reader)) {
+ return st;
+ }
+
+ switch (peek_byte(reader)) {
+ case '$':
+ case '?':
+ st = read_Var(reader, &ctx.predicate);
+ break;
+ case '<':
+ st = read_IRIREF(reader, &ctx.predicate);
+ break;
+ }
+
+ if (st || !read_ws_star(reader) ||
(st = read_object(reader, &ctx, false, &ate_dot))) {
return st;
}
@@ -1730,6 +1798,9 @@ read_nquadsDoc(SerdReader* const reader)
switch (peek_byte(reader)) {
case '.':
break;
+ case '?':
+ TRY(st, read_Var(reader, &ctx.graph));
+ break;
case '_':
TRY(st, read_BLANK_NODE_LABEL(reader, &ctx.graph, &ate_dot));
break;