From 8e430f642ca9189e4af2b96c320586bf8eb0f91e Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 20 Feb 2012 02:33:23 +0000 Subject: Use iterative algorithm for collection parsing. git-svn-id: http://svn.drobilla.net/serd/trunk@306 490d8e77-9747-427b-9fa3-0b8f29cee8a0 --- src/reader.c | 111 ++++++++++++++++++++++++++++------------------------------- 1 file changed, 52 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/reader.c b/src/reader.c index 38d0c21a..e2eda76c 100644 --- a/src/reader.c +++ b/src/reader.c @@ -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) 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 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) 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) 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: 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 -- cgit v1.2.1