From 9b1139fe7045a0630e87501235af21803860b80c Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 1 Dec 2023 21:59:18 -0500 Subject: [WIP] Add support for reading and writing variables [WIP] Command line option, move later? 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. --- src/read_ntriples.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) (limited to 'src/read_ntriples.c') 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: -- cgit v1.2.1