// Copyright 2011-2021 David Robillard // SPDX-License-Identifier: ISC #include "read_nquads.h" #include "caret.h" #include "read_ntriples.h" #include "reader.h" #include "stack.h" #include "statement.h" #include "try.h" #include "serd/caret.h" #include "serd/node.h" #include "serd/sink.h" #include "serd/statement.h" #include #include /// [6] graphLabel static SerdStatus read_graphLabel(SerdReader* const reader, SerdNode** const dest) { return read_nt_subject(reader, dest); // Equivalent rule } /// [2] statement static SerdStatus read_nquads_statement(SerdReader* const reader) { SerdStatementFlags flags = 0; ReadContext ctx = {0, 0, 0, 0, &flags}; SerdStatus st = SERD_SUCCESS; bool ate_dot = false; // Read subject and predicate if ((st = read_nt_subject(reader, &ctx.subject)) || (st = skip_horizontal_whitespace(reader)) || (st = read_nt_predicate(reader, &ctx.predicate)) || (st = skip_horizontal_whitespace(reader))) { return st; } // Preserve the caret for error reporting and read object SerdCaret orig_caret = reader->source.caret; if ((st = read_nt_object(reader, &ctx.object, &ate_dot)) || (st = skip_horizontal_whitespace(reader))) { return st; } if (!ate_dot) { if (peek_byte(reader) == '.') { skip_byte(reader, '.'); } else { TRY(st, read_graphLabel(reader, &ctx.graph)); skip_horizontal_whitespace(reader); TRY(st, eat_byte_check(reader, '.')); } } const SerdStatement statement = { {ctx.subject, ctx.predicate, ctx.object, ctx.graph}, &orig_caret}; return serd_sink_write_statement(reader->sink, *ctx.flags, &statement); } SerdStatus read_nquads_line(SerdReader* const reader) { const size_t orig_stack_size = reader->stack.size; SerdStatus st = SERD_SUCCESS; skip_horizontal_whitespace(reader); switch (peek_byte(reader)) { case EOF: return SERD_FAILURE; case '\n': case '\r': return read_EOL(reader); case '#': return read_comment(reader); default: if (!(st = read_nquads_statement(reader))) { skip_horizontal_whitespace(reader); if (peek_byte(reader) == '#') { st = read_comment(reader); } } break; } serd_stack_pop_to(&reader->stack, orig_stack_size); return (st || peek_byte(reader) == EOF) ? st : read_EOL(reader); } SerdStatus read_nquadsDoc(SerdReader* const reader) { // Read the first line SerdStatus st = read_nquads_line(reader); if (st == SERD_FAILURE || !tolerate_status(reader, st)) { return st; } // Continue reading lines for as long as possible for (st = SERD_SUCCESS; !st;) { st = read_nquads_line(reader); if (st > SERD_FAILURE && !reader->strict && tolerate_status(reader, st)) { serd_reader_skip_until_byte(reader, '\n'); st = SERD_SUCCESS; } } // If we made it this far, we succeeded at reading at least one line return st > SERD_FAILURE ? st : SERD_SUCCESS; }