WIP
This commit is contained in:
93
node_modules/n3/lib/BaseIRI.js
generated
vendored
Normal file
93
node_modules/n3/lib/BaseIRI.js
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _Util = require("./Util");
|
||||
// Do not handle base IRIs without scheme, and currently unsupported cases:
|
||||
// - file: IRIs (which could also use backslashes)
|
||||
// - IRIs containing /. or /.. or //
|
||||
const BASE_UNSUPPORTED = /^:?[^:?#]*(?:[?#]|$)|^file:|^[^:]*:\/*[^?#]+?\/(?:\.\.?(?:\/|$)|\/)/i;
|
||||
const SUFFIX_SUPPORTED = /^(?:(?:[^/?#]{3,}|\.?[^/?#.]\.?)(?:\/[^/?#]{3,}|\.?[^/?#.]\.?)*\/?)?(?:[?#]|$)/;
|
||||
const CURRENT = './';
|
||||
const PARENT = '../';
|
||||
const QUERY = '?';
|
||||
const FRAGMENT = '#';
|
||||
class BaseIRI {
|
||||
constructor(base) {
|
||||
this.base = base;
|
||||
this._baseLength = 0;
|
||||
this._baseMatcher = null;
|
||||
this._pathReplacements = new Array(base.length + 1);
|
||||
}
|
||||
static supports(base) {
|
||||
return !BASE_UNSUPPORTED.test(base);
|
||||
}
|
||||
_getBaseMatcher() {
|
||||
if (this._baseMatcher) return this._baseMatcher;
|
||||
if (!BaseIRI.supports(this.base)) return this._baseMatcher = /.^/;
|
||||
|
||||
// Extract the scheme
|
||||
const scheme = /^[^:]*:\/*/.exec(this.base)[0];
|
||||
const regexHead = ['^', (0, _Util.escapeRegex)(scheme)];
|
||||
const regexTail = [];
|
||||
|
||||
// Generate a regex for every path segment
|
||||
const segments = [],
|
||||
segmenter = /[^/?#]*([/?#])/y;
|
||||
let segment,
|
||||
query = 0,
|
||||
fragment = 0,
|
||||
last = segmenter.lastIndex = scheme.length;
|
||||
while (!query && !fragment && (segment = segmenter.exec(this.base))) {
|
||||
// Truncate base resolution path at fragment start
|
||||
if (segment[1] === FRAGMENT) fragment = segmenter.lastIndex - 1;else {
|
||||
// Create regex that matches the segment
|
||||
regexHead.push((0, _Util.escapeRegex)(segment[0]), '(?:');
|
||||
regexTail.push(')?');
|
||||
|
||||
// Create dedicated query string replacement
|
||||
if (segment[1] !== QUERY) segments.push(last = segmenter.lastIndex);else {
|
||||
query = last = segmenter.lastIndex;
|
||||
fragment = this.base.indexOf(FRAGMENT, query);
|
||||
this._pathReplacements[query] = QUERY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Precalculate parent path substitutions
|
||||
for (let i = 0; i < segments.length; i++) this._pathReplacements[segments[i]] = PARENT.repeat(segments.length - i - 1);
|
||||
this._pathReplacements[segments[segments.length - 1]] = CURRENT;
|
||||
|
||||
// Add the remainder of the base IRI (without fragment) to the regex
|
||||
this._baseLength = fragment > 0 ? fragment : this.base.length;
|
||||
regexHead.push((0, _Util.escapeRegex)(this.base.substring(last, this._baseLength)), query ? '(?:#|$)' : '(?:[?#]|$)');
|
||||
return this._baseMatcher = new RegExp([...regexHead, ...regexTail].join(''));
|
||||
}
|
||||
toRelative(iri) {
|
||||
// Unsupported or non-matching base IRI
|
||||
const match = this._getBaseMatcher().exec(iri);
|
||||
if (!match) return iri;
|
||||
|
||||
// Exact base IRI match
|
||||
const length = match[0].length;
|
||||
if (length === this._baseLength && length === iri.length) return '';
|
||||
|
||||
// Parent path match
|
||||
const parentPath = this._pathReplacements[length];
|
||||
if (parentPath) {
|
||||
const suffix = iri.substring(length);
|
||||
// Don't abbreviate unsupported path
|
||||
if (parentPath !== QUERY && !SUFFIX_SUPPORTED.test(suffix)) return iri;
|
||||
// Omit ./ with fragment or query string
|
||||
if (parentPath === CURRENT && /^[^?#]/.test(suffix)) return suffix;
|
||||
// Append suffix to relative parent path
|
||||
return parentPath + suffix;
|
||||
}
|
||||
|
||||
// Fragment or query string, so include delimiter
|
||||
return iri.substring(length - 1);
|
||||
}
|
||||
}
|
||||
exports.default = BaseIRI;
|
||||
36
node_modules/n3/lib/IRIs.js
generated
vendored
Normal file
36
node_modules/n3/lib/IRIs.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
const RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
|
||||
XSD = 'http://www.w3.org/2001/XMLSchema#',
|
||||
SWAP = 'http://www.w3.org/2000/10/swap/';
|
||||
var _default = exports.default = {
|
||||
xsd: {
|
||||
decimal: `${XSD}decimal`,
|
||||
boolean: `${XSD}boolean`,
|
||||
double: `${XSD}double`,
|
||||
integer: `${XSD}integer`,
|
||||
string: `${XSD}string`
|
||||
},
|
||||
rdf: {
|
||||
type: `${RDF}type`,
|
||||
nil: `${RDF}nil`,
|
||||
first: `${RDF}first`,
|
||||
rest: `${RDF}rest`,
|
||||
langString: `${RDF}langString`
|
||||
},
|
||||
owl: {
|
||||
sameAs: 'http://www.w3.org/2002/07/owl#sameAs'
|
||||
},
|
||||
r: {
|
||||
forSome: `${SWAP}reify#forSome`,
|
||||
forAll: `${SWAP}reify#forAll`
|
||||
},
|
||||
log: {
|
||||
implies: `${SWAP}log#implies`,
|
||||
isImpliedBy: `${SWAP}log#isImpliedBy`
|
||||
}
|
||||
};
|
||||
399
node_modules/n3/lib/N3DataFactory.js
generated
vendored
Normal file
399
node_modules/n3/lib/N3DataFactory.js
generated
vendored
Normal file
@@ -0,0 +1,399 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = exports.Variable = exports.Triple = exports.Term = exports.Quad = exports.NamedNode = exports.Literal = exports.DefaultGraph = exports.BlankNode = void 0;
|
||||
exports.escapeQuotes = escapeQuotes;
|
||||
exports.fromQuad = fromQuad;
|
||||
exports.fromTerm = fromTerm;
|
||||
exports.termFromId = termFromId;
|
||||
exports.termToId = termToId;
|
||||
exports.unescapeQuotes = unescapeQuotes;
|
||||
var _IRIs = _interopRequireDefault(require("./IRIs"));
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
// N3.js implementations of the RDF/JS core data types
|
||||
// See http://rdf.js.org/data-model-spec/
|
||||
|
||||
const {
|
||||
rdf,
|
||||
xsd
|
||||
} = _IRIs.default;
|
||||
|
||||
// eslint-disable-next-line prefer-const
|
||||
let DEFAULTGRAPH;
|
||||
let _blankNodeCounter = 0;
|
||||
const escapedLiteral = /^"(.*".*)(?="[^"]*$)/;
|
||||
|
||||
// ## DataFactory singleton
|
||||
const DataFactory = {
|
||||
namedNode,
|
||||
blankNode,
|
||||
variable,
|
||||
literal,
|
||||
defaultGraph,
|
||||
quad,
|
||||
triple: quad,
|
||||
fromTerm,
|
||||
fromQuad
|
||||
};
|
||||
var _default = exports.default = DataFactory; // ## Term constructor
|
||||
class Term {
|
||||
constructor(id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
// ### The value of this term
|
||||
get value() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
// ### Returns whether this object represents the same term as the other
|
||||
equals(other) {
|
||||
// If both terms were created by this library,
|
||||
// equality can be computed through ids
|
||||
if (other instanceof Term) return this.id === other.id;
|
||||
// Otherwise, compare term type and value
|
||||
return !!other && this.termType === other.termType && this.value === other.value;
|
||||
}
|
||||
|
||||
// ### Implement hashCode for Immutable.js, since we implement `equals`
|
||||
// https://immutable-js.com/docs/v4.0.0/ValueObject/#hashCode()
|
||||
hashCode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ### Returns a plain object representation of this term
|
||||
toJSON() {
|
||||
return {
|
||||
termType: this.termType,
|
||||
value: this.value
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// ## NamedNode constructor
|
||||
exports.Term = Term;
|
||||
class NamedNode extends Term {
|
||||
// ### The term type of this term
|
||||
get termType() {
|
||||
return 'NamedNode';
|
||||
}
|
||||
}
|
||||
|
||||
// ## Literal constructor
|
||||
exports.NamedNode = NamedNode;
|
||||
class Literal extends Term {
|
||||
// ### The term type of this term
|
||||
get termType() {
|
||||
return 'Literal';
|
||||
}
|
||||
|
||||
// ### The text value of this literal
|
||||
get value() {
|
||||
return this.id.substring(1, this.id.lastIndexOf('"'));
|
||||
}
|
||||
|
||||
// ### The language of this literal
|
||||
get language() {
|
||||
// Find the last quotation mark (e.g., '"abc"@en-us')
|
||||
const id = this.id;
|
||||
let atPos = id.lastIndexOf('"') + 1;
|
||||
// If "@" it follows, return the remaining substring; empty otherwise
|
||||
return atPos < id.length && id[atPos++] === '@' ? id.substr(atPos).toLowerCase() : '';
|
||||
}
|
||||
|
||||
// ### The datatype IRI of this literal
|
||||
get datatype() {
|
||||
return new NamedNode(this.datatypeString);
|
||||
}
|
||||
|
||||
// ### The datatype string of this literal
|
||||
get datatypeString() {
|
||||
// Find the last quotation mark (e.g., '"abc"^^http://ex.org/types#t')
|
||||
const id = this.id,
|
||||
dtPos = id.lastIndexOf('"') + 1;
|
||||
const char = dtPos < id.length ? id[dtPos] : '';
|
||||
// If "^" it follows, return the remaining substring
|
||||
return char === '^' ? id.substr(dtPos + 2) :
|
||||
// If "@" follows, return rdf:langString; xsd:string otherwise
|
||||
char !== '@' ? xsd.string : rdf.langString;
|
||||
}
|
||||
|
||||
// ### Returns whether this object represents the same term as the other
|
||||
equals(other) {
|
||||
// If both literals were created by this library,
|
||||
// equality can be computed through ids
|
||||
if (other instanceof Literal) return this.id === other.id;
|
||||
// Otherwise, compare term type, value, language, and datatype
|
||||
return !!other && !!other.datatype && this.termType === other.termType && this.value === other.value && this.language === other.language && this.datatype.value === other.datatype.value;
|
||||
}
|
||||
toJSON() {
|
||||
return {
|
||||
termType: this.termType,
|
||||
value: this.value,
|
||||
language: this.language,
|
||||
datatype: {
|
||||
termType: 'NamedNode',
|
||||
value: this.datatypeString
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// ## BlankNode constructor
|
||||
exports.Literal = Literal;
|
||||
class BlankNode extends Term {
|
||||
constructor(name) {
|
||||
super(`_:${name}`);
|
||||
}
|
||||
|
||||
// ### The term type of this term
|
||||
get termType() {
|
||||
return 'BlankNode';
|
||||
}
|
||||
|
||||
// ### The name of this blank node
|
||||
get value() {
|
||||
return this.id.substr(2);
|
||||
}
|
||||
}
|
||||
exports.BlankNode = BlankNode;
|
||||
class Variable extends Term {
|
||||
constructor(name) {
|
||||
super(`?${name}`);
|
||||
}
|
||||
|
||||
// ### The term type of this term
|
||||
get termType() {
|
||||
return 'Variable';
|
||||
}
|
||||
|
||||
// ### The name of this variable
|
||||
get value() {
|
||||
return this.id.substr(1);
|
||||
}
|
||||
}
|
||||
|
||||
// ## DefaultGraph constructor
|
||||
exports.Variable = Variable;
|
||||
class DefaultGraph extends Term {
|
||||
constructor() {
|
||||
super('');
|
||||
return DEFAULTGRAPH || this;
|
||||
}
|
||||
|
||||
// ### The term type of this term
|
||||
get termType() {
|
||||
return 'DefaultGraph';
|
||||
}
|
||||
|
||||
// ### Returns whether this object represents the same term as the other
|
||||
equals(other) {
|
||||
// If both terms were created by this library,
|
||||
// equality can be computed through strict equality;
|
||||
// otherwise, compare term types.
|
||||
return this === other || !!other && this.termType === other.termType;
|
||||
}
|
||||
}
|
||||
|
||||
// ## DefaultGraph singleton
|
||||
exports.DefaultGraph = DefaultGraph;
|
||||
DEFAULTGRAPH = new DefaultGraph();
|
||||
|
||||
// ### Constructs a term from the given internal string ID
|
||||
// The third 'nested' parameter of this function is to aid
|
||||
// with recursion over nested terms. It should not be used
|
||||
// by consumers of this library.
|
||||
// See https://github.com/rdfjs/N3.js/pull/311#discussion_r1061042725
|
||||
function termFromId(id, factory, nested) {
|
||||
factory = factory || DataFactory;
|
||||
|
||||
// Falsy value or empty string indicate the default graph
|
||||
if (!id) return factory.defaultGraph();
|
||||
|
||||
// Identify the term type based on the first character
|
||||
switch (id[0]) {
|
||||
case '?':
|
||||
return factory.variable(id.substr(1));
|
||||
case '_':
|
||||
return factory.blankNode(id.substr(2));
|
||||
case '"':
|
||||
// Shortcut for internal literals
|
||||
if (factory === DataFactory) return new Literal(id);
|
||||
// Literal without datatype or language
|
||||
if (id[id.length - 1] === '"') return factory.literal(id.substr(1, id.length - 2));
|
||||
// Literal with datatype or language
|
||||
const endPos = id.lastIndexOf('"', id.length - 1);
|
||||
return factory.literal(id.substr(1, endPos - 1), id[endPos + 1] === '@' ? id.substr(endPos + 2) : factory.namedNode(id.substr(endPos + 3)));
|
||||
case '[':
|
||||
id = JSON.parse(id);
|
||||
break;
|
||||
default:
|
||||
if (!nested || !Array.isArray(id)) {
|
||||
return factory.namedNode(id);
|
||||
}
|
||||
}
|
||||
return factory.quad(termFromId(id[0], factory, true), termFromId(id[1], factory, true), termFromId(id[2], factory, true), id[3] && termFromId(id[3], factory, true));
|
||||
}
|
||||
|
||||
// ### Constructs an internal string ID from the given term or ID string
|
||||
// The third 'nested' parameter of this function is to aid
|
||||
// with recursion over nested terms. It should not be used
|
||||
// by consumers of this library.
|
||||
// See https://github.com/rdfjs/N3.js/pull/311#discussion_r1061042725
|
||||
function termToId(term, nested) {
|
||||
if (typeof term === 'string') return term;
|
||||
if (term instanceof Term && term.termType !== 'Quad') return term.id;
|
||||
if (!term) return DEFAULTGRAPH.id;
|
||||
|
||||
// Term instantiated with another library
|
||||
switch (term.termType) {
|
||||
case 'NamedNode':
|
||||
return term.value;
|
||||
case 'BlankNode':
|
||||
return `_:${term.value}`;
|
||||
case 'Variable':
|
||||
return `?${term.value}`;
|
||||
case 'DefaultGraph':
|
||||
return '';
|
||||
case 'Literal':
|
||||
return `"${term.value}"${term.language ? `@${term.language}` : term.datatype && term.datatype.value !== xsd.string ? `^^${term.datatype.value}` : ''}`;
|
||||
case 'Quad':
|
||||
const res = [termToId(term.subject, true), termToId(term.predicate, true), termToId(term.object, true)];
|
||||
if (term.graph && term.graph.termType !== 'DefaultGraph') {
|
||||
res.push(termToId(term.graph, true));
|
||||
}
|
||||
return nested ? res : JSON.stringify(res);
|
||||
default:
|
||||
throw new Error(`Unexpected termType: ${term.termType}`);
|
||||
}
|
||||
}
|
||||
|
||||
// ## Quad constructor
|
||||
class Quad extends Term {
|
||||
constructor(subject, predicate, object, graph) {
|
||||
super('');
|
||||
this._subject = subject;
|
||||
this._predicate = predicate;
|
||||
this._object = object;
|
||||
this._graph = graph || DEFAULTGRAPH;
|
||||
}
|
||||
|
||||
// ### The term type of this term
|
||||
get termType() {
|
||||
return 'Quad';
|
||||
}
|
||||
get subject() {
|
||||
return this._subject;
|
||||
}
|
||||
get predicate() {
|
||||
return this._predicate;
|
||||
}
|
||||
get object() {
|
||||
return this._object;
|
||||
}
|
||||
get graph() {
|
||||
return this._graph;
|
||||
}
|
||||
|
||||
// ### Returns a plain object representation of this quad
|
||||
toJSON() {
|
||||
return {
|
||||
termType: this.termType,
|
||||
subject: this._subject.toJSON(),
|
||||
predicate: this._predicate.toJSON(),
|
||||
object: this._object.toJSON(),
|
||||
graph: this._graph.toJSON()
|
||||
};
|
||||
}
|
||||
|
||||
// ### Returns whether this object represents the same quad as the other
|
||||
equals(other) {
|
||||
return !!other && this._subject.equals(other.subject) && this._predicate.equals(other.predicate) && this._object.equals(other.object) && this._graph.equals(other.graph);
|
||||
}
|
||||
}
|
||||
exports.Triple = exports.Quad = Quad;
|
||||
// ### Escapes the quotes within the given literal
|
||||
function escapeQuotes(id) {
|
||||
return id.replace(escapedLiteral, (_, quoted) => `"${quoted.replace(/"/g, '""')}`);
|
||||
}
|
||||
|
||||
// ### Unescapes the quotes within the given literal
|
||||
function unescapeQuotes(id) {
|
||||
return id.replace(escapedLiteral, (_, quoted) => `"${quoted.replace(/""/g, '"')}`);
|
||||
}
|
||||
|
||||
// ### Creates an IRI
|
||||
function namedNode(iri) {
|
||||
return new NamedNode(iri);
|
||||
}
|
||||
|
||||
// ### Creates a blank node
|
||||
function blankNode(name) {
|
||||
return new BlankNode(name || `n3-${_blankNodeCounter++}`);
|
||||
}
|
||||
|
||||
// ### Creates a literal
|
||||
function literal(value, languageOrDataType) {
|
||||
// Create a language-tagged string
|
||||
if (typeof languageOrDataType === 'string') return new Literal(`"${value}"@${languageOrDataType.toLowerCase()}`);
|
||||
|
||||
// Automatically determine datatype for booleans and numbers
|
||||
let datatype = languageOrDataType ? languageOrDataType.value : '';
|
||||
if (datatype === '') {
|
||||
// Convert a boolean
|
||||
if (typeof value === 'boolean') datatype = xsd.boolean;
|
||||
// Convert an integer or double
|
||||
else if (typeof value === 'number') {
|
||||
if (Number.isFinite(value)) datatype = Number.isInteger(value) ? xsd.integer : xsd.double;else {
|
||||
datatype = xsd.double;
|
||||
if (!Number.isNaN(value)) value = value > 0 ? 'INF' : '-INF';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a datatyped literal
|
||||
return datatype === '' || datatype === xsd.string ? new Literal(`"${value}"`) : new Literal(`"${value}"^^${datatype}`);
|
||||
}
|
||||
|
||||
// ### Creates a variable
|
||||
function variable(name) {
|
||||
return new Variable(name);
|
||||
}
|
||||
|
||||
// ### Returns the default graph
|
||||
function defaultGraph() {
|
||||
return DEFAULTGRAPH;
|
||||
}
|
||||
|
||||
// ### Creates a quad
|
||||
function quad(subject, predicate, object, graph) {
|
||||
return new Quad(subject, predicate, object, graph);
|
||||
}
|
||||
function fromTerm(term) {
|
||||
if (term instanceof Term) return term;
|
||||
|
||||
// Term instantiated with another library
|
||||
switch (term.termType) {
|
||||
case 'NamedNode':
|
||||
return namedNode(term.value);
|
||||
case 'BlankNode':
|
||||
return blankNode(term.value);
|
||||
case 'Variable':
|
||||
return variable(term.value);
|
||||
case 'DefaultGraph':
|
||||
return DEFAULTGRAPH;
|
||||
case 'Literal':
|
||||
return literal(term.value, term.language || term.datatype);
|
||||
case 'Quad':
|
||||
return fromQuad(term);
|
||||
default:
|
||||
throw new Error(`Unexpected termType: ${term.termType}`);
|
||||
}
|
||||
}
|
||||
function fromQuad(inQuad) {
|
||||
if (inQuad instanceof Quad) return inQuad;
|
||||
if (inQuad.termType !== 'Quad') throw new Error(`Unexpected termType: ${inQuad.termType}`);
|
||||
return quad(fromTerm(inQuad.subject), fromTerm(inQuad.predicate), fromTerm(inQuad.object), fromTerm(inQuad.graph));
|
||||
}
|
||||
519
node_modules/n3/lib/N3Lexer.js
generated
vendored
Normal file
519
node_modules/n3/lib/N3Lexer.js
generated
vendored
Normal file
@@ -0,0 +1,519 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _buffer = require("buffer");
|
||||
var _IRIs = _interopRequireDefault(require("./IRIs"));
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
// **N3Lexer** tokenizes N3 documents.
|
||||
|
||||
const {
|
||||
xsd
|
||||
} = _IRIs.default;
|
||||
|
||||
// Regular expression and replacement string to escape N3 strings
|
||||
const escapeSequence = /\\u([a-fA-F0-9]{4})|\\U([a-fA-F0-9]{8})|\\([^])/g;
|
||||
const escapeReplacements = {
|
||||
'\\': '\\',
|
||||
"'": "'",
|
||||
'"': '"',
|
||||
'n': '\n',
|
||||
'r': '\r',
|
||||
't': '\t',
|
||||
'f': '\f',
|
||||
'b': '\b',
|
||||
'_': '_',
|
||||
'~': '~',
|
||||
'.': '.',
|
||||
'-': '-',
|
||||
'!': '!',
|
||||
'$': '$',
|
||||
'&': '&',
|
||||
'(': '(',
|
||||
')': ')',
|
||||
'*': '*',
|
||||
'+': '+',
|
||||
',': ',',
|
||||
';': ';',
|
||||
'=': '=',
|
||||
'/': '/',
|
||||
'?': '?',
|
||||
'#': '#',
|
||||
'@': '@',
|
||||
'%': '%'
|
||||
};
|
||||
const illegalIriChars = /[\x00-\x20<>\\"\{\}\|\^\`]/;
|
||||
const lineModeRegExps = {
|
||||
_iri: true,
|
||||
_unescapedIri: true,
|
||||
_simpleQuotedString: true,
|
||||
_langcode: true,
|
||||
_blank: true,
|
||||
_newline: true,
|
||||
_comment: true,
|
||||
_whitespace: true,
|
||||
_endOfFile: true
|
||||
};
|
||||
const invalidRegExp = /$0^/;
|
||||
|
||||
// ## Constructor
|
||||
class N3Lexer {
|
||||
constructor(options) {
|
||||
// ## Regular expressions
|
||||
// It's slightly faster to have these as properties than as in-scope variables
|
||||
this._iri = /^<((?:[^ <>{}\\]|\\[uU])+)>[ \t]*/; // IRI with escape sequences; needs sanity check after unescaping
|
||||
this._unescapedIri = /^<([^\x00-\x20<>\\"\{\}\|\^\`]*)>[ \t]*/; // IRI without escape sequences; no unescaping
|
||||
this._simpleQuotedString = /^"([^"\\\r\n]*)"(?=[^"])/; // string without escape sequences
|
||||
this._simpleApostropheString = /^'([^'\\\r\n]*)'(?=[^'])/;
|
||||
this._langcode = /^@([a-z]+(?:-[a-z0-9]+)*)(?=[^a-z0-9\-])/i;
|
||||
this._prefix = /^((?:[A-Za-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])(?:\.?[\-0-9A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])*)?:(?=[#\s<])/;
|
||||
this._prefixed = /^((?:[A-Za-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])(?:\.?[\-0-9A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])*)?:((?:(?:[0-:A-Z_a-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~])(?:(?:[\.\-0-:A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~])*(?:[\-0-:A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff]|%[0-9a-fA-F]{2}|\\[!#-\/;=?\-@_~]))?)?)(?:[ \t]+|(?=\.?[,;!\^\s#()\[\]\{\}"'<>]))/;
|
||||
this._variable = /^\?(?:(?:[A-Z_a-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])(?:[\-0-:A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])*)(?=[.,;!\^\s#()\[\]\{\}"'<>])/;
|
||||
this._blank = /^_:((?:[0-9A-Z_a-z\xc0-\xd6\xd8-\xf6\xf8-\u02ff\u0370-\u037d\u037f-\u1fff\u200c\u200d\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])(?:\.?[\-0-9A-Z_a-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u037f-\u1fff\u200c\u200d\u203f\u2040\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff\uf900-\ufdcf\ufdf0-\ufffd]|[\ud800-\udb7f][\udc00-\udfff])*)(?:[ \t]+|(?=\.?[,;:\s#()\[\]\{\}"'<>]))/;
|
||||
this._number = /^[\-+]?(?:(\d+\.\d*|\.?\d+)[eE][\-+]?|\d*(\.)?)\d+(?=\.?[,;:\s#()\[\]\{\}"'<>])/;
|
||||
this._boolean = /^(?:true|false)(?=[.,;\s#()\[\]\{\}"'<>])/;
|
||||
this._keyword = /^@[a-z]+(?=[\s#<:])/i;
|
||||
this._sparqlKeyword = /^(?:PREFIX|BASE|GRAPH)(?=[\s#<])/i;
|
||||
this._shortPredicates = /^a(?=[\s#()\[\]\{\}"'<>])/;
|
||||
this._newline = /^[ \t]*(?:#[^\n\r]*)?(?:\r\n|\n|\r)[ \t]*/;
|
||||
this._comment = /#([^\n\r]*)/;
|
||||
this._whitespace = /^[ \t]+/;
|
||||
this._endOfFile = /^(?:#[^\n\r]*)?$/;
|
||||
options = options || {};
|
||||
|
||||
// Whether the log:isImpliedBy predicate is supported
|
||||
this._isImpliedBy = options.isImpliedBy;
|
||||
|
||||
// In line mode (N-Triples or N-Quads), only simple features may be parsed
|
||||
if (this._lineMode = !!options.lineMode) {
|
||||
this._n3Mode = false;
|
||||
// Don't tokenize special literals
|
||||
for (const key in this) {
|
||||
if (!(key in lineModeRegExps) && this[key] instanceof RegExp) this[key] = invalidRegExp;
|
||||
}
|
||||
}
|
||||
// When not in line mode, enable N3 functionality by default
|
||||
else {
|
||||
this._n3Mode = options.n3 !== false;
|
||||
}
|
||||
// Don't output comment tokens by default
|
||||
this.comments = !!options.comments;
|
||||
// Cache the last tested closing position of long literals
|
||||
this._literalClosingPos = 0;
|
||||
}
|
||||
|
||||
// ## Private methods
|
||||
|
||||
// ### `_tokenizeToEnd` tokenizes as for as possible, emitting tokens through the callback
|
||||
_tokenizeToEnd(callback, inputFinished) {
|
||||
// Continue parsing as far as possible; the loop will return eventually
|
||||
let input = this._input;
|
||||
let currentLineLength = input.length;
|
||||
while (true) {
|
||||
// Count and skip whitespace lines
|
||||
let whiteSpaceMatch, comment;
|
||||
while (whiteSpaceMatch = this._newline.exec(input)) {
|
||||
// Try to find a comment
|
||||
if (this.comments && (comment = this._comment.exec(whiteSpaceMatch[0]))) emitToken('comment', comment[1], '', this._line, whiteSpaceMatch[0].length);
|
||||
// Advance the input
|
||||
input = input.substr(whiteSpaceMatch[0].length, input.length);
|
||||
currentLineLength = input.length;
|
||||
this._line++;
|
||||
}
|
||||
// Skip whitespace on current line
|
||||
if (!whiteSpaceMatch && (whiteSpaceMatch = this._whitespace.exec(input))) input = input.substr(whiteSpaceMatch[0].length, input.length);
|
||||
|
||||
// Stop for now if we're at the end
|
||||
if (this._endOfFile.test(input)) {
|
||||
// If the input is finished, emit EOF
|
||||
if (inputFinished) {
|
||||
// Try to find a final comment
|
||||
if (this.comments && (comment = this._comment.exec(input))) emitToken('comment', comment[1], '', this._line, input.length);
|
||||
input = null;
|
||||
emitToken('eof', '', '', this._line, 0);
|
||||
}
|
||||
return this._input = input;
|
||||
}
|
||||
|
||||
// Look for specific token types based on the first character
|
||||
const line = this._line,
|
||||
firstChar = input[0];
|
||||
let type = '',
|
||||
value = '',
|
||||
prefix = '',
|
||||
match = null,
|
||||
matchLength = 0,
|
||||
inconclusive = false;
|
||||
switch (firstChar) {
|
||||
case '^':
|
||||
// We need at least 3 tokens lookahead to distinguish ^^<IRI> and ^^pre:fixed
|
||||
if (input.length < 3) break;
|
||||
// Try to match a type
|
||||
else if (input[1] === '^') {
|
||||
this._previousMarker = '^^';
|
||||
// Move to type IRI or prefixed name
|
||||
input = input.substr(2);
|
||||
if (input[0] !== '<') {
|
||||
inconclusive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If no type, it must be a path expression
|
||||
else {
|
||||
if (this._n3Mode) {
|
||||
matchLength = 1;
|
||||
type = '^';
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Fall through in case the type is an IRI
|
||||
case '<':
|
||||
// Try to find a full IRI without escape sequences
|
||||
if (match = this._unescapedIri.exec(input)) type = 'IRI', value = match[1];
|
||||
// Try to find a full IRI with escape sequences
|
||||
else if (match = this._iri.exec(input)) {
|
||||
value = this._unescape(match[1]);
|
||||
if (value === null || illegalIriChars.test(value)) return reportSyntaxError(this);
|
||||
type = 'IRI';
|
||||
}
|
||||
// Try to find a nested triple
|
||||
else if (input.length > 1 && input[1] === '<') type = '<<', matchLength = 2;
|
||||
// Try to find a backwards implication arrow
|
||||
else if (this._n3Mode && input.length > 1 && input[1] === '=') {
|
||||
matchLength = 2;
|
||||
if (this._isImpliedBy) type = 'abbreviation', value = '<';else type = 'inverse', value = '>';
|
||||
}
|
||||
break;
|
||||
case '>':
|
||||
if (input.length > 1 && input[1] === '>') type = '>>', matchLength = 2;
|
||||
break;
|
||||
case '_':
|
||||
// Try to find a blank node. Since it can contain (but not end with) a dot,
|
||||
// we always need a non-dot character before deciding it is a blank node.
|
||||
// Therefore, try inserting a space if we're at the end of the input.
|
||||
if ((match = this._blank.exec(input)) || inputFinished && (match = this._blank.exec(`${input} `))) type = 'blank', prefix = '_', value = match[1];
|
||||
break;
|
||||
case '"':
|
||||
// Try to find a literal without escape sequences
|
||||
if (match = this._simpleQuotedString.exec(input)) value = match[1];
|
||||
// Try to find a literal wrapped in three pairs of quotes
|
||||
else {
|
||||
({
|
||||
value,
|
||||
matchLength
|
||||
} = this._parseLiteral(input));
|
||||
if (value === null) return reportSyntaxError(this);
|
||||
}
|
||||
if (match !== null || matchLength !== 0) {
|
||||
type = 'literal';
|
||||
this._literalClosingPos = 0;
|
||||
}
|
||||
break;
|
||||
case "'":
|
||||
if (!this._lineMode) {
|
||||
// Try to find a literal without escape sequences
|
||||
if (match = this._simpleApostropheString.exec(input)) value = match[1];
|
||||
// Try to find a literal wrapped in three pairs of quotes
|
||||
else {
|
||||
({
|
||||
value,
|
||||
matchLength
|
||||
} = this._parseLiteral(input));
|
||||
if (value === null) return reportSyntaxError(this);
|
||||
}
|
||||
if (match !== null || matchLength !== 0) {
|
||||
type = 'literal';
|
||||
this._literalClosingPos = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
// Try to find a variable
|
||||
if (this._n3Mode && (match = this._variable.exec(input))) type = 'var', value = match[0];
|
||||
break;
|
||||
case '@':
|
||||
// Try to find a language code
|
||||
if (this._previousMarker === 'literal' && (match = this._langcode.exec(input))) type = 'langcode', value = match[1];
|
||||
// Try to find a keyword
|
||||
else if (match = this._keyword.exec(input)) type = match[0];
|
||||
break;
|
||||
case '.':
|
||||
// Try to find a dot as punctuation
|
||||
if (input.length === 1 ? inputFinished : input[1] < '0' || input[1] > '9') {
|
||||
type = '.';
|
||||
matchLength = 1;
|
||||
break;
|
||||
}
|
||||
// Fall through to numerical case (could be a decimal dot)
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '+':
|
||||
case '-':
|
||||
// Try to find a number. Since it can contain (but not end with) a dot,
|
||||
// we always need a non-dot character before deciding it is a number.
|
||||
// Therefore, try inserting a space if we're at the end of the input.
|
||||
if (match = this._number.exec(input) || inputFinished && (match = this._number.exec(`${input} `))) {
|
||||
type = 'literal', value = match[0];
|
||||
prefix = typeof match[1] === 'string' ? xsd.double : typeof match[2] === 'string' ? xsd.decimal : xsd.integer;
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
case 'b':
|
||||
case 'p':
|
||||
case 'P':
|
||||
case 'G':
|
||||
case 'g':
|
||||
// Try to find a SPARQL-style keyword
|
||||
if (match = this._sparqlKeyword.exec(input)) type = match[0].toUpperCase();else inconclusive = true;
|
||||
break;
|
||||
case 'f':
|
||||
case 't':
|
||||
// Try to match a boolean
|
||||
if (match = this._boolean.exec(input)) type = 'literal', value = match[0], prefix = xsd.boolean;else inconclusive = true;
|
||||
break;
|
||||
case 'a':
|
||||
// Try to find an abbreviated predicate
|
||||
if (match = this._shortPredicates.exec(input)) type = 'abbreviation', value = 'a';else inconclusive = true;
|
||||
break;
|
||||
case '=':
|
||||
// Try to find an implication arrow or equals sign
|
||||
if (this._n3Mode && input.length > 1) {
|
||||
type = 'abbreviation';
|
||||
if (input[1] !== '>') matchLength = 1, value = '=';else matchLength = 2, value = '>';
|
||||
}
|
||||
break;
|
||||
case '!':
|
||||
if (!this._n3Mode) break;
|
||||
case ',':
|
||||
case ';':
|
||||
case '[':
|
||||
case ']':
|
||||
case '(':
|
||||
case ')':
|
||||
case '}':
|
||||
if (!this._lineMode) {
|
||||
matchLength = 1;
|
||||
type = firstChar;
|
||||
}
|
||||
break;
|
||||
case '{':
|
||||
// We need at least 2 tokens lookahead to distinguish "{|" and "{ "
|
||||
if (!this._lineMode && input.length >= 2) {
|
||||
// Try to find a quoted triple annotation start
|
||||
if (input[1] === '|') type = '{|', matchLength = 2;else type = firstChar, matchLength = 1;
|
||||
}
|
||||
break;
|
||||
case '|':
|
||||
// We need 2 tokens lookahead to parse "|}"
|
||||
// Try to find a quoted triple annotation end
|
||||
if (input.length >= 2 && input[1] === '}') type = '|}', matchLength = 2;
|
||||
break;
|
||||
default:
|
||||
inconclusive = true;
|
||||
}
|
||||
|
||||
// Some first characters do not allow an immediate decision, so inspect more
|
||||
if (inconclusive) {
|
||||
// Try to find a prefix
|
||||
if ((this._previousMarker === '@prefix' || this._previousMarker === 'PREFIX') && (match = this._prefix.exec(input))) type = 'prefix', value = match[1] || '';
|
||||
// Try to find a prefixed name. Since it can contain (but not end with) a dot,
|
||||
// we always need a non-dot character before deciding it is a prefixed name.
|
||||
// Therefore, try inserting a space if we're at the end of the input.
|
||||
else if ((match = this._prefixed.exec(input)) || inputFinished && (match = this._prefixed.exec(`${input} `))) type = 'prefixed', prefix = match[1] || '', value = this._unescape(match[2]);
|
||||
}
|
||||
|
||||
// A type token is special: it can only be emitted after an IRI or prefixed name is read
|
||||
if (this._previousMarker === '^^') {
|
||||
switch (type) {
|
||||
case 'prefixed':
|
||||
type = 'type';
|
||||
break;
|
||||
case 'IRI':
|
||||
type = 'typeIRI';
|
||||
break;
|
||||
default:
|
||||
type = '';
|
||||
}
|
||||
}
|
||||
|
||||
// What if nothing of the above was found?
|
||||
if (!type) {
|
||||
// We could be in streaming mode, and then we just wait for more input to arrive.
|
||||
// Otherwise, a syntax error has occurred in the input.
|
||||
// One exception: error on an unaccounted linebreak (= not inside a triple-quoted literal).
|
||||
if (inputFinished || !/^'''|^"""/.test(input) && /\n|\r/.test(input)) return reportSyntaxError(this);else return this._input = input;
|
||||
}
|
||||
|
||||
// Emit the parsed token
|
||||
const length = matchLength || match[0].length;
|
||||
const token = emitToken(type, value, prefix, line, length);
|
||||
this.previousToken = token;
|
||||
this._previousMarker = type;
|
||||
|
||||
// Advance to next part to tokenize
|
||||
input = input.substr(length, input.length);
|
||||
}
|
||||
|
||||
// Emits the token through the callback
|
||||
function emitToken(type, value, prefix, line, length) {
|
||||
const start = input ? currentLineLength - input.length : currentLineLength;
|
||||
const end = start + length;
|
||||
const token = {
|
||||
type,
|
||||
value,
|
||||
prefix,
|
||||
line,
|
||||
start,
|
||||
end
|
||||
};
|
||||
callback(null, token);
|
||||
return token;
|
||||
}
|
||||
// Signals the syntax error through the callback
|
||||
function reportSyntaxError(self) {
|
||||
callback(self._syntaxError(/^\S*/.exec(input)[0]));
|
||||
}
|
||||
}
|
||||
|
||||
// ### `_unescape` replaces N3 escape codes by their corresponding characters
|
||||
_unescape(item) {
|
||||
let invalid = false;
|
||||
const replaced = item.replace(escapeSequence, (sequence, unicode4, unicode8, escapedChar) => {
|
||||
// 4-digit unicode character
|
||||
if (typeof unicode4 === 'string') return String.fromCharCode(Number.parseInt(unicode4, 16));
|
||||
// 8-digit unicode character
|
||||
if (typeof unicode8 === 'string') {
|
||||
let charCode = Number.parseInt(unicode8, 16);
|
||||
return charCode <= 0xFFFF ? String.fromCharCode(Number.parseInt(unicode8, 16)) : String.fromCharCode(0xD800 + ((charCode -= 0x10000) >> 10), 0xDC00 + (charCode & 0x3FF));
|
||||
}
|
||||
// fixed escape sequence
|
||||
if (escapedChar in escapeReplacements) return escapeReplacements[escapedChar];
|
||||
// invalid escape sequence
|
||||
invalid = true;
|
||||
return '';
|
||||
});
|
||||
return invalid ? null : replaced;
|
||||
}
|
||||
|
||||
// ### `_parseLiteral` parses a literal into an unescaped value
|
||||
_parseLiteral(input) {
|
||||
// Ensure we have enough lookahead to identify triple-quoted strings
|
||||
if (input.length >= 3) {
|
||||
// Identify the opening quote(s)
|
||||
const opening = input.match(/^(?:"""|"|'''|'|)/)[0];
|
||||
const openingLength = opening.length;
|
||||
|
||||
// Find the next candidate closing quotes
|
||||
let closingPos = Math.max(this._literalClosingPos, openingLength);
|
||||
while ((closingPos = input.indexOf(opening, closingPos)) > 0) {
|
||||
// Count backslashes right before the closing quotes
|
||||
let backslashCount = 0;
|
||||
while (input[closingPos - backslashCount - 1] === '\\') backslashCount++;
|
||||
|
||||
// An even number of backslashes (in particular 0)
|
||||
// means these are actual, non-escaped closing quotes
|
||||
if (backslashCount % 2 === 0) {
|
||||
// Extract and unescape the value
|
||||
const raw = input.substring(openingLength, closingPos);
|
||||
const lines = raw.split(/\r\n|\r|\n/).length - 1;
|
||||
const matchLength = closingPos + openingLength;
|
||||
// Only triple-quoted strings can be multi-line
|
||||
if (openingLength === 1 && lines !== 0 || openingLength === 3 && this._lineMode) break;
|
||||
this._line += lines;
|
||||
return {
|
||||
value: this._unescape(raw),
|
||||
matchLength
|
||||
};
|
||||
}
|
||||
closingPos++;
|
||||
}
|
||||
this._literalClosingPos = input.length - openingLength + 1;
|
||||
}
|
||||
return {
|
||||
value: '',
|
||||
matchLength: 0
|
||||
};
|
||||
}
|
||||
|
||||
// ### `_syntaxError` creates a syntax error for the given issue
|
||||
_syntaxError(issue) {
|
||||
this._input = null;
|
||||
const err = new Error(`Unexpected "${issue}" on line ${this._line}.`);
|
||||
err.context = {
|
||||
token: undefined,
|
||||
line: this._line,
|
||||
previousToken: this.previousToken
|
||||
};
|
||||
return err;
|
||||
}
|
||||
|
||||
// ### Strips off any starting UTF BOM mark.
|
||||
_readStartingBom(input) {
|
||||
return input.startsWith('\ufeff') ? input.substr(1) : input;
|
||||
}
|
||||
|
||||
// ## Public methods
|
||||
|
||||
// ### `tokenize` starts the transformation of an N3 document into an array of tokens.
|
||||
// The input can be a string or a stream.
|
||||
tokenize(input, callback) {
|
||||
this._line = 1;
|
||||
|
||||
// If the input is a string, continuously emit tokens through the callback until the end
|
||||
if (typeof input === 'string') {
|
||||
this._input = this._readStartingBom(input);
|
||||
// If a callback was passed, asynchronously call it
|
||||
if (typeof callback === 'function') queueMicrotask(() => this._tokenizeToEnd(callback, true));
|
||||
// If no callback was passed, tokenize synchronously and return
|
||||
else {
|
||||
const tokens = [];
|
||||
let error;
|
||||
this._tokenizeToEnd((e, t) => e ? error = e : tokens.push(t), true);
|
||||
if (error) throw error;
|
||||
return tokens;
|
||||
}
|
||||
}
|
||||
// Otherwise, the input must be a stream
|
||||
else {
|
||||
this._pendingBuffer = null;
|
||||
if (typeof input.setEncoding === 'function') input.setEncoding('utf8');
|
||||
// Adds the data chunk to the buffer and parses as far as possible
|
||||
input.on('data', data => {
|
||||
if (this._input !== null && data.length !== 0) {
|
||||
// Prepend any previous pending writes
|
||||
if (this._pendingBuffer) {
|
||||
data = _buffer.Buffer.concat([this._pendingBuffer, data]);
|
||||
this._pendingBuffer = null;
|
||||
}
|
||||
// Hold if the buffer ends in an incomplete unicode sequence
|
||||
if (data[data.length - 1] & 0x80) {
|
||||
this._pendingBuffer = data;
|
||||
}
|
||||
// Otherwise, tokenize as far as possible
|
||||
else {
|
||||
// Only read a BOM at the start
|
||||
if (typeof this._input === 'undefined') this._input = this._readStartingBom(typeof data === 'string' ? data : data.toString());else this._input += data;
|
||||
this._tokenizeToEnd(callback, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
// Parses until the end
|
||||
input.on('end', () => {
|
||||
if (typeof this._input === 'string') this._tokenizeToEnd(callback, true);
|
||||
});
|
||||
input.on('error', callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.default = N3Lexer;
|
||||
1030
node_modules/n3/lib/N3Parser.js
generated
vendored
Normal file
1030
node_modules/n3/lib/N3Parser.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
226
node_modules/n3/lib/N3Reasoner.js
generated
vendored
Normal file
226
node_modules/n3/lib/N3Reasoner.js
generated
vendored
Normal file
@@ -0,0 +1,226 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
exports.getRulesFromDataset = getRulesFromDataset;
|
||||
var _N3DataFactory = _interopRequireDefault(require("./N3DataFactory"));
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* Gets rules from a dataset. This will only collect horn rules declared using log:implies.
|
||||
*/
|
||||
function getRulesFromDataset(dataset) {
|
||||
const rules = [];
|
||||
for (const {
|
||||
subject,
|
||||
object
|
||||
} of dataset.match(null, _N3DataFactory.default.namedNode('http://www.w3.org/2000/10/swap/log#implies'), null, _N3DataFactory.default.defaultGraph())) {
|
||||
const premise = [...dataset.match(null, null, null, subject)];
|
||||
const conclusion = [...dataset.match(null, null, null, object)];
|
||||
rules.push({
|
||||
premise,
|
||||
conclusion
|
||||
});
|
||||
}
|
||||
return rules;
|
||||
}
|
||||
class N3Reasoner {
|
||||
constructor(store) {
|
||||
this._store = store;
|
||||
}
|
||||
_add(subject, predicate, object, graphItem, cb) {
|
||||
// Only add to the remaining indexes if there is not already a value in the index
|
||||
if (!this._store._addToIndex(graphItem.subjects, subject, predicate, object)) return;
|
||||
this._store._addToIndex(graphItem.predicates, predicate, object, subject);
|
||||
this._store._addToIndex(graphItem.objects, object, subject, predicate);
|
||||
cb();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-warning-comments
|
||||
_evaluatePremise(rule, content, cb, i = 0) {
|
||||
let v1, v2, value, index1, index2;
|
||||
const [val0, val1, val2] = rule.premise[i].value,
|
||||
index = content[rule.premise[i].content];
|
||||
const v0 = !(value = val0.value);
|
||||
for (value in v0 ? index : {
|
||||
[value]: index[value]
|
||||
}) {
|
||||
if (index1 = index[value]) {
|
||||
if (v0) val0.value = Number(value);
|
||||
v1 = !(value = val1.value);
|
||||
for (value in v1 ? index1 : {
|
||||
[value]: index1[value]
|
||||
}) {
|
||||
if (index2 = index1[value]) {
|
||||
if (v1) val1.value = Number(value);
|
||||
v2 = !(value = val2.value);
|
||||
for (value in v2 ? index2 : {
|
||||
[value]: index2[value]
|
||||
}) {
|
||||
if (v2) val2.value = Number(value);
|
||||
if (i === rule.premise.length - 1) rule.conclusion.forEach(c => {
|
||||
// eslint-disable-next-line max-nested-callbacks
|
||||
this._add(c.subject.value, c.predicate.value, c.object.value, content, () => {
|
||||
cb(c);
|
||||
});
|
||||
});else this._evaluatePremise(rule, content, cb, i + 1);
|
||||
}
|
||||
if (v2) val2.value = null;
|
||||
}
|
||||
}
|
||||
if (v1) val1.value = null;
|
||||
}
|
||||
}
|
||||
if (v0) val0.value = null;
|
||||
}
|
||||
_evaluateRules(rules, content, cb) {
|
||||
for (let i = 0; i < rules.length; i++) {
|
||||
this._evaluatePremise(rules[i], content, cb);
|
||||
}
|
||||
}
|
||||
|
||||
// A naive reasoning algorithm where rules are just applied by repeatedly applying rules
|
||||
// until no more evaluations are made
|
||||
_reasonGraphNaive(rules, content) {
|
||||
const newRules = [];
|
||||
function addRule(conclusion) {
|
||||
if (conclusion.next) conclusion.next.forEach(rule => {
|
||||
newRules.push([conclusion.subject.value, conclusion.predicate.value, conclusion.object.value, rule]);
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line func-style
|
||||
const addConclusions = conclusion => {
|
||||
conclusion.forEach(c => {
|
||||
// eslint-disable-next-line max-nested-callbacks
|
||||
this._add(c.subject.value, c.predicate.value, c.object.value, content, () => {
|
||||
addRule(c);
|
||||
});
|
||||
});
|
||||
};
|
||||
this._evaluateRules(rules, content, addRule);
|
||||
let r;
|
||||
while ((r = newRules.pop()) !== undefined) {
|
||||
const [subject, predicate, object, rule] = r;
|
||||
const v1 = rule.basePremise.subject.value;
|
||||
if (!v1) rule.basePremise.subject.value = subject;
|
||||
const v2 = rule.basePremise.predicate.value;
|
||||
if (!v2) rule.basePremise.predicate.value = predicate;
|
||||
const v3 = rule.basePremise.object.value;
|
||||
if (!v3) rule.basePremise.object.value = object;
|
||||
if (rule.premise.length === 0) {
|
||||
addConclusions(rule.conclusion);
|
||||
} else {
|
||||
this._evaluatePremise(rule, content, addRule);
|
||||
}
|
||||
if (!v1) rule.basePremise.subject.value = null;
|
||||
if (!v2) rule.basePremise.predicate.value = null;
|
||||
if (!v3) rule.basePremise.object.value = null;
|
||||
}
|
||||
}
|
||||
_createRule({
|
||||
premise,
|
||||
conclusion
|
||||
}) {
|
||||
const varMapping = {};
|
||||
const toId = value => value.termType === 'Variable' ?
|
||||
// If the term is a variable, then create an empty object that values can be placed into
|
||||
varMapping[value.value] = varMapping[value.value] || {} :
|
||||
// If the term is not a variable, then set the ID value
|
||||
{
|
||||
value: this._store._termToNewNumericId(value)
|
||||
};
|
||||
|
||||
// eslint-disable-next-line func-style
|
||||
const t = term => ({
|
||||
subject: toId(term.subject),
|
||||
predicate: toId(term.predicate),
|
||||
object: toId(term.object)
|
||||
});
|
||||
return {
|
||||
premise: premise.map(p => t(p)),
|
||||
conclusion: conclusion.map(p => t(p)),
|
||||
variables: Object.values(varMapping)
|
||||
};
|
||||
}
|
||||
reason(rules) {
|
||||
if (!Array.isArray(rules)) {
|
||||
rules = getRulesFromDataset(rules);
|
||||
}
|
||||
rules = rules.map(rule => this._createRule(rule));
|
||||
for (const r1 of rules) {
|
||||
for (const r2 of rules) {
|
||||
for (let i = 0; i < r2.premise.length; i++) {
|
||||
const p = r2.premise[i];
|
||||
for (const c of r1.conclusion) {
|
||||
if (termEq(p.subject, c.subject) && termEq(p.predicate, c.predicate) && termEq(p.object, c.object)) {
|
||||
const set = new Set();
|
||||
const premise = [];
|
||||
|
||||
// Since these *will* be substituted when we apply the rule,
|
||||
// we need to do this, so that we index correctly in the subsequent section
|
||||
p.subject.value = p.subject.value || 1;
|
||||
p.object.value = p.object.value || 1;
|
||||
p.predicate.value = p.predicate.value || 1;
|
||||
for (let j = 0; j < r2.premise.length; j++) {
|
||||
if (j !== i) {
|
||||
premise.push(getIndex(r2.premise[j], set));
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-warning-comments
|
||||
// TODO: Create new rule, with new indexing
|
||||
// Future, 'collapse' the next statements when they share a premise/base-premise
|
||||
(c.next = c.next || []).push({
|
||||
premise,
|
||||
conclusion: r2.conclusion,
|
||||
// This is a single premise of the form { subject, predicate, object },
|
||||
// which we can use to instantiate the rule using the new data that was emitted
|
||||
basePremise: p
|
||||
});
|
||||
}
|
||||
r2.variables.forEach(v => {
|
||||
v.value = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const rule of rules) {
|
||||
const set = new Set();
|
||||
rule.premise = rule.premise.map(p => getIndex(p, set));
|
||||
}
|
||||
const graphs = this._store._getGraphs();
|
||||
for (const graphId in graphs) {
|
||||
this._reasonGraphNaive(rules, graphs[graphId]);
|
||||
}
|
||||
this._store._size = null;
|
||||
}
|
||||
}
|
||||
exports.default = N3Reasoner;
|
||||
function getIndex({
|
||||
subject,
|
||||
predicate,
|
||||
object
|
||||
}, set) {
|
||||
const s = subject.value || set.has(subject) || (set.add(subject), false);
|
||||
const p = predicate.value || set.has(predicate) || (set.add(predicate), false);
|
||||
const o = object.value || set.has(object) || (set.add(object), false);
|
||||
return !s && p ? {
|
||||
content: 'predicates',
|
||||
value: [predicate, object, subject]
|
||||
} : o ? {
|
||||
content: 'objects',
|
||||
value: [object, subject, predicate]
|
||||
} : {
|
||||
content: 'subjects',
|
||||
value: [subject, predicate, object]
|
||||
};
|
||||
}
|
||||
function termEq(t1, t2) {
|
||||
if (t1.value === null) {
|
||||
t1.value = t2.value;
|
||||
}
|
||||
return t1.value === t2.value;
|
||||
}
|
||||
1199
node_modules/n3/lib/N3Store.js
generated
vendored
Normal file
1199
node_modules/n3/lib/N3Store.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
14
node_modules/n3/lib/N3StoreFactory.js
generated
vendored
Normal file
14
node_modules/n3/lib/N3StoreFactory.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _N3Store = _interopRequireDefault(require("./N3Store"));
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
class N3DatasetCoreFactory {
|
||||
dataset(quads) {
|
||||
return new _N3Store.default(quads);
|
||||
}
|
||||
}
|
||||
exports.default = N3DatasetCoreFactory;
|
||||
74
node_modules/n3/lib/N3StreamParser.js
generated
vendored
Normal file
74
node_modules/n3/lib/N3StreamParser.js
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _readableStream = require("readable-stream");
|
||||
var _N3Parser = _interopRequireDefault(require("./N3Parser"));
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
// **N3StreamParser** parses a text stream into a quad stream.
|
||||
|
||||
// ## Constructor
|
||||
class N3StreamParser extends _readableStream.Transform {
|
||||
constructor(options) {
|
||||
super({
|
||||
decodeStrings: true
|
||||
});
|
||||
this._readableState.objectMode = true;
|
||||
|
||||
// Set up parser with dummy stream to obtain `data` and `end` callbacks
|
||||
const parser = new _N3Parser.default(options);
|
||||
let onData, onEnd;
|
||||
const callbacks = {
|
||||
// Handle quads by pushing them down the pipeline
|
||||
onQuad: (error, quad) => {
|
||||
error && this.emit('error', error) || quad && this.push(quad);
|
||||
},
|
||||
// Emit prefixes through the `prefix` event
|
||||
onPrefix: (prefix, uri) => {
|
||||
this.emit('prefix', prefix, uri);
|
||||
}
|
||||
};
|
||||
if (options && options.comments) callbacks.onComment = comment => {
|
||||
this.emit('comment', comment);
|
||||
};
|
||||
parser.parse({
|
||||
on: (event, callback) => {
|
||||
switch (event) {
|
||||
case 'data':
|
||||
onData = callback;
|
||||
break;
|
||||
case 'end':
|
||||
onEnd = callback;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, callbacks);
|
||||
|
||||
// Implement Transform methods through parser callbacks
|
||||
this._transform = (chunk, encoding, done) => {
|
||||
onData(chunk);
|
||||
done();
|
||||
};
|
||||
this._flush = done => {
|
||||
onEnd();
|
||||
done();
|
||||
};
|
||||
}
|
||||
|
||||
// ### Parses a stream of strings
|
||||
import(stream) {
|
||||
stream.on('data', chunk => {
|
||||
this.write(chunk);
|
||||
});
|
||||
stream.on('end', () => {
|
||||
this.end();
|
||||
});
|
||||
stream.on('error', error => {
|
||||
this.emit('error', error);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
}
|
||||
exports.default = N3StreamParser;
|
||||
58
node_modules/n3/lib/N3StreamWriter.js
generated
vendored
Normal file
58
node_modules/n3/lib/N3StreamWriter.js
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _readableStream = require("readable-stream");
|
||||
var _N3Writer = _interopRequireDefault(require("./N3Writer"));
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
// **N3StreamWriter** serializes a quad stream into a text stream.
|
||||
|
||||
// ## Constructor
|
||||
class N3StreamWriter extends _readableStream.Transform {
|
||||
constructor(options) {
|
||||
super({
|
||||
encoding: 'utf8',
|
||||
writableObjectMode: true
|
||||
});
|
||||
|
||||
// Set up writer with a dummy stream object
|
||||
const writer = this._writer = new _N3Writer.default({
|
||||
write: (quad, encoding, callback) => {
|
||||
this.push(quad);
|
||||
callback && callback();
|
||||
},
|
||||
end: callback => {
|
||||
this.push(null);
|
||||
callback && callback();
|
||||
}
|
||||
}, options);
|
||||
|
||||
// Implement Transform methods on top of writer
|
||||
this._transform = (quad, encoding, done) => {
|
||||
writer.addQuad(quad, done);
|
||||
};
|
||||
this._flush = done => {
|
||||
writer.end(done);
|
||||
};
|
||||
}
|
||||
|
||||
// ### Serializes a stream of quads
|
||||
import(stream) {
|
||||
stream.on('data', quad => {
|
||||
this.write(quad);
|
||||
});
|
||||
stream.on('end', () => {
|
||||
this.end();
|
||||
});
|
||||
stream.on('error', error => {
|
||||
this.emit('error', error);
|
||||
});
|
||||
stream.on('prefix', (prefix, iri) => {
|
||||
this._writer.addPrefix(prefix, iri);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
}
|
||||
exports.default = N3StreamWriter;
|
||||
85
node_modules/n3/lib/N3Util.js
generated
vendored
Normal file
85
node_modules/n3/lib/N3Util.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.inDefaultGraph = inDefaultGraph;
|
||||
exports.isBlankNode = isBlankNode;
|
||||
exports.isDefaultGraph = isDefaultGraph;
|
||||
exports.isLiteral = isLiteral;
|
||||
exports.isNamedNode = isNamedNode;
|
||||
exports.isQuad = isQuad;
|
||||
exports.isVariable = isVariable;
|
||||
exports.prefix = prefix;
|
||||
exports.prefixes = prefixes;
|
||||
var _N3DataFactory = _interopRequireDefault(require("./N3DataFactory"));
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
// **N3Util** provides N3 utility functions.
|
||||
|
||||
// Tests whether the given term represents an IRI
|
||||
function isNamedNode(term) {
|
||||
return !!term && term.termType === 'NamedNode';
|
||||
}
|
||||
|
||||
// Tests whether the given term represents a blank node
|
||||
function isBlankNode(term) {
|
||||
return !!term && term.termType === 'BlankNode';
|
||||
}
|
||||
|
||||
// Tests whether the given term represents a literal
|
||||
function isLiteral(term) {
|
||||
return !!term && term.termType === 'Literal';
|
||||
}
|
||||
|
||||
// Tests whether the given term represents a variable
|
||||
function isVariable(term) {
|
||||
return !!term && term.termType === 'Variable';
|
||||
}
|
||||
|
||||
// Tests whether the given term represents a quad
|
||||
function isQuad(term) {
|
||||
return !!term && term.termType === 'Quad';
|
||||
}
|
||||
|
||||
// Tests whether the given term represents the default graph
|
||||
function isDefaultGraph(term) {
|
||||
return !!term && term.termType === 'DefaultGraph';
|
||||
}
|
||||
|
||||
// Tests whether the given quad is in the default graph
|
||||
function inDefaultGraph(quad) {
|
||||
return isDefaultGraph(quad.graph);
|
||||
}
|
||||
|
||||
// Creates a function that prepends the given IRI to a local name
|
||||
function prefix(iri, factory) {
|
||||
return prefixes({
|
||||
'': iri.value || iri
|
||||
}, factory)('');
|
||||
}
|
||||
|
||||
// Creates a function that allows registering and expanding prefixes
|
||||
function prefixes(defaultPrefixes, factory) {
|
||||
// Add all of the default prefixes
|
||||
const prefixes = Object.create(null);
|
||||
for (const prefix in defaultPrefixes) processPrefix(prefix, defaultPrefixes[prefix]);
|
||||
// Set the default factory if none was specified
|
||||
factory = factory || _N3DataFactory.default;
|
||||
|
||||
// Registers a new prefix (if an IRI was specified)
|
||||
// or retrieves a function that expands an existing prefix (if no IRI was specified)
|
||||
function processPrefix(prefix, iri) {
|
||||
// Create a new prefix if an IRI is specified or the prefix doesn't exist
|
||||
if (typeof iri === 'string') {
|
||||
// Create a function that expands the prefix
|
||||
const cache = Object.create(null);
|
||||
prefixes[prefix] = local => {
|
||||
return cache[local] || (cache[local] = factory.namedNode(iri + local));
|
||||
};
|
||||
} else if (!(prefix in prefixes)) {
|
||||
throw new Error(`Unknown prefix: ${prefix}`);
|
||||
}
|
||||
return prefixes[prefix];
|
||||
}
|
||||
return processPrefix;
|
||||
}
|
||||
384
node_modules/n3/lib/N3Writer.js
generated
vendored
Normal file
384
node_modules/n3/lib/N3Writer.js
generated
vendored
Normal file
@@ -0,0 +1,384 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _IRIs = _interopRequireDefault(require("./IRIs"));
|
||||
var _N3DataFactory = _interopRequireWildcard(require("./N3DataFactory"));
|
||||
var _N3Util = require("./N3Util");
|
||||
var _BaseIRI = _interopRequireDefault(require("./BaseIRI"));
|
||||
var _Util = require("./Util");
|
||||
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
// **N3Writer** writes N3 documents.
|
||||
|
||||
const DEFAULTGRAPH = _N3DataFactory.default.defaultGraph();
|
||||
const {
|
||||
rdf,
|
||||
xsd
|
||||
} = _IRIs.default;
|
||||
|
||||
// Characters in literals that require escaping
|
||||
const escape = /["\\\t\n\r\b\f\u0000-\u0019\ud800-\udbff]/,
|
||||
escapeAll = /["\\\t\n\r\b\f\u0000-\u0019]|[\ud800-\udbff][\udc00-\udfff]/g,
|
||||
escapedCharacters = {
|
||||
'\\': '\\\\',
|
||||
'"': '\\"',
|
||||
'\t': '\\t',
|
||||
'\n': '\\n',
|
||||
'\r': '\\r',
|
||||
'\b': '\\b',
|
||||
'\f': '\\f'
|
||||
};
|
||||
|
||||
// ## Placeholder class to represent already pretty-printed terms
|
||||
class SerializedTerm extends _N3DataFactory.Term {
|
||||
// Pretty-printed nodes are not equal to any other node
|
||||
// (e.g., [] does not equal [])
|
||||
equals(other) {
|
||||
return other === this;
|
||||
}
|
||||
}
|
||||
|
||||
// ## Constructor
|
||||
class N3Writer {
|
||||
constructor(outputStream, options) {
|
||||
// ### `_prefixRegex` matches a prefixed name or IRI that begins with one of the added prefixes
|
||||
this._prefixRegex = /$0^/;
|
||||
|
||||
// Shift arguments if the first argument is not a stream
|
||||
if (outputStream && typeof outputStream.write !== 'function') options = outputStream, outputStream = null;
|
||||
options = options || {};
|
||||
this._lists = options.lists;
|
||||
|
||||
// If no output stream given, send the output as string through the end callback
|
||||
if (!outputStream) {
|
||||
let output = '';
|
||||
this._outputStream = {
|
||||
write(chunk, encoding, done) {
|
||||
output += chunk;
|
||||
done && done();
|
||||
},
|
||||
end: done => {
|
||||
done && done(null, output);
|
||||
}
|
||||
};
|
||||
this._endStream = true;
|
||||
} else {
|
||||
this._outputStream = outputStream;
|
||||
this._endStream = options.end === undefined ? true : !!options.end;
|
||||
}
|
||||
|
||||
// Initialize writer, depending on the format
|
||||
this._subject = null;
|
||||
if (!/triple|quad/i.test(options.format)) {
|
||||
this._lineMode = false;
|
||||
this._graph = DEFAULTGRAPH;
|
||||
this._prefixIRIs = Object.create(null);
|
||||
options.prefixes && this.addPrefixes(options.prefixes);
|
||||
if (options.baseIRI) {
|
||||
this._baseIri = new _BaseIRI.default(options.baseIRI);
|
||||
}
|
||||
} else {
|
||||
this._lineMode = true;
|
||||
this._writeQuad = this._writeQuadLine;
|
||||
}
|
||||
}
|
||||
|
||||
// ## Private methods
|
||||
|
||||
// ### Whether the current graph is the default graph
|
||||
get _inDefaultGraph() {
|
||||
return DEFAULTGRAPH.equals(this._graph);
|
||||
}
|
||||
|
||||
// ### `_write` writes the argument to the output stream
|
||||
_write(string, callback) {
|
||||
this._outputStream.write(string, 'utf8', callback);
|
||||
}
|
||||
|
||||
// ### `_writeQuad` writes the quad to the output stream
|
||||
_writeQuad(subject, predicate, object, graph, done) {
|
||||
try {
|
||||
// Write the graph's label if it has changed
|
||||
if (!graph.equals(this._graph)) {
|
||||
// Close the previous graph and start the new one
|
||||
this._write((this._subject === null ? '' : this._inDefaultGraph ? '.\n' : '\n}\n') + (DEFAULTGRAPH.equals(graph) ? '' : `${this._encodeIriOrBlank(graph)} {\n`));
|
||||
this._graph = graph;
|
||||
this._subject = null;
|
||||
}
|
||||
// Don't repeat the subject if it's the same
|
||||
if (subject.equals(this._subject)) {
|
||||
// Don't repeat the predicate if it's the same
|
||||
if (predicate.equals(this._predicate)) this._write(`, ${this._encodeObject(object)}`, done);
|
||||
// Same subject, different predicate
|
||||
else this._write(`;\n ${this._encodePredicate(this._predicate = predicate)} ${this._encodeObject(object)}`, done);
|
||||
}
|
||||
// Different subject; write the whole quad
|
||||
else this._write(`${(this._subject === null ? '' : '.\n') + this._encodeSubject(this._subject = subject)} ${this._encodePredicate(this._predicate = predicate)} ${this._encodeObject(object)}`, done);
|
||||
} catch (error) {
|
||||
done && done(error);
|
||||
}
|
||||
}
|
||||
|
||||
// ### `_writeQuadLine` writes the quad to the output stream as a single line
|
||||
_writeQuadLine(subject, predicate, object, graph, done) {
|
||||
// Write the quad without prefixes
|
||||
delete this._prefixMatch;
|
||||
this._write(this.quadToString(subject, predicate, object, graph), done);
|
||||
}
|
||||
|
||||
// ### `quadToString` serializes a quad as a string
|
||||
quadToString(subject, predicate, object, graph) {
|
||||
return `${this._encodeSubject(subject)} ${this._encodeIriOrBlank(predicate)} ${this._encodeObject(object)}${graph && graph.value ? ` ${this._encodeIriOrBlank(graph)} .\n` : ' .\n'}`;
|
||||
}
|
||||
|
||||
// ### `quadsToString` serializes an array of quads as a string
|
||||
quadsToString(quads) {
|
||||
let quadsString = '';
|
||||
for (const quad of quads) quadsString += this.quadToString(quad.subject, quad.predicate, quad.object, quad.graph);
|
||||
return quadsString;
|
||||
}
|
||||
|
||||
// ### `_encodeSubject` represents a subject
|
||||
_encodeSubject(entity) {
|
||||
return entity.termType === 'Quad' ? this._encodeQuad(entity) : this._encodeIriOrBlank(entity);
|
||||
}
|
||||
|
||||
// ### `_encodeIriOrBlank` represents an IRI or blank node
|
||||
_encodeIriOrBlank(entity) {
|
||||
// A blank node or list is represented as-is
|
||||
if (entity.termType !== 'NamedNode') {
|
||||
// If it is a list head, pretty-print it
|
||||
if (this._lists && entity.value in this._lists) entity = this.list(this._lists[entity.value]);
|
||||
return 'id' in entity ? entity.id : `_:${entity.value}`;
|
||||
}
|
||||
let iri = entity.value;
|
||||
// Use relative IRIs if requested and possible
|
||||
if (this._baseIri) {
|
||||
iri = this._baseIri.toRelative(iri);
|
||||
}
|
||||
// Escape special characters
|
||||
if (escape.test(iri)) iri = iri.replace(escapeAll, characterReplacer);
|
||||
// Try to represent the IRI as prefixed name
|
||||
const prefixMatch = this._prefixRegex.exec(iri);
|
||||
return !prefixMatch ? `<${iri}>` : !prefixMatch[1] ? iri : this._prefixIRIs[prefixMatch[1]] + prefixMatch[2];
|
||||
}
|
||||
|
||||
// ### `_encodeLiteral` represents a literal
|
||||
_encodeLiteral(literal) {
|
||||
// Escape special characters
|
||||
let value = literal.value;
|
||||
if (escape.test(value)) value = value.replace(escapeAll, characterReplacer);
|
||||
|
||||
// Write a language-tagged literal
|
||||
if (literal.language) return `"${value}"@${literal.language}`;
|
||||
|
||||
// Write dedicated literals per data type
|
||||
if (this._lineMode) {
|
||||
// Only abbreviate strings in N-Triples or N-Quads
|
||||
if (literal.datatype.value === xsd.string) return `"${value}"`;
|
||||
} else {
|
||||
// Use common datatype abbreviations in Turtle or TriG
|
||||
switch (literal.datatype.value) {
|
||||
case xsd.string:
|
||||
return `"${value}"`;
|
||||
case xsd.boolean:
|
||||
if (value === 'true' || value === 'false') return value;
|
||||
break;
|
||||
case xsd.integer:
|
||||
if (/^[+-]?\d+$/.test(value)) return value;
|
||||
break;
|
||||
case xsd.decimal:
|
||||
if (/^[+-]?\d*\.\d+$/.test(value)) return value;
|
||||
break;
|
||||
case xsd.double:
|
||||
if (/^[+-]?(?:\d+\.\d*|\.?\d+)[eE][+-]?\d+$/.test(value)) return value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Write a regular datatyped literal
|
||||
return `"${value}"^^${this._encodeIriOrBlank(literal.datatype)}`;
|
||||
}
|
||||
|
||||
// ### `_encodePredicate` represents a predicate
|
||||
_encodePredicate(predicate) {
|
||||
return predicate.value === rdf.type ? 'a' : this._encodeIriOrBlank(predicate);
|
||||
}
|
||||
|
||||
// ### `_encodeObject` represents an object
|
||||
_encodeObject(object) {
|
||||
switch (object.termType) {
|
||||
case 'Quad':
|
||||
return this._encodeQuad(object);
|
||||
case 'Literal':
|
||||
return this._encodeLiteral(object);
|
||||
default:
|
||||
return this._encodeIriOrBlank(object);
|
||||
}
|
||||
}
|
||||
|
||||
// ### `_encodeQuad` encodes an RDF-star quad
|
||||
_encodeQuad({
|
||||
subject,
|
||||
predicate,
|
||||
object,
|
||||
graph
|
||||
}) {
|
||||
return `<<${this._encodeSubject(subject)} ${this._encodePredicate(predicate)} ${this._encodeObject(object)}${(0, _N3Util.isDefaultGraph)(graph) ? '' : ` ${this._encodeIriOrBlank(graph)}`}>>`;
|
||||
}
|
||||
|
||||
// ### `_blockedWrite` replaces `_write` after the writer has been closed
|
||||
_blockedWrite() {
|
||||
throw new Error('Cannot write because the writer has been closed.');
|
||||
}
|
||||
|
||||
// ### `addQuad` adds the quad to the output stream
|
||||
addQuad(subject, predicate, object, graph, done) {
|
||||
// The quad was given as an object, so shift parameters
|
||||
if (object === undefined) this._writeQuad(subject.subject, subject.predicate, subject.object, subject.graph, predicate);
|
||||
// The optional `graph` parameter was not provided
|
||||
else if (typeof graph === 'function') this._writeQuad(subject, predicate, object, DEFAULTGRAPH, graph);
|
||||
// The `graph` parameter was provided
|
||||
else this._writeQuad(subject, predicate, object, graph || DEFAULTGRAPH, done);
|
||||
}
|
||||
|
||||
// ### `addQuads` adds the quads to the output stream
|
||||
addQuads(quads) {
|
||||
for (let i = 0; i < quads.length; i++) this.addQuad(quads[i]);
|
||||
}
|
||||
|
||||
// ### `addPrefix` adds the prefix to the output stream
|
||||
addPrefix(prefix, iri, done) {
|
||||
const prefixes = {};
|
||||
prefixes[prefix] = iri;
|
||||
this.addPrefixes(prefixes, done);
|
||||
}
|
||||
|
||||
// ### `addPrefixes` adds the prefixes to the output stream
|
||||
addPrefixes(prefixes, done) {
|
||||
// Ignore prefixes if not supported by the serialization
|
||||
if (!this._prefixIRIs) return done && done();
|
||||
|
||||
// Write all new prefixes
|
||||
let hasPrefixes = false;
|
||||
for (let prefix in prefixes) {
|
||||
let iri = prefixes[prefix];
|
||||
if (typeof iri !== 'string') iri = iri.value;
|
||||
hasPrefixes = true;
|
||||
// Finish a possible pending quad
|
||||
if (this._subject !== null) {
|
||||
this._write(this._inDefaultGraph ? '.\n' : '\n}\n');
|
||||
this._subject = null, this._graph = '';
|
||||
}
|
||||
// Store and write the prefix
|
||||
this._prefixIRIs[iri] = prefix += ':';
|
||||
this._write(`@prefix ${prefix} <${iri}>.\n`);
|
||||
}
|
||||
// Recreate the prefix matcher
|
||||
if (hasPrefixes) {
|
||||
let IRIlist = '',
|
||||
prefixList = '';
|
||||
for (const prefixIRI in this._prefixIRIs) {
|
||||
IRIlist += IRIlist ? `|${prefixIRI}` : prefixIRI;
|
||||
prefixList += (prefixList ? '|' : '') + this._prefixIRIs[prefixIRI];
|
||||
}
|
||||
IRIlist = (0, _Util.escapeRegex)(IRIlist, /[\]\/\(\)\*\+\?\.\\\$]/g, '\\$&');
|
||||
this._prefixRegex = new RegExp(`^(?:${prefixList})[^\/]*$|` + `^(${IRIlist})([_a-zA-Z0-9][\\-_a-zA-Z0-9]*)$`);
|
||||
}
|
||||
// End a prefix block with a newline
|
||||
this._write(hasPrefixes ? '\n' : '', done);
|
||||
}
|
||||
|
||||
// ### `blank` creates a blank node with the given content
|
||||
blank(predicate, object) {
|
||||
let children = predicate,
|
||||
child,
|
||||
length;
|
||||
// Empty blank node
|
||||
if (predicate === undefined) children = [];
|
||||
// Blank node passed as blank(Term("predicate"), Term("object"))
|
||||
else if (predicate.termType) children = [{
|
||||
predicate: predicate,
|
||||
object: object
|
||||
}];
|
||||
// Blank node passed as blank({ predicate: predicate, object: object })
|
||||
else if (!('length' in predicate)) children = [predicate];
|
||||
switch (length = children.length) {
|
||||
// Generate an empty blank node
|
||||
case 0:
|
||||
return new SerializedTerm('[]');
|
||||
// Generate a non-nested one-triple blank node
|
||||
case 1:
|
||||
child = children[0];
|
||||
if (!(child.object instanceof SerializedTerm)) return new SerializedTerm(`[ ${this._encodePredicate(child.predicate)} ${this._encodeObject(child.object)} ]`);
|
||||
// Generate a multi-triple or nested blank node
|
||||
default:
|
||||
let contents = '[';
|
||||
// Write all triples in order
|
||||
for (let i = 0; i < length; i++) {
|
||||
child = children[i];
|
||||
// Write only the object is the predicate is the same as the previous
|
||||
if (child.predicate.equals(predicate)) contents += `, ${this._encodeObject(child.object)}`;
|
||||
// Otherwise, write the predicate and the object
|
||||
else {
|
||||
contents += `${(i ? ';\n ' : '\n ') + this._encodePredicate(child.predicate)} ${this._encodeObject(child.object)}`;
|
||||
predicate = child.predicate;
|
||||
}
|
||||
}
|
||||
return new SerializedTerm(`${contents}\n]`);
|
||||
}
|
||||
}
|
||||
|
||||
// ### `list` creates a list node with the given content
|
||||
list(elements) {
|
||||
const length = elements && elements.length || 0,
|
||||
contents = new Array(length);
|
||||
for (let i = 0; i < length; i++) contents[i] = this._encodeObject(elements[i]);
|
||||
return new SerializedTerm(`(${contents.join(' ')})`);
|
||||
}
|
||||
|
||||
// ### `end` signals the end of the output stream
|
||||
end(done) {
|
||||
// Finish a possible pending quad
|
||||
if (this._subject !== null) {
|
||||
this._write(this._inDefaultGraph ? '.\n' : '\n}\n');
|
||||
this._subject = null;
|
||||
}
|
||||
// Disallow further writing
|
||||
this._write = this._blockedWrite;
|
||||
|
||||
// Try to end the underlying stream, ensuring done is called exactly one time
|
||||
let singleDone = done && ((error, result) => {
|
||||
singleDone = null, done(error, result);
|
||||
});
|
||||
if (this._endStream) {
|
||||
try {
|
||||
return this._outputStream.end(singleDone);
|
||||
} catch (error) {/* error closing stream */}
|
||||
}
|
||||
singleDone && singleDone();
|
||||
}
|
||||
}
|
||||
|
||||
// Replaces a character by its escaped version
|
||||
exports.default = N3Writer;
|
||||
function characterReplacer(character) {
|
||||
// Replace a single character by its escaped version
|
||||
let result = escapedCharacters[character];
|
||||
if (result === undefined) {
|
||||
// Replace a single character with its 4-bit unicode escape sequence
|
||||
if (character.length === 1) {
|
||||
result = character.charCodeAt(0).toString(16);
|
||||
result = '\\u0000'.substr(0, 6 - result.length) + result;
|
||||
}
|
||||
// Replace a surrogate pair with its 8-bit unicode escape sequence
|
||||
else {
|
||||
result = ((character.charCodeAt(0) - 0xD800) * 0x400 + character.charCodeAt(1) + 0x2400).toString(16);
|
||||
result = '\\U00000000'.substr(0, 10 - result.length) + result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
9
node_modules/n3/lib/Util.js
generated
vendored
Normal file
9
node_modules/n3/lib/Util.js
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.escapeRegex = escapeRegex;
|
||||
function escapeRegex(regex) {
|
||||
return regex.replace(/[\]\/\(\)\*\+\?\.\\\$]/g, '\\$&');
|
||||
}
|
||||
179
node_modules/n3/lib/index.js
generated
vendored
Normal file
179
node_modules/n3/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "BaseIRI", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _BaseIRI.default;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "BlankNode", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3DataFactory.BlankNode;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "DataFactory", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3DataFactory.default;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "DefaultGraph", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3DataFactory.DefaultGraph;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "EntityIndex", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3Store.N3EntityIndex;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "Lexer", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3Lexer.default;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "Literal", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3DataFactory.Literal;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "NamedNode", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3DataFactory.NamedNode;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "Parser", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3Parser.default;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "Quad", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3DataFactory.Quad;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "Reasoner", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3Reasoner.default;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "Store", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3Store.default;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "StoreFactory", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3StoreFactory.default;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "StreamParser", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3StreamParser.default;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "StreamWriter", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3StreamWriter.default;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "Term", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3DataFactory.Term;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "Triple", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3DataFactory.Triple;
|
||||
}
|
||||
});
|
||||
exports.Util = void 0;
|
||||
Object.defineProperty(exports, "Variable", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3DataFactory.Variable;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "Writer", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3Writer.default;
|
||||
}
|
||||
});
|
||||
exports.default = void 0;
|
||||
Object.defineProperty(exports, "getRulesFromDataset", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3Reasoner.getRulesFromDataset;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "termFromId", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3DataFactory.termFromId;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "termToId", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _N3DataFactory.termToId;
|
||||
}
|
||||
});
|
||||
var _N3Lexer = _interopRequireDefault(require("./N3Lexer"));
|
||||
var _N3Parser = _interopRequireDefault(require("./N3Parser"));
|
||||
var _N3Writer = _interopRequireDefault(require("./N3Writer"));
|
||||
var _N3Store = _interopRequireWildcard(require("./N3Store"));
|
||||
var _N3StoreFactory = _interopRequireDefault(require("./N3StoreFactory"));
|
||||
var _N3Reasoner = _interopRequireWildcard(require("./N3Reasoner"));
|
||||
var _N3StreamParser = _interopRequireDefault(require("./N3StreamParser"));
|
||||
var _N3StreamWriter = _interopRequireDefault(require("./N3StreamWriter"));
|
||||
var Util = _interopRequireWildcard(require("./N3Util"));
|
||||
exports.Util = Util;
|
||||
var _BaseIRI = _interopRequireDefault(require("./BaseIRI"));
|
||||
var _N3DataFactory = _interopRequireWildcard(require("./N3DataFactory"));
|
||||
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
// Named exports
|
||||
// Export all named exports as a default object for backward compatibility
|
||||
var _default = exports.default = {
|
||||
Lexer: _N3Lexer.default,
|
||||
Parser: _N3Parser.default,
|
||||
Writer: _N3Writer.default,
|
||||
Store: _N3Store.default,
|
||||
StoreFactory: _N3StoreFactory.default,
|
||||
EntityIndex: _N3Store.N3EntityIndex,
|
||||
StreamParser: _N3StreamParser.default,
|
||||
StreamWriter: _N3StreamWriter.default,
|
||||
Util,
|
||||
Reasoner: _N3Reasoner.default,
|
||||
BaseIRI: _BaseIRI.default,
|
||||
DataFactory: _N3DataFactory.default,
|
||||
Term: _N3DataFactory.Term,
|
||||
NamedNode: _N3DataFactory.NamedNode,
|
||||
Literal: _N3DataFactory.Literal,
|
||||
BlankNode: _N3DataFactory.BlankNode,
|
||||
Variable: _N3DataFactory.Variable,
|
||||
DefaultGraph: _N3DataFactory.DefaultGraph,
|
||||
Quad: _N3DataFactory.Quad,
|
||||
Triple: _N3DataFactory.Triple,
|
||||
termFromId: _N3DataFactory.termFromId,
|
||||
termToId: _N3DataFactory.termToId
|
||||
};
|
||||
Reference in New Issue
Block a user