W3C home > Mailing lists > Public > public-data-shapes-wg@w3.org > April 2016

Re: proposed user-friendly syntax for SHACL

From: Holger Knublauch <holger@topquadrant.com>
Date: Fri, 8 Apr 2016 09:35:18 +1000
To: public-data-shapes-wg@w3.org
Message-ID: <5706EEB6.8010607@topquadrant.com>
Peter, maybe this should be wrapped into an ISSUE so that it gets 
discussed properly?

I am not against such a syntax. It may have its place in academic papers 
etc, and cover scenarios where space is scarce and Turtle snippets would 
be too verbose. It could potentially become a stand-alone deliverable of 
the WG, assuming this effort doesn't take away more critical resources.

At the same time, I believe the label "User-Friendly" is not appropriate 
here. A user-friendly syntax should be limited to easy-to-type 
characters, ideally ASCII. In your email I am not even sure that the 
characters were correctly transmitted. Maybe call it "Symbolic" Syntax? 
(Or LaTeX-friendly syntax :) )

Holger


On 1/04/2016 23:02, Peter F. Patel-Schneider wrote:
> 		A User-Friendly Syntax for Core SHACL
>
>
> This is a user-friendly syntax for the core of SHACL that tries to align
> directly with my SHACL RDF syntax.
>
>
> 	Example    				Description
>
> ∈ ex:Person ⊩ |≤27|			# there are at most 27 people
> ¹ex:child ⊩ ∋ ex:john			# child subjects include John
> ¹ex:child ⊩ ∈ ex:Person ∧ IRI		# ... are people and not blank
> ex:child² ⊩ ∈ ex:Person 		# child objects are people
> ∈ ex:Patriot ⊩ ⋹ ex:Citizen		# patriots are directly citizens
> ex:password² ⊩ ^^xs:string ∧ ℓ≤24 ∧ ℓ≥8	# passwords are between 8 and 24 long
> ex:age² ⊩ ^^xs:integer ∧ ≥0		# ages are non-negative integers
> ex:john ⊩ ex:name ∝ "^John.*" ★ 	# John's name starts with "John"
> ex:mstatus² ⊩ ∈ { ex:single ex:married ex:divorced }
> 					# three marital statuses only
> ex:Person ⊩ ex:mstatus ∝ |=1|		# people have one marital status
> ex:Person ⊩ ex:mstatus ∝ ∋ ex:married → ex:spouse ∝ |≥1|
> 					# married people have a spouse
> ex:Person ⊩ ex:mstatus ∝ ∋ ex:single → ex:spouse ∝ |≤0|
> 					# single people don't have a spouse
> ∈ ex:Person ⊩ ex:spouse ∅ ex:child ∧	# people can't marry their children
> 	ex:child ex:age ≤ ex:age ∧	# ... are older than their children
> 	ex:age ≤ ex:child⁻¹ ex:age ∧	# ... are younger than their parents
> 	ex:child⁻¹ ex:child ∝ |≤9| ∧	# ... have at most 8 siblings
> 	ex:name ∝ ∈ rdf:langString ∧	# ... names are lang-tagged strings
> 	ex:name ∝ ➀			# ... have only one name per language
> ∈ ex:Person ⊩
>    ( ( ex:spouse ∝ |≤0| → ex:mstatus ∝ ( |≥1| ∧ ∈{ex:single ex:divorced} ) ) ∖
>      ( ex:spouse ∝ |≤1| → ex:mstatus ∝ ( |≥1| ∧ ∈{ex:married} ) ) ∖
>      |≤3| ∖ )      		# people with no spouse are single or divorced
> 				# people with one spouse are married
> 				# and there are at most three people left over
> ∈ ex:Isolated ⊩ ⟦ rdf:type ⟧		# isolated nodes have only types
> ∈ ex:nonIsolated ⊩ ¬ ⟦ rdf:type ⟧	# non-isolated nodes have other values
> sh:partShape ≡ (IRI ∨ sh:inverse ∝ IRI)	# parts are properties or inverses
> sh:pathShape ≡ ∈ sh:path ⊩ ( sh:partShape ∨ ⦇ sh:partShape ⦈ )
> 					# paths are parts or lists of parts
>
>
> 	Grammar					Meaning
>
> shaclDoc  ::= ( prefixID | definition ) *
>
> prefixID  ::= '@prefix' prefixName ':' IRI
>
> definition::= name '≡' shape			# refer to shape by name
> 	    | name '≡' scopedShape		# refer to shape by name
>
> scopedShape ::= scope ( '∪' scope )* '⊩' shape
> 		# set of all nodes in any scope validates against shape
>
> scope	  ::= value				# the value
> 	    | '∈' class				# SHACL instances of class
> 	    | '¹' property			# subjects of property
> 	    | property '²'			# objects of property
> 	    | '¹' '?'				# all subjects
> 	    | '?' '²'				# all objects
>
> shape	  ::= ( filter ( '∧' filter )* '→' )? component ( '∧' component )*
> 		# set of nodes that validate against all filters
> 		# validates against each component
>
> filter	  ::= component				# nodes that validate vs shape
>
> component ::= name				# validate against named shape
> 	    | '¬' component			# doesn't validate ag. comp.
> 	    | '∈' class ( '∪' class )*		# SHACL instance of some class
> 	    | '^^' datatype ( '∪' datatype )*	# has one of datatypes
> 	    | '∈' '{' value* '}'		# is one of values
> 	    | '⋹' class  			# has rdf:type of class
> 	    | 'ℓ' '≤' nonnegativeInteger 	# maximum string length
> 	    | 'ℓ' '≥' nonnegativeInteger 	# minimum string length
> 	    | '>' literal			# exclusive minimum
> 	    | '≥' literal			# inclusive minimum
> 	    | '<' literal			# exclusive maximum
> 	    | '≤' literal			# inclusive maximum
> 	    | 'IRI' | 'Literal' | 'BlankNode'	# kind of node
> 	    | regex '★' ( string )?		# matches pattern (with flags)
> 	    | path '=' path			# path values the same
> 	    | path '∅' path			# path values disjoint
> 	    | path '<' path			# path1 values < path2 values
> 	    | path '≤' path			# path1 values ≤ path2 values
> 	    | path '∝' component		# path values in shape
> 	    | '⦇' shape '⦈'			# list members in shape
> 	    | '⟦' pathpart * '⟧'		# no other property has values
> 	    | '∋' value				# set contains value
> 	    | '|' '≥' nonnegativeInteger '|'	# minimum size of set
> 	    | '|' '≤' nonnegativeInteger '|'	# maximum size of set
> 	    | '|' '=' nonnegativeInteger '|'	# exact size of set
> 	    | '➀'				# only one value per language
> 	    | '(' shape ')'			# validate against shape
> 	    | '(' component ('∨'component)+ ')'	# validate against one or more
> 	    | '(' ( component '∖' ) + ')'	# partition - see below
> 		# The initial remnant is the entire set being validated.
> 		# The next remnant is the subset of the current one that fails
> 		# to validate against the filter of the respective component.
> 		# The final remnant is empty.
> 		# Each remnant validates against the respective component.
> ⦅
>
> path	  ::= pathpart +			# composition
> pathpart  ::= property
> 	    | property '⁻¹'			# inverse of property
>
> class	  ::= name				# a class
> datatype  ::= name				# a datatype
> property  ::= name				# a property
> value	  ::= name | literal			# object
>
> regex	  ::= string				# regular expression
>
> name      ::= qname			# NOTE: no <IRI> here, just qnames
> qname	  ::= prefixName ':' name
> IRI	  ::= '<' ucharacter '>'
>
> prefixName		as per Turtle
> name			as per Turtle
> literal   		as per Turtle
>
> string			as per usual
> nonnegativeInteger	as per usual
>
>
>
> 	Possible Tweaks
>
> It would be possible to modify the syntax to come up with a more standard
> treatment of conjunction, disjunction, and negation but that syntax would
> not align as closely with the RDF syntax.
Received on Thursday, 7 April 2016 23:35:53 UTC

This archive was generated by hypermail 2.4.0 : Friday, 17 January 2020 19:30:31 UTC