Esempio n. 1
0
static bool
read_collection(SerdReader* reader, ReadContext ctx, Ref* dest)
{
	eat_byte_safe(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, *dest, 0, 0));
		*ctx.flags |= SERD_LIST_CONT;
	} else {
		*ctx.flags |= (end ? 0 : SERD_LIST_S_BEGIN);
	}

	if (end) {
		return end_collection(reader, ctx, 0, 0, true);
	}

	/* The order of node allocation here is necessarily not in stack order,
	   so we create two nodes and recycle them throughout. */
	Ref n1   = push_node_padded(reader, genid_size(reader), SERD_BLANK, "", 0);
	Ref n2   = 0;
	Ref node = n1;
	Ref rest = 0;

	ctx.subject = *dest;
	while (!(end = peek_delim(reader, ')'))) {
		// _:node rdf:first object
		ctx.predicate = reader->rdf_first;
		bool ate_dot = false;
		if (!read_object(reader, ctx, &ate_dot) || ate_dot) {
			return end_collection(reader, ctx, n1, n2, false);
		}

		if (!(end = peek_delim(reader, ')'))) {
			/* Give rest a new ID.  Done as late as possible to ensure it is
			   used and > IDs generated by read_object above. */
			if (!rest) {
				rest = n2 = blank_id(reader);  // First pass, push
			} else {
				set_blank_id(reader, rest, genid_size(reader));
			}
		}

		// _:node rdf:rest _:rest
		*ctx.flags |= SERD_LIST_CONT;
		ctx.predicate = reader->rdf_rest;
		TRY_RET(emit_statement(reader, ctx,
		                       (end ? reader->rdf_nil : rest), 0, 0));

		ctx.subject = rest;         // _:node = _:rest
		rest        = node;         // _:rest = (old)_:node
		node        = ctx.subject;  // invariant
	}

	return end_collection(reader, ctx, n1, n2, true);
}
Esempio n. 2
0
static bool
read_blank(SerdReader* reader, ReadContext ctx, bool subject, Ref* dest, bool* ate_dot)
{
	const SerdStatementFlags old_flags = *ctx.flags;
	bool empty;
	switch (peek_byte(reader)) {
	case '_':
		return (*dest = read_BLANK_NODE_LABEL(reader, ate_dot));
	case '[':
		eat_byte_safe(reader, '[');
		if ((empty = peek_delim(reader, ']'))) {
			*ctx.flags |= (subject) ? SERD_EMPTY_S : SERD_EMPTY_O;
		} else {
			*ctx.flags |= (subject) ? SERD_ANON_S_BEGIN : SERD_ANON_O_BEGIN;
			if (peek_delim(reader, '=')) {
				if (!(*dest = read_blankName(reader)) ||
				    !eat_delim(reader, ';')) {
					return false;
				}
			}
		}

		if (!*dest) {
			*dest = blank_id(reader);
		}
		if (ctx.subject) {
			TRY_RET(emit_statement(reader, ctx, *dest, 0, 0));
		}

		ctx.subject = *dest;
		if (!empty) {
			*ctx.flags &= ~(SERD_LIST_CONT);
			if (!subject) {
				*ctx.flags |= SERD_ANON_CONT;
			}
			bool ate_dot_in_list = false;
			read_predicateObjectList(reader, ctx, &ate_dot_in_list);
			if (ate_dot_in_list) {
				return r_err(reader, SERD_ERR_BAD_SYNTAX, "`.' inside blank\n");
			}
			read_ws_star(reader);
			if (reader->end_sink) {
				reader->end_sink(reader->handle, deref(reader, *dest));
			}
			*ctx.flags = old_flags;
		}
		return (eat_byte_check(reader, ']') == ']');
	case '(':
		return read_collection(reader, ctx, dest);
	default: return false;  // never reached
	}
}
Esempio n. 3
0
void
emit_statements (sblock_t *first_sblock)
{
	sblock_t   *sblock;
	statement_t *s;

	for (sblock = first_sblock; sblock; sblock = sblock->next) {
		sblock->offset = pr.code->size;
		for (s = sblock->statements; s; s = s->next)
			emit_statement (s);
	}

	for (sblock = first_sblock; sblock; sblock = sblock->next)
		relocate_refs (sblock->relocs, sblock->offset);
}
Esempio n. 4
0
// Recurses, calling statement_sink for every statement encountered.
// Leaves stack in original calling state (i.e. pops everything it pushes).
static bool
read_object(SerdReader* reader, ReadContext ctx, bool* ate_dot)
{
	static const char* const XSD_BOOLEAN     = NS_XSD "boolean";
	static const size_t      XSD_BOOLEAN_LEN = 40;

#ifndef NDEBUG
	const size_t orig_stack_size = reader->stack.size;
#endif

	bool          ret      = false;
	bool          emit     = (ctx.subject != 0);
	SerdNode*     node     = NULL;
	Ref           o        = 0;
	Ref           datatype = 0;
	Ref           lang     = 0;
	uint32_t      flags    = 0;
	const uint8_t c        = peek_byte(reader);
	switch (c) {
	case '\0':
	case ')':
		return false;
	case '[':
		emit = false;
		TRY_THROW(ret = read_anon(reader, ctx, false, &o));
		break;
	case '(':
		emit = false;
		TRY_THROW(ret = read_collection(reader, ctx, &o));
		break;
	case '_':
		TRY_THROW(ret = (o = read_BLANK_NODE_LABEL(reader, ate_dot)));
		break;
	case '<': case ':':
		TRY_THROW(ret = read_iri(reader, &o, ate_dot));
		break;
	case '+': case '-': case '.': case '0': case '1': case '2': case '3':
	case '4': case '5': case '6': case '7': case '8': case '9':
		TRY_THROW(ret = read_number(reader, &o, &datatype, ate_dot));
		break;
	case '\"':
	case '\'':
		TRY_THROW(ret = read_literal(reader, &o, &datatype, &lang, &flags, ate_dot));
		break;
	default:
		/* Either a boolean literal, or a qname.  Read the prefix first, and if
		   it is in fact a "true" or "false" literal, produce that instead.
		*/
		node = deref(reader, o = push_node(reader, SERD_CURIE, "", 0));
		while (read_PN_CHARS_BASE(reader, o)) {}
		if ((node->n_bytes == 4 && !memcmp(node->buf, "true", 4)) ||
		    (node->n_bytes == 5 && !memcmp(node->buf, "false", 5))) {
			node->type = SERD_LITERAL;
			datatype   = push_node(
				reader, SERD_URI, XSD_BOOLEAN, XSD_BOOLEAN_LEN);
			ret = true;
		} else if (read_PN_PREFIX_tail(reader, o) > SERD_FAILURE) {
			ret = false;
		} else {
			ret = read_PrefixedName(reader, o, false, ate_dot);
		}
	}

	if (ret && emit) {
		deref(reader, o)->flags = flags;
		ret = emit_statement(reader, ctx, o, datatype, lang);
	}

except:
	pop_node(reader, lang);
	pop_node(reader, datatype);
	pop_node(reader, o);
#ifndef NDEBUG
	assert(reader->stack.size == orig_stack_size);
#endif
	return ret;
}