srl-engine
v0.1.0
Published
SHACL 1.2 Rules (SRL) parser, validator, and inference engine
Maintainers
Readme
srl-engine
Parser, validator, and inference engine for SHACL 1.2 Rules written in SRL (Shape Rules Language).
Pure TypeScript. Two runtime dependencies — chevrotain
(lexer/parser) and n3 (RDF store). No DOM,
no framework — runs in Node, a Web Worker, or any bundler target. Ships dual
ESM + CJS builds with full type declarations.
Given SRL rules and an RDF data graph, the engine computes the triples the rules infer — running to a fixed point — and returns each inferred triple with the rule that produced it (provenance).
Install
npm install srl-engineUsage
import { validateSRL, buildAST, executeRules } from 'srl-engine';
const srl = `PREFIX : <http://example.org/>
RULE { ?x :childOf ?y } WHERE { ?y :parentOf ?x }`;
const data = `@prefix : <http://example.org/> .
:john :parentOf :mary .`;
// 1. Validate — lexer/parser errors + §4.2 well-formedness + stratification.
const report = validateSRL(srl);
if (!report.isValid) throw new Error(report.messages[0].message);
// 2. Build the typed RuleSet AST (throws on parse error).
const ruleSet = buildAST(srl);
// 3. Run the rules against the RDF data → inferred triples with provenance.
const result = executeRules(ruleSet, data);
for (const t of result.inferredTriples) {
console.log(t.quadString, '←', t.sourceRule.name);
}
// → <http://example.org/mary> <http://example.org/childOf> <http://example.org/john> ← Rule 1: childOfCommonJS works too: const { validateSRL } = require('srl-engine');
Features
- Full SRL front end — Chevrotain lexer + CST parser + typed AST builder for the current W3C SHACL 1.2 Rules grammar.
- Two rule forms —
RULE iri? { head } WHERE { body }andIF { body } THEN { head }. - Shorthand declarations —
TRANSITIVE(:p), postfix(:p) SYMMETRIC,INVERSE(:p, :q)(expanded into rules at run time). - Property paths — sequence (
/) and inverse (^) in rule bodies. - §4.2 well-formedness — variable scoping, single-assignment
SET, non-leakingNOT, head-var binding, groundDATA,[121]built-ins. - Fixed-point engine — open/closed-dependency stratification, run-once vs
general layers,
DATA-block seeding, pinnedNOW(), per-triple provenance. - Fully typed — every AST, result, and diagnostic type is exported.
API
Values:
| Export | Purpose |
| ------ | ------- |
| parseSRL(text) | Lex + CST parse; returns { tokens, cst, errors } (never throws). |
| buildAST(text) | Parse + walk the CST into a typed RuleSet (throws on parse error). |
| validateSRL(text) | Full diagnostics: lexer/parser, §4.2 well-formedness, stratification (never throws). |
| executeRules(ruleSet, rdfData, options?) | Fixed-point inference → inferred triples + provenance (never throws; collects errors). |
| stratifyRules(rules) / isStratifiable(rules) | Open/closed dependency stratification. |
| expandDeclarations(decls, prefixes) | Rewrite TRANSITIVE/SYMMETRIC/INVERSE into ordinary rules. |
| formatTripleForDisplay(quad, prefixes) | Prefix-collapsed S/P/O strings for UIs. |
| getSerializedGrammar() / getGrammarRuleNames() | Grammar introspection (railroad diagrams etc.). |
| SRLLexer, allTokens | The Chevrotain lexer + token list. |
| RDF helpers | PatternMatcher, termToN3, n3TermToRDFTerm, termsEqual, quadToString, termToString, triplePatternToString, isVariable, isRDFTerm, isTriplePattern, getPatternVariables. |
Types (all exported): RuleSet, Rule, RuleHead, RuleBody, TriplePattern,
BodyElement, FilterElement, AssignmentElement, NegationElement, RDFTerm
and its variants, Declaration (+ Transitive/Symmetric/Inverse),
DataBlock, Expression, PathExpression, SourceLocation, ParseResult,
GrammarRuleInfo, ExecutionResult, InferredTriple, RuleInfo,
ExecutorOptions, StratificationLayer, StratifiedRule, StratificationCheck,
ValidationResult, ValidationMessage, SolutionMapping, EvalResult.
See src/index.ts for the complete surface.
Learn more
- How-To Guide — the full pipeline (validate → build → execute), semantics, an SRL cheat-sheet, recipes, and gotchas.
- Examples — seven runnable scripts (
node examples/01-….mjs), from basic inference to provenance. - Publishing — step-by-step npm release procedure.
- Backlog — known bugs, deferred features, and release follow-ups.
SHACL shape targeting (opt-in extension)
The engine includes an opt-in extension — not part of W3C SHACL 1.2 Rules — that ties a rule to a SHACL shape so the rule fires only for the shape's conforming focus nodes.
Off by default. Without { extensions: true }, FOR is a syntax error and
executeRules ignores any targeted rules — spec-conformant code is unaffected.
Syntax
PREFIX ex: <http://example.org/>
RULE ex:adultStatus FOR ?this IN ex:AdultShape
{ ?this ex:status ex:adult }
WHERE
{ ?this ex:age ?a }FOR ?this IN ex:AdultShape pre-binds ?this to each node that conforms
to ex:AdultShape in the supplied shapes graph. The body and head are the
standard rule machinery — they see ?this as already bound.
API
import { buildAST, validateSRL, executeRules } from 'srl-engine';
// 1. Parse with extension syntax enabled.
const ruleSet = buildAST(srl, { extensions: true });
// 2. Validate (optional but recommended).
const report = validateSRL(srl, { extensions: true });
// 3. Execute — supply the shapes graph as a Turtle string (shapesGraph)
// or a pre-parsed n3 Store (shapesStore).
const result = executeRules(ruleSet, data, {
extensions: true,
shapesGraph: shapesTurtle, // or: shapesStore: myStore
});Example
const shapes = `
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix ex: <http://example.org/> .
ex:AdultShape a sh:NodeShape ;
sh:targetClass ex:Person ;
sh:property [ sh:path ex:age ; sh:minCount 1 ; sh:minInclusive 18 ] .`;
const srl = `PREFIX ex: <http://example.org/>
RULE ex:adultStatus FOR ?this IN ex:AdultShape
{ ?this ex:status ex:adult }
WHERE
{ ?this ex:age ?a }`;
const data = `
@prefix ex: <http://example.org/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
ex:Alice rdf:type ex:Person ; ex:age 30 .
ex:Bob rdf:type ex:Person ; ex:age 10 .`;
const result = executeRules(buildAST(srl, { extensions: true }), data, {
extensions: true,
shapesGraph: shapes,
});
// Inferred: ex:Alice ex:status ex:adult (Alice age 30 ≥ 18 → conforms)
// NOT inferred for Bob (age 10 < 18 → does not conform to AdultShape)The supported SHACL Core subset is documented in
docs/shacl-core-support-matrix.md.
For a full worked example see examples/07-for-in-shape.mjs
and the How-To Guide §14.
Scope
Implements the current W3C SHACL 1.2 Rules surface syntax and semantics.
Deferred (parse to errors today): RDF-1.2 rich terms (reification
<< >>/<<( )>>, collections ( )/[ ], annotations {| |}) and extended
property paths (*/+/?/|, negated property sets). Built-ins are restricted
to the spec [121] set. The complete list of deferred features and known issues
lives in docs/BACKLOG.md.
Syntax and semantics are validated against the
w3c/data-shapes rules test suite.
Development
Run from the monorepo root:
npm -w srl-engine run build # tsup → dist/ (ESM + CJS + .d.ts + .d.cts)
npm -w srl-engine test # vitest (facade smoke + W3C fixtures)
npm -w srl-engine run typecheck # tsc --noEmitReleasing to npm: see PUBLISHING.md (detailed) or
../../RELEASING.md (condensed + CI/changesets/UMD).
License
MIT.
