SHACL 1.2 Rules

W3C First Public Working Draft

More details about this document
This version:
https://www.w3.org/TR/2025/WD-shacl12-rules-20251209/
Latest published version:
https://www.w3.org/TR/shacl12-rules/
Latest editor's draft:
https://w3c.github.io/data-shapes/shacl12-rules/
History:
https://www.w3.org/standards/history/shacl12-rules/
Commit history
Editors:
Robert David (Ontotext)
David Habgood (KurrawongAI)
Andy Seaborne (Apache Software Foundation)
Simon Steyskal (Siemens AG)
Feedback:
GitHub w3c/data-shapes (pull requests, new issue, open issues)

Abstract

This document describes Shapes Constraint Language (SHACL) Rules.

This specification is published by the Data Shapes Working Group .

Status of This Document

This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C standards and drafts index.

This document was published by the Data Shapes Working Group as a First Public Working Draft using the Recommendation track.

Publication as a First Public Working Draft does not imply endorsement by W3C and its Members.

This is a draft document and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to cite this document as other than a work in progress. Future updates to this upcoming Recommendation may incorporate new features.

This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent that the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

This document is governed by the 18 August 2025 W3C Process Document.

SHACL Specifications

This specification is part of the SHACL 1.2 family of specifications. See the SHACL 1.2 Overview for a more detailed introduction to them.

The specifications are as follows:

SHACL 1.2 Overview
overviews the set of SHACL specifications
SHACL 1.2 Core
defines the Core of SHACL
SHACL 1.2 SPARQL Extensions
defines SPARQL-related extensions of SHACL
SHACL 1.2 Node Expressions
defines graph expressions used to determine focus nodes in SHACL
SHACL 1.2 Rules
defines SHACL's methods of rule-based inference
SHACL 1.2 UI
defines SHACL's use for User Interface generation
SHACL 1.2 Compact Syntax
defines an RDF syntax for expressing SHACL concepts
SHACL 1.2 Profiling
defines the use of SHACL for profiling data, including SHACL data

1. Introduction

This document introduces the concept of inference rules for SHACL 1.2, a mechanism for deriving new RDF triples from existing data using declarative rules defined in shapes graphs. This extends SHACL’s capabilities beyond validation, enabling reasoning and data enrichment.

This document complements other SHACL 1.2 specifications, such as SHACL Core, by defining the syntax and semantics of rule-based inference. While SHACL Core focuses on constraint validation, the SHACL Rules specification provides a standardized way to express and evaluate rules that generate new data.

1.1 Terminology

Editor's note

Connect to definitions in RDF 1.2 Concepts.

The following definitions from other specifications are used in this document: @@

1.2 Document Conventions

Some examples in this document use Turtle [turtle]. The reader is expected to be familiar with SHACL [shacl] and SPARQL [sparql-query].

Within this document, the following namespace prefix bindings are used:

Prefix Namespace
rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#
rdfs: http://www.w3.org/2000/01/rdf-schema#
sh: http://www.w3.org/ns/shacl#
shrl: http://www.w3.org/ns/shacl-rules#
shnex: http://www.w3.org/ns/shacl-node-expr#
xsd: http://www.w3.org/2001/XMLSchema#
ex: http://example.com/

Throughout the document, color-coded boxes containing RDF graphs in Turtle will appear. These fragments of Turtle documents use the prefix bindings given above.

1.3 Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

TODO

Editor's note

RFC 2119 language should autmatically be inserted here.

2. Outline

SHACL rules infer new triples. The input is a data graph and a set of rules. The output is a graph of inferred triples that do not occur in the data graph.

2.1 Basic Usage

:A :fatherOf :X .
:B :motherOf :X .
:C :motherOf :A .
RULE { ?x :childOf ?y } WHERE { ?y :fatherOf ?x }
RULE { ?x :childOf ?y } WHERE { ?y :motherOf ?x }

RULE { ?x :descendedFrom ?y } WHERE { ?x :childOf ?y }
RULE { ?x :descendedFrom ?y } WHERE { ?x :childOf ?z . ?z :childOf ?y }

The above rules, applied to the data, will conclude that: :X is the :childOf :A and :B, and that :X is :descendedFrom :C.

2.2 Recursion

RULE { ?x :ancestorOf ?y } WHERE { ?y :descendedFrom ?x }
RULE { ?a :ancestorOf ?b } WHERE { ?a :ancestorOf ?c . ?c :ancestorOf ?b }

2.3 Negation

# Default value - calculate a name
RULE { ?x :name ?FN } WHERE { 
    ?x rdf:type :Person 
    NOT { ?x :name ?someName }
    ?x :givenName ?name1 ;
       :familyName ?name2 .
    BIND(concat(?name1, " ", ?name2) AS ?FN)
}

3. Shape Rules Abstract Syntax

The Shape Rules Abstract Syntax

variable
A variable represents a possible RDF term in a triple pattern. Variables are also used in expressions.
expression

An expression is a function, or functional form. It's arguments are RDF terms. An expression is evaluated with respect to a solution mapping to give an RDF term as the result. Expressions are compatible with SHACL list parameter functions and with SPARQL expressions.

data block
A data block is a set of triples. These form extra facts that are included in the inference process.
triple template
A triple template is 3-tuple where each element is either a variable or an [=RDF term] (which might be a triple term). The second element of the tuple must be an IRI or a variable. Triple templates appear in the head of a rule.
triple pattern
A triple pattern is 3-tuple where each element is either a variable, or an RDF term (which might be a triple term). The second element of the tuple must be an IRI. Triple patterns appear in the body of a rule.
condition expression
A condition expression is a function, or functional form, that evaluates to true or false. Condition expressions appear in the body of a rule.
negation element
A negation element is ..@@.. . Negation elements appear in the body of a rule.
assignment
An assignment is a pair of a variable, called the assignment variable, and an expression, called the assignment expression. Assignments appear in the body of a rule.
aggregation element
An aggregation element is ..@@.. . Aggregation elements appear in the body of a rule.
rule body element
A rule body element (often just "rule element") is any element that can appear in a rule body; a triple pattern, a condition expression, a negation element, an assignment, or an aggregation element.
rule head
A rule head is a sequence where each element of the sequence is a triple template.
rule body
A rule body is a sequence of rule body elements.
rule
A rule is a pair of a rule head (often just "head") and a rule body (often just "body").
rule set
A rule set is a collection of zero or more rules and a collection of zero or more data blocks.

In a triple pattern or a triple template, position 1 of the tuple is informally called the subject, position 2 is informally called the predicate, and position 3 is informally called the object.

3.1 Stratification

Stratification is the process of labelling rules based on their dependency relationships in a rule set. The set of rules with the same label are called a layer.

stratification layer
A stratification layer, usually, just "layer", is the set of rules with same stratification labelling. stratification layer, layer
rule element dependency
A rule body element E depends on a rule R if the head of rule R contains a triple template that may provide a triple that is matched by a triple pattern in E.
rule dependency
A rule R1 depends on rule R2 if any rule element of R1 depends on R2.
@@formalize

Process

Conditions

3.2 Well-formedness Conditions

Well-formedness is a set of conditions on the abstract syntax of shapes rules. Together, these rules ensure that a variable in the head of a rule has a value defined in the body of the rule; that each variable in an condition expression or assignment expression has a value at the point of evaluation; and that each assignment in a rule introduces a new variable, not used earlier in the rule body.

Editor's note

Add a rule for nested patterns e.g. negation.

A rule is a well-formed rule if all of the following conditions are met:

A rule set is "well-formed" if and only if all of the rules of the rule set are "well-formed".

4. Concrete Syntax forms for Shapes Rules

There are two concrete syntaxes.

Note

The Shape Rules Language (SRL) syntax has an equivalent RDF syntax form. Well-formed RDF syntax can be translated to the Shape Rules Language syntax.

Shape Rules Language:

PREFIX : <http://example/>

DATA { :x :p 1 ; :q 2 . }

RULE { ?x :bothPositive true . }
WHERE { ?x :p ?v1  FILTER ( ?v1 > 0 )  ?x :q ?v2  FILTER ( ?v2 > 0 )  }

RULE { ?x :oneIsZero true . }
WHERE { ?x :p ?v1 ;  :q ?v2  FILTER ( ( ?v1 = 0 ) || ( ?v2 = 0 ) )  }

RDF Rules syntax:

PREFIX :       <http://example/>
PREFIX rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX sh:     <http://www.w3.org/ns/shacl#>
PREFIX shrl:   <http://www.w3.org/ns/shacl-rules#>
PREFIX sparql: <http://www.w3.org/ns/sparql#>

:ruleSet-1
  rdf:type shrl:RuleSet;
  shrl:data (
    <<( :x :p 1 )>>
    <<( :x :q 2 )>>
  );
  shrl:ruleSet (
    [
      rdf:type shrl:Rule;
      shrl:head (
        [ shrl:subject [ shrl:var "x" ] ; shrl:predicate :bothPositive; shrl:object true ]
      ) ;
      shrl:body (
        [ shrl:subject [ shrl:var "x" ]; shrl:predicate :p; shrl:object [ shrl:var "v1" ] ]
        [ shrl:expr [ sparql:greaterThan ( [ shrl:var "v1" ] 0 ) ] ]
        [ shrl:subject [ shrl:var "x" ] ; shrl:predicate :q; shrl:object [ shrl:var "v2" ] ]
        [ shrl:expr [ sparql:greaterThan ( [ shrl:var "v2" ] 0 ) ] ]
      );
    ]
    [
      rdf:type shrl:Rule;
      shrl:head (
        [ shrl:subject [ shrl:var "x" ] ; shrl:predicate :oneIsZero ; shrl:object true ]
      ) ;
      shrl:body (
        [ shrl:subject [ shrl:var "x" ] ; shrl:predicate :p ; shrl:object [ shrl:var "v1" ] ]
        [ shrl:subject [ shrl:var "x" ] ; shrl:predicate :q ; shrl:object [ shrl:var "v2" ] ]
        [ shrl:expr [ sparql:function-or (
              [ sparql:equals ( [ shrl:var "v1" ] 0 ) ]
              [ sparql:equals ( [ shrl:var "v2" ] 0 ) ]
            ) ]
        ]
      );
    ]
  ) .

4.1 Shape Rules Language syntax

The grammar is given below.

Editor's note

Mapping the AST to the abstract syntax.

4.1.1 Shape Rules Language Abbreviations

Additional helpers (short-hand abbreviations):

Note

These allow for well-known rule patterns and also specialised implementations in basic engines

  • TRANSITIVE(uri)
  • SYMMETRIC(uri)
  • INVERSE(uri)

4.2 RDF Rules Syntax

Vocabulary: shacl-rules.ttl.

Editor's note

Well-formedness:

  • All RDF lists are well-formed
  • exactly one of subject - predicate - object, per body of head element
  • Well-formed, single-valued,list-argument node expressions
  • well-formed abstract syntax
Editor's note

Describe how the abstract model maps to triples??. way round - copes with extra triples. Output is the instance of the abtract model that generates the triples - but need to define "maximal".

Editor's note

Process : accumulators, bottom up/ Walk the structure.

  • Collect data triples
  • Map expressions
  • Map triple-patterns
  • Map triple-templates
  • Map assignments
  • Map to rule
  • Rule set

All triples not in the syntax are ignored. No other "shrl:" predicates are allowed (??).

5. Rule Set Evaluation

This section defines the outcome of evaluating a rule set on given data. It does not prescribe the algorithm as the method of implementation. An implementation can use any algorithm that generates the same outcome.

Inputs: data graph G, called the base graph, and a rule set RS.
Output: an RDF graph GI of inferred triples

The inferred triples do not include triples present in the set of triples of the base graph.

5.1 Evaluation Definitions

binding
A binding is a pair (variable, RDF term), consistent with the definition used in [sparql12-query].
solution mapping
A solution mapping, μ, is a partial function μ : VT, where V is the set of all variables and T is the set of all RDF terms. The domain of μ is denoted by dom(μ), and it is the subset of V for which μ is defined. We use the term solution where it is clear that a solution mapping is meant. Write μ0 for the solution mapping such that dom(μ0) is the empty set.
substitution function
A substitution function, or just substitution, is a function subst(μ, triple pattern) that returns a triple pattern where each occurrence in the triple pattern of a variable that is in the dom(μ) is replaced by the RDF term given by the solution mapping for var. If the triple pattern result has no variables, then it is an RDF Triple.
base graph
The base graph is the RDF Graph given as input to the evaluation process.
evaluation graph
A evaluation graph is an RDF Graph that combines the base graph and all triples produced during the evaluation of a rule set.
graph match
A graph match finds the ways to map a triple pattern onto triples in an RDF Graph.

Let G be an RDF graph and TP be a triple pattern. The function graphMatch(G, TP) returns a set of all possible solutions that, when applied to the triple pattern, produce a triple that is in the evaluation graph

Let G be an RDF graph and TP be a triple pattern.

graphMatch(G, TP) = { μ | subst(μ, TP) is a triple in G }
solution compatible
Two solutions S1 and S2 are compatible if they agree on the variables in common.

Let S1 and S2 be solutions.

compatible1, μ2) = true
                      if forall v in dom1) intersection dom2)
                          μ1(v) = μ2(v)
compatible1, μ2) = false otherwise
solution sequence
A solution sequence is a multi-set of solutions. There is no defined order to the sequence. It is equivalent to an unordered list and it can contain duplicates.
solution merge
If two solutions are compatible, the merge of two solutions is the solution that maps variables of each solution to the RDF term from one or other of the solutions.
Let μ1, μ2 be solution mappings, and S1 and S2 be solution sequences.
merge(μ1, μ2) = { μ |
                    μ(v) = μ1(v) if v in dom(μ1)
                    μ(v) = μ2(v) otherwise }
merge(S1, S2) = { μ |
                    μ1 in S1, μ2 in S2
                    and compatible(μ1, μ2)
                    μ(v) = merge(μ1, μ2)
Editor's note

Say the domain is dom(S1) ∪︀ dom(S2).

Say that two solutions that have no variables in common are compatible.

5.2 Evaluation of an Expression

Editor's note

Sketch

Let F(arg1, arg2, ...) be an expression.
where arg1, arg2 are RDF terms.
@@

Let [x/μ] be
    if x is an RDF term, then [x/row] is x
    if x is a variable, then [x/row] is μ(x)
    ## By well-formedness, it is an error if x is not in the row.

eval(F(expr1, expr2 ...), row) = F(eval(expr1, row), eval(expr2, row), ...)
 ...
eval(FF(expr1, expr2) , row) = ... things that are not functions like `IF`

5.3 Evaluation of a Rule

Editor's note

Sketch

Turn into definitions of the step components

let R be a well-formed rule.
let rule R = (H, B) where
             H is the sequence of triple templates in the head
             B is the sequence of triple patterns, condition expressions,
                and assignments in the body

let R : map variable to RDF term as a set of pairs (variable, RDF term)

## Solution sequence of one solution that does not map any variables.
## (This is the join identity)

let SEQ: Solution sequence = { μ0 }
let G = evaluation graph

# Start::

Replace each blank node in B with a fresh 
variable that does not occur in the rule body.

# Evaluate rule body

for each rule element rElt in B
    if rElt is a triple pattern TP:
        X = graphMatch(G, TP)
        SEQ1 = {}
        for each μ1 in X:
            for each μ2 in SEQ:
              if compatible(μ1, μ2)
                μ3 = merge(μ1, μ2)
                add μ3 to SEQ1
            endfor
        endif

    if rElt is a condition expression F:
        SEQ1 = {}
        for each solution μ in SEQ:
            ## EBV = Effective boolean value.
            ## TODO: Eval errors.
            if ( EBV(eval(μ, F)) is true )
                add μ to SEQ1
                endif
            endfor
        endif

    if rElt is an assignment(V, expr)
        SEQ1 = {}
        for each solution S in SEQ:
            let x = eval(expr, S)
            add(V, x) to S
            add S to SEQ1
            endfor
        endif

     if SEQ1 is empty 
        SEQ = {}
        exit
        endif

      SEQ = SEQ1
   
    endfor

# Evaluate rule head
let H = empty set
for each μ in SEQ:
    let S = {}
    for each triple template TT in head
        let triple = subst(μ, TT)
        Add triple to S
    H = H union S
    endfor

result eval(R, G) is H

Note that H may contain triples that are also in the data graph.

5.4 Evaluation of a Rule Set

Editor's note

Sketch

let G0 be the input RDF graph.
let RS be the rule set
Apply stratification to RS
let L be the sequence of layers after stratification

let GI = G0
for each layer in L:
    let finished = false
    while !finished:
        finished = true
        for each rule in layer:
            let X = eval(rule, GI)
            let Y = { t ∈ X | t ∉ in GI }
            if Y is not empty:
                finished = false
                endif
            let GI = Y ∪︀ GI
            endfor
        endwhile
    endfor
the result is GI

6. Shapes Rules Language Grammar

[1]   RuleSet   ::=   ( Prologue ( Rule | Data ) )*
[2]   Prologue   ::=   ( BaseDecl | PrefixDecl | VersionDecl | ImportsDecl )*
[3]   BaseDecl   ::=   'BASE' IRIREF
[4]   PrefixDecl   ::=   'PREFIX' PNAME_NS IRIREF
[5]   VersionDecl   ::=   'VERSION' VersionSpecifier
[6]   VersionSpecifier   ::=   STRING_LITERAL1 | STRING_LITERAL2
[7]   ImportsDecl   ::=   'IMPORTS' iri
[8]   Rule   ::=   Rule1 | Rule2 | Rule3 | Declaration
[9]   Rule1   ::=   'RULE' HeadTemplate 'WHERE' BodyPattern
[10]   Rule2   ::=   'IF' BodyPattern 'THEN' HeadTemplate
[11]   Rule3   ::=   HeadTemplate ':-' BodyPattern
[12]   Declaration   ::=   ( 'TRANSITIVE' '(' iri ')' | 'SYMMETRIC' '(' iri ')' | 'INVERSE' '(' iri ',' iri ')' )
[13]   Data   ::=   'DATA' TriplesTemplateBlock
[14]   HeadTemplate   ::=   TriplesTemplateBlock
[15]   BodyPattern   ::=   '{' BodyPattern1 '}'
[16]   BodyPattern1   ::=   BodyTriplesBlock? ( BodyNotTriples BodyTriplesBlock? )*
[17]   BodyNotTriples   ::=   Filter | Negation | Assignment
[18]   BodyTriplesBlock   ::=   TriplesBlock
[19]   Negation   ::=   'NOT' '{' BodyBasic '}'
[20]   BodyBasic   ::=   BodyTriplesBlock? ( Filter BodyTriplesBlock? )*
[21]   TriplesTemplateBlock   ::=   '{' TriplesTemplate? '}'
[22]   TriplesTemplate   ::=   TriplesSameSubject ( '.' TriplesTemplate? )?
[23]   TriplesBlock   ::=   TriplesSameSubjectPath ( '.' TriplesBlock? )?
[24]   ReifiedTripleBlock   ::=   ReifiedTriple PropertyList
[25]   ReifiedTripleBlockPath   ::=   ReifiedTriple PropertyListPath
[26]   Assignment   ::=   'BIND' '(' Expression 'AS' Var ')'
[27]   Reifier   ::=   '~' VarOrReifierId?
[28]   VarOrReifierId   ::=   Var | iri | BlankNode
[29]   Filter   ::=   'FILTER' Constraint
[30]   Constraint   ::=   BrackettedExpression | BuiltInCall | FunctionCall
[31]   FunctionCall   ::=   iri ArgList
[32]   ArgList   ::=   NIL | '(' Expression ( ',' Expression )* ')'
[33]   ExpressionList   ::=   NIL | '(' Expression ( ',' Expression )* ')'
[34]   TriplesSameSubject   ::=   VarOrTerm PropertyListNotEmpty | TriplesNode PropertyList | ReifiedTripleBlock
[35]   PropertyList   ::=   PropertyListNotEmpty?
[36]   PropertyListNotEmpty   ::=   Verb ObjectList ( ';' ( Verb ObjectList )? )*
[37]   Verb   ::=   VarOrIri | 'a'
[38]   ObjectList   ::=   Object ( ',' Object )*
[39]   Object   ::=   GraphNode Annotation
[40]   TriplesSameSubjectPath   ::=   VarOrTerm PropertyListPathNotEmpty | TriplesNodePath PropertyListPath | ReifiedTripleBlockPath
[41]   PropertyListPath   ::=   PropertyListPathNotEmpty?
[42]   PropertyListPathNotEmpty   ::=   ( VerbPath | VerbSimple ) ObjectListPath ( ';' ( ( VerbPath | VerbSimple ) ObjectListPath )? )*
[43]   VerbPath   ::=   Path
[44]   VerbSimple   ::=   Var
[45]   ObjectListPath   ::=   ObjectPath ( ',' ObjectPath )*
[46]   ObjectPath   ::=   GraphNodePath AnnotationPath
[47]   Path   ::=   PathSequence
[48]   PathSequence   ::=   PathEltOrInverse ( '/' PathEltOrInverse )*
[49]   PathEltOrInverse   ::=   PathElt | '^' PathElt
[50]   PathElt   ::=   PathPrimary
[51]   PathPrimary   ::=   iri | 'a' | '(' Path ')'
[52]   TriplesNode   ::=   Collection | BlankNodePropertyList
[53]   BlankNodePropertyList   ::=   '[' PropertyListNotEmpty ']'
[54]   TriplesNodePath   ::=   CollectionPath | BlankNodePropertyListPath
[55]   BlankNodePropertyListPath   ::=   '[' PropertyListPathNotEmpty ']'
[56]   Collection   ::=   '(' GraphNode+ ')'
[57]   CollectionPath   ::=   '(' GraphNodePath+ ')'
[58]   AnnotationPath   ::=   ( Reifier | AnnotationBlockPath )*
[59]   AnnotationBlockPath   ::=   '{|' PropertyListPathNotEmpty '|}'
[60]   Annotation   ::=   ( Reifier | AnnotationBlock )*
[61]   AnnotationBlock   ::=   '{|' PropertyListNotEmpty '|}'
[62]   GraphNode   ::=   VarOrTerm | TriplesNode | ReifiedTriple
[63]   GraphNodePath   ::=   VarOrTerm | TriplesNodePath | ReifiedTriple
[64]   VarOrTerm   ::=   Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | NIL | TripleTerm
[65]   ReifiedTriple   ::=   '<<' ReifiedTripleSubject Verb ReifiedTripleObject Reifier? '>>'
[66]   ReifiedTripleSubject   ::=   Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | ReifiedTriple
[67]   ReifiedTripleObject   ::=   Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | ReifiedTriple | TripleTerm
[68]   TripleTerm   ::=   '<<(' TripleTermSubject Verb TripleTermObject ')>>'
[69]   TripleTermSubject   ::=   Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode
[70]   TripleTermObject   ::=   Var | iri | RDFLiteral | NumericLiteral | BooleanLiteral | BlankNode | TripleTerm
[71]   TripleTermData   ::=   '<<(' TripleTermDataSubject ( iri | 'a' ) TripleTermDataObject ')>>'
[72]   TripleTermDataSubject   ::=   iri | RDFLiteral | NumericLiteral | BooleanLiteral
[73]   TripleTermDataObject   ::=   iri | RDFLiteral | NumericLiteral | BooleanLiteral | TripleTermData
[74]   VarOrIri   ::=   Var | iri
[75]   Var   ::=   VAR1 | VAR2
[76]   Expression   ::=   ConditionalOrExpression
[77]   ConditionalOrExpression   ::=   ConditionalAndExpression ( '||' ConditionalAndExpression )*
[78]   ConditionalAndExpression   ::=   ValueLogical ( '&&' ValueLogical )*
[79]   ValueLogical   ::=   RelationalExpression
[80]   RelationalExpression   ::=   NumericExpression ( '=' NumericExpression | '!=' NumericExpression | '<' NumericExpression | '>' NumericExpression | '<=' NumericExpression | '>=' NumericExpression | 'IN' ExpressionList | 'NOT' 'IN' ExpressionList )?
[81]   NumericExpression   ::=   AdditiveExpression
[82]   AdditiveExpression   ::=   MultiplicativeExpression ( '+' MultiplicativeExpression | '-' MultiplicativeExpression | ( NumericLiteralPositive | NumericLiteralNegative ) ( ( '*' UnaryExpression ) | ( '/' UnaryExpression ) )* )*
[83]   MultiplicativeExpression   ::=   UnaryExpression ( '*' UnaryExpression | '/' UnaryExpression )*
[84]   UnaryExpression   ::=     '!' PrimaryExpression
| '+' PrimaryExpression
| '-' PrimaryExpression
| PrimaryExpression
[85]   PrimaryExpression   ::=   BrackettedExpression | BuiltInCall | iriOrFunction | RDFLiteral | NumericLiteral | BooleanLiteral | Var | ExprTripleTerm
[86]   ExprTripleTerm   ::=   '<<(' ExprTripleTermSubject Verb ExprTripleTermObject ')>>'
[87]   ExprTripleTermSubject   ::=   iri | RDFLiteral | NumericLiteral | BooleanLiteral | Var
[88]   ExprTripleTermObject   ::=   iri | RDFLiteral | NumericLiteral | BooleanLiteral | Var | ExprTripleTerm
[89]   BrackettedExpression   ::=   '(' Expression ')'
[90]   BuiltInCall   ::=     'STR' '(' Expression ')'
| 'LANG' '(' Expression ')'
| 'LANGMATCHES' '(' Expression ',' Expression ')'
| 'LANGDIR' '(' Expression ')'
| 'DATATYPE' '(' Expression ')'
| 'BOUND' '(' Var ')'
| 'IRI' '(' Expression ')'
| 'URI' '(' Expression ')'
| 'BNODE' ( '(' Expression ')' | NIL )
| 'RAND' NIL
| 'ABS' '(' Expression ')'
| 'CEIL' '(' Expression ')'
| 'FLOOR' '(' Expression ')'
| 'ROUND' '(' Expression ')'
| 'CONCAT' ExpressionList
| 'SUBSTR' '(' Expression ',' Expression ( ',' Expression )? ')'
| 'STRLEN' '(' Expression ')'
| 'REPLACE' '(' Expression ',' Expression ',' Expression ( ',' Expression )? ')'
| 'UCASE' '(' Expression ')'
| 'LCASE' '(' Expression ')'
| 'ENCODE_FOR_URI' '(' Expression ')'
| 'CONTAINS' '(' Expression ',' Expression ')'
| 'STRSTARTS' '(' Expression ',' Expression ')'
| 'STRENDS' '(' Expression ',' Expression ')'
| 'STRBEFORE' '(' Expression ',' Expression ')'
| 'STRAFTER' '(' Expression ',' Expression ')'
| 'YEAR' '(' Expression ')'
| 'MONTH' '(' Expression ')'
| 'DAY' '(' Expression ')'
| 'HOURS' '(' Expression ')'
| 'MINUTES' '(' Expression ')'
| 'SECONDS' '(' Expression ')'
| 'TIMEZONE' '(' Expression ')'
| 'TZ' '(' Expression ')'
| 'NOW' NIL
| 'UUID' NIL
| 'STRUUID' NIL
| 'MD5' '(' Expression ')'
| 'SHA1' '(' Expression ')'
| 'SHA256' '(' Expression ')'
| 'SHA384' '(' Expression ')'
| 'SHA512' '(' Expression ')'
| 'COALESCE' ExpressionList
| 'IF' '(' Expression ',' Expression ',' Expression ')'
| 'STRLANG' '(' Expression ',' Expression ')'
| 'STRLANGDIR' '(' Expression ',' Expression ',' Expression ')'
| 'STRDT' '(' Expression ',' Expression ')'
| 'sameTerm' '(' Expression ',' Expression ')'
| 'isIRI' '(' Expression ')'
| 'isURI' '(' Expression ')'
| 'isBLANK' '(' Expression ')'
| 'isLITERAL' '(' Expression ')'
| 'isNUMERIC' '(' Expression ')'
| 'hasLANG' '(' Expression ')'
| 'hasLANGDIR' '(' Expression ')'
| 'REGEX' '(' Expression ',' Expression ( ',' Expression )? ')'
| 'isTRIPLE' '(' Expression ')'
| 'TRIPLE' '(' Expression ',' Expression ',' Expression ')'
| 'SUBJECT' '(' Expression ')'
| 'PREDICATE' '(' Expression ')'
| 'OBJECT' '(' Expression ')'
[91]   iriOrFunction   ::=   iri ArgList?
[92]   RDFLiteral   ::=   String ( LANG_DIR | '^^' iri )?
[93]   NumericLiteral   ::=   NumericLiteralUnsigned | NumericLiteralPositive | NumericLiteralNegative
[94]   NumericLiteralUnsigned   ::=   INTEGER | DECIMAL | DOUBLE
[95]   NumericLiteralPositive   ::=   INTEGER_POSITIVE | DECIMAL_POSITIVE | DOUBLE_POSITIVE
[96]   NumericLiteralNegative   ::=   INTEGER_NEGATIVE | DECIMAL_NEGATIVE | DOUBLE_NEGATIVE
[97]   BooleanLiteral   ::=   'true' | 'false'
[98]   String   ::=   STRING_LITERAL1 | STRING_LITERAL2 | STRING_LITERAL_LONG1 | STRING_LITERAL_LONG2
[99]   iri   ::=   IRIREF | PrefixedName
[100]   PrefixedName   ::=   PNAME_LN | PNAME_NS
[101]   BlankNode   ::=   BLANK_NODE_LABEL | ANON

Productions for terminals:

[102]   IRIREF   ::=   '<' ([^<>"{}|^`\]-[#x00-#x20])* '>'
[103]   PNAME_NS   ::=   PN_PREFIX? ':'
[104]   PNAME_LN   ::=   PNAME_NS PN_LOCAL
[105]   BLANK_NODE_LABEL   ::=   '_:' ( PN_CHARS_U | [0-9] ) ((PN_CHARS|'.')* PN_CHARS)?
[106]   VAR1   ::=   '?' VARNAME
[107]   VAR2   ::=   '$' VARNAME
[108]   LANG_DIR   ::=   '@' [a-zA-Z]+ ('-' [a-zA-Z0-9]+)* ('--' [a-zA-Z]+)?
[109]   INTEGER   ::=   [0-9]+
[110]   DECIMAL   ::=   [0-9]* '.' [0-9]+
[111]   DOUBLE   ::=   ( ([0-9]+ ('.'[0-9]*)? ) | ( '.' ([0-9])+ ) ) [eE][+-]?[0-9]+
[112]   INTEGER_POSITIVE   ::=   '+' INTEGER
[113]   DECIMAL_POSITIVE   ::=   '+' DECIMAL
[114]   DOUBLE_POSITIVE   ::=   '+' DOUBLE
[115]   INTEGER_NEGATIVE   ::=   '-' INTEGER
[116]   DECIMAL_NEGATIVE   ::=   '-' DECIMAL
[117]   DOUBLE_NEGATIVE   ::=   '-' DOUBLE
[118]   STRING_LITERAL1   ::=   "'" ( ([^#x27#x5C#xA#xD]) | ECHAR )* "'"
[119]   STRING_LITERAL2   ::=   '"' ( ([^#x22#x5C#xA#xD]) | ECHAR )* '"'
[120]   STRING_LITERAL_LONG1   ::=   "'''" ( ( "'" | "''" )? ( [^'\] | ECHAR ) )* "'''"
[121]   STRING_LITERAL_LONG2   ::=   '"""' ( ( '"' | '""' )? ( [^"\] | ECHAR ) )* '"""'
[122]   ECHAR   ::=   '\' [tbnrf\"']
[123]   NIL   ::=   '(' WS* ')'
[124]   WS   ::=   #x20 | #x9 | #xD | #xA
[125]   ANON   ::=   '[' WS* ']'
[126]   PN_CHARS_BASE   ::=   [A-Z] | [a-z] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | [#x00F8-#x02FF] | [#x0370-#x037D] | [#x037F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
[127]   PN_CHARS_U   ::=   PN_CHARS_BASE | '_'
[128]   VARNAME   ::=   ( PN_CHARS_U | [0-9] ) ( PN_CHARS_U | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040] )*
[129]   PN_CHARS   ::=   PN_CHARS_U | '-' | [0-9] | #x00B7 | [#x0300-#x036F] | [#x203F-#x2040]
[130]   PN_PREFIX   ::=   PN_CHARS_BASE ((PN_CHARS|'.')* PN_CHARS)?
[131]   PN_LOCAL   ::=   (PN_CHARS_U | ':' | [0-9] | PLX ) ((PN_CHARS | '.' | ':' | PLX)* (PN_CHARS | ':' | PLX) )?
[132]   PLX   ::=   PERCENT | PN_LOCAL_ESC
[133]   PERCENT   ::=   '%' HEX HEX
[134]   HEX   ::=   [0-9] | [A-F] | [a-f]
[135]   PN_LOCAL_ESC   ::=   '\' ( '_' | '~' | '.' | '-' | '!' | '$' | '&' | "'" | '(' | ')' | '*' | '+' | ',' | ';' | '=' | '/' | '?' | '#' | '@' | '%' )

A. Internet Media Type, File Extension and Macintosh File Type

Editor's note

@@see the Turtle registration for format

The Internet Media Type (formerly known as MIME Type) for @@ is "text/shape-rules".

The information that follows has been submitted to the Internet Engineering Steering Group (IESG) for review, approval, and registration with IANA.

Type name:
application
Subtype name:
shape-rules
Required parameters:
None
Optional parameters:
@@version, @@profile
Encoding considerations:
The syntax of the @@@ Language is expressed over code points in Unicode [UNICODE]. The encoding is always UTF-8 [RFC3629].
Unicode code points may also be expressed using an \uXXXX (U+0 to U+FFFF) or \UXXXXXXXX syntax (for U+10000 onwards) where X is a hexadecimal digit [0-9A-F]
Security considerations:
@@ See appendix C?, Security Considerations as well as UTF-8, a transformation format of ISO 10646 [RFC3629] section 7, Security Considerations.
Interoperability considerations:
There are no known interoperability issues.
Published specification:
This specification.
Applications which use this media type:
@@
Additional information:
Magic number(s):
A SHACL rules file may have the string 'PREFIX' (case independent) near the beginning of the document.
File extension(s):
".srl"
Base URI:
The SHACL Rules 'BASE <IRIref>' term can change the current base URI for relative IRIrefs in the query language that are used sequentially later in the document.
Macintosh file type code(s):
"TEXT"
Person & email address to contact for further information:
@@
Intended usage:
COMMON
Restrictions on usage:
None
Author/Change controller:
The SHACL Rules 1.2 specification is a work product of the World Wide Web Consortium's Data Shapes Working Group. The W3C has change control over these specifications.

B. Security Considerations

This section is non-normative.

TODO

C. Privacy Considerations

This section is non-normative.

TODO

D. Internationalization Considerations

This section is non-normative.

TODO

E. Acknowledgements

This section is non-normative.

Many people contributed to this document, including members of the RDF Data Shapes Working Group.

F. Index

F.1 Terms defined by this specification

F.2 Terms defined by reference

G. Issue summary

There are no issues listed in this specification.

H. References

H.1 Normative references

[rdf12-concepts]
RDF 1.2 Concepts and Abstract Data Model. Gregg Kellogg; Olaf Hartig; Pierre-Antoine Champin; Andy Seaborne. W3C. 20 November 2025. W3C Working Draft. URL: https://www.w3.org/TR/rdf12-concepts/
[RFC3629]
UTF-8, a transformation format of ISO 10646. F. Yergeau. IETF. November 2003. Internet Standard. URL: https://www.rfc-editor.org/rfc/rfc3629
[shacl]
Shapes Constraint Language (SHACL). Holger Knublauch; Dimitris Kontokostas. W3C. 20 July 2017. W3C Recommendation. URL: https://www.w3.org/TR/shacl/
[shacl12-core]
SHACL 1.2 Core. Holger Knublauch; Thomas Bergwinkl; Yousouf Taghzouti; Jesse Wright. W3C. 25 November 2025. W3C Working Draft. URL: https://www.w3.org/TR/shacl12-core/
[shacl12-node-expr]
SHACL 1.2 Node Expressions. W3C. Editor's Draft. URL: https://w3c.github.io/data-shapes/shacl12-node-expr/
[sparql-query]
SPARQL Query Language for RDF. Eric Prud'hommeaux; Andy Seaborne. W3C. 15 January 2008. W3C Recommendation. URL: https://www.w3.org/TR/rdf-sparql-query/
[sparql12-query]
SPARQL 1.2 Query Language. Olaf Hartig; Andy Seaborne; Ruben Taelman; Gregory Williams; Thomas Pellissier Tanon. W3C. 22 November 2025. W3C Working Draft. URL: https://www.w3.org/TR/sparql12-query/
[turtle]
RDF 1.1 Turtle. Eric Prud'hommeaux; Gavin Carothers. W3C. 25 February 2014. W3C Recommendation. URL: https://www.w3.org/TR/turtle/
[UNICODE]
The Unicode Standard. Unicode Consortium. URL: https://www.unicode.org/versions/latest/