Browse Source

Use iterative algorithm for collection parsing.

git-svn-id: http://svn.drobilla.net/serd/trunk@306 490d8e77-9747-427b-9fa3-0b8f29cee8a0
zrythm_meson
David Robillard 11 years ago
parent
commit
8e430f642c
  1. 3
      ChangeLog
  2. 111
      src/reader.c
  3. 1
      tests/test-list-subject.out
  4. 3
      tests/test-list-subject.ttl

3
ChangeLog

@ -24,7 +24,8 @@ serd (UNRELEASED) unstable; urgency=low @@ -24,7 +24,8 @@ serd (UNRELEASED) unstable; urgency=low
* Add serd_node_new_blob and serd_base64_decode for handling arbitrary
binary data via base64 encoding.
* Support compilation as C++ under MSVC++.
* Impement pretty-printing for collections.
* Implement pretty-printing for collections.
* Use iterative algorithm for collection parsing.
-- David Robillard <d@drobilla.net> (UNRELEASED)

111
src/reader.c

@ -601,18 +601,35 @@ read_ws(SerdReader* reader) @@ -601,18 +601,35 @@ read_ws(SerdReader* reader)
}
}
static inline void
static inline bool
read_ws_star(SerdReader* reader)
{
while (read_ws(reader)) {}
return true;
}
static inline bool
read_ws_plus(SerdReader* reader)
{
TRY_RET(read_ws(reader));
return read_ws_star(reader);
}
static inline bool
peek_delim(SerdReader* reader, const char delim)
{
read_ws_star(reader);
return true;
return peek_byte(reader) == delim;
}
static inline bool
eat_delim(SerdReader* reader, const char delim)
{
if (peek_delim(reader, delim)) {
eat_byte_safe(reader, delim);
return read_ws_star(reader);
}
return false;
}
// [37] longString ::= #x22 #x22 #x22 lcharacter* #x22 #x22 #x22
@ -1015,9 +1032,7 @@ read_blank(SerdReader* reader, ReadContext ctx, bool subject, Ref* dest) @@ -1015,9 +1032,7 @@ read_blank(SerdReader* reader, ReadContext ctx, bool subject, Ref* dest)
return true;
case '[':
eat_byte_safe(reader, '[');
read_ws_star(reader);
const bool empty = (peek_byte(reader) == ']');
const bool empty = peek_delim(reader, ']');
if (empty) {
*ctx.flags |= (subject) ? SERD_EMPTY_S : SERD_EMPTY_O;
} else {
@ -1140,12 +1155,8 @@ static bool @@ -1140,12 +1155,8 @@ static bool
read_objectList(SerdReader* reader, ReadContext ctx)
{
TRY_RET(read_object(reader, ctx));
read_ws_star(reader);
while (peek_byte(reader) == ',') {
eat_byte_safe(reader, ',');
read_ws_star(reader);
while (eat_delim(reader, ',')) {
TRY_RET(read_object(reader, ctx));
read_ws_star(reader);
}
return true;
}
@ -1164,10 +1175,7 @@ read_predicateObjectList(SerdReader* reader, ReadContext ctx) @@ -1164,10 +1175,7 @@ read_predicateObjectList(SerdReader* reader, ReadContext ctx)
TRY_THROW(read_objectList(reader, ctx));
pop_node(reader, predicate);
predicate = 0;
read_ws_star(reader);
while (peek_byte(reader) == ';') {
eat_byte_safe(reader, ';');
read_ws_star(reader);
while (eat_delim(reader, ';')) {
switch (peek_byte(reader)) {
case '.': case ']':
return true;
@ -1178,7 +1186,6 @@ read_predicateObjectList(SerdReader* reader, ReadContext ctx) @@ -1178,7 +1186,6 @@ read_predicateObjectList(SerdReader* reader, ReadContext ctx)
TRY_THROW(read_objectList(reader, ctx));
pop_node(reader, predicate);
predicate = 0;
read_ws_star(reader);
}
}
pop_node(reader, predicate);
@ -1188,63 +1195,49 @@ except: @@ -1188,63 +1195,49 @@ except:
return false;
}
/** Recursive helper for read_collection. */
static bool
read_collection_rec(SerdReader* reader, ReadContext ctx)
{
read_ws_star(reader);
const bool end = (peek_byte(reader) == ')');
const Ref rest = (end ? reader->rdf_nil : blank_id(reader));
*ctx.flags |= SERD_LIST_CONT;
TRY_RET(emit_statement(reader, ctx.flags, ctx.graph,
ctx.subject, reader->rdf_rest, rest, 0, 0));
if (end) {
eat_byte_safe(reader, ')');
} else {
ctx.subject = rest;
ctx.predicate = reader->rdf_first;
if (read_object(reader, ctx)) {
TRY_RET(read_collection_rec(reader, ctx));
}
}
*ctx.flags &= ~SERD_LIST_CONT;
return true;
}
// [22] itemList ::= object+
// [23] collection ::= '(' itemList? ')'
static bool
read_collection(SerdReader* reader, ReadContext ctx, Ref* dest)
{
eat_byte_safe(reader, '(');
read_ws_star(reader);
bool end = peek_delim(reader, ')');
*dest = end ? reader->rdf_nil : blank_id(reader);
if (ctx.subject) {
// subject predicate _:head
*ctx.flags |= (end ? 0 : SERD_LIST_O_BEGIN);
TRY_RET(emit_statement(reader, ctx.flags, ctx.graph,
ctx.subject, ctx.predicate, *dest, 0, 0));
*ctx.flags |= SERD_LIST_CONT;
} else {
*ctx.flags |= (end ? 0 : SERD_LIST_S_BEGIN);
}
if (peek_byte(reader) == ')') {
*dest = reader->rdf_nil;
if (ctx.subject) {
TRY_RET(emit_statement(reader, ctx.flags, ctx.graph,
ctx.subject, ctx.predicate, *dest, 0, 0));
ctx.subject = *dest;
while (!end) {
// _:node rdf:first object
ctx.predicate = reader->rdf_first;
if (!read_object(reader, ctx)) {
return error(reader, "unexpected end of collection\n");
}
eat_byte_safe(reader, ')');
return true;
}
*dest = blank_id(reader);
*ctx.flags |= (!ctx.subject) ? SERD_LIST_S_BEGIN : SERD_LIST_O_BEGIN;
end = peek_delim(reader, ')');
if (ctx.subject) {
// _:node rdf:rest _:rest
const Ref rest = end ? reader->rdf_nil : blank_id(reader);
*ctx.flags |= SERD_LIST_CONT;
TRY_RET(emit_statement(reader, ctx.flags, ctx.graph,
ctx.subject, ctx.predicate, *dest, 0, 0));
*ctx.flags = SERD_LIST_CONT;
}
ctx.subject = *dest;
ctx.predicate = reader->rdf_first;
if (!read_object(reader, ctx)) {
return error(reader, "unexpected end of collection\n");
ctx.subject, reader->rdf_rest, rest, 0, 0));
ctx.subject = rest;
*ctx.flags |= SERD_LIST_CONT;
end = peek_delim(reader, ')');
}
return read_collection_rec(reader, ctx);
eat_byte_safe(reader, ')');
*ctx.flags &= ~SERD_LIST_CONT;
return true;
}
// [11] subject ::= resource | blank

1
tests/test-list-subject.out

@ -1,3 +1,4 @@ @@ -1,3 +1,4 @@
<http://www.w3.org/1999/02/22-rdf-syntax-ns#nil> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example.org/List> .
_:genid1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "apple" .
_:genid1 <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> _:genid2 .
_:genid2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "banana" .

3
tests/test-list-subject.ttl

@ -1 +1,2 @@ @@ -1 +1,2 @@
("apple" "banana") a <http://example.org/List> .
() a <http://example.org/List> .
("apple" "banana") a <http://example.org/List> .

Loading…
Cancel
Save