manchester¶
Evaluate Manchester syntax
This module compiles restrictions and logical constructs in Manchester
syntax into Owlready2 classes. The main function in this module is
manchester.evaluate(), see its docstring for usage example.
Pyparsing is used under the hood for parsing.
ManchesterError (EMMOntoPyException)
¶
Raised on invalid Manchester notation.
Source code in ontopy/manchester.py
class ManchesterError(EMMOntoPyException):
"""Raised on invalid Manchester notation."""
evaluate(ontology, expr)
¶
Evaluate expression in Manchester syntax.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ontology |
Ontology |
The ontology within which the expression will be evaluated. |
required |
expr |
str |
Manchester expression to be evaluated. |
required |
Returns:
| Type | Description |
|---|---|
Construct |
An Owlready2 construct that corresponds to the expression. |
Examples:
from ontopy.manchester import evaluate from ontopy import get_ontology emmo = get_ontology().load()
restriction = evaluate(emmo, 'hasPart some Atom') cls = evaluate(emmo, 'Atom') expr = evaluate(emmo, 'Atom or Molecule')
Note
Logical expressions (with not, and and or) are supported as
well as object property restrictions. For data properterties are
only value restrictions supported so far.
Source code in ontopy/manchester.py
def evaluate(ontology: owlready2.Ontology, expr: str) -> owlready2.Construct:
"""Evaluate expression in Manchester syntax.
Args:
ontology: The ontology within which the expression will be evaluated.
expr: Manchester expression to be evaluated.
Returns:
An Owlready2 construct that corresponds to the expression.
Example:
>>> from ontopy.manchester import evaluate
>>> from ontopy import get_ontology
>>> emmo = get_ontology().load()
>>> restriction = evaluate(emmo, 'hasPart some Atom')
>>> cls = evaluate(emmo, 'Atom')
>>> expr = evaluate(emmo, 'Atom or Molecule')
Note:
Logical expressions (with `not`, `and` and `or`) are supported as
well as object property restrictions. For data properterties are
only value restrictions supported so far.
"""
# pylint: disable=invalid-name
def _parse_literal(r):
"""Compiles literal to Owlready2 type."""
if r.language:
v = owlready2.locstr(r.string, r.language)
elif r.number:
v = r.number
else:
v = r.string
return v
# pylint: disable=invalid-name,no-else-return,too-many-return-statements
# pylint: disable=too-many-branches
def _eval(r):
"""Recursively evaluate expression produced by pyparsing into an
Owlready2 construct."""
def fneg(x):
"""Negates the argument if `neg` is true."""
return owlready2.Not(x) if neg else x
if isinstance(r, str): # r is atomic, returns its owlready2 repr
return ontology[r]
neg = False # whether the expression starts with "not"
while r[0] == "not":
r.pop(0) # strip off the "not" and proceed
neg = not neg
if len(r) == 1: # r is either a atomic or a parenthesised
# subexpression that should be further evaluated
if isinstance(r[0], str):
return fneg(ontology[r[0]])
else:
return fneg(_eval(r[0]))
elif r.op: # r contains a logical operator: and/or
ops = {"and": owlready2.And, "or": owlready2.Or}
op = ops[r.op]
if len(r) == 3:
return op([fneg(_eval(r[0])), _eval(r[2])])
else:
arg1 = fneg(_eval(r[0]))
r.pop(0)
r.pop(0)
return op([arg1, _eval(r)])
elif r.objProp: # r is a restriction
if r[0] == "inverse":
r.pop(0)
prop = owlready2.Inverse(ontology[r[0]])
else:
prop = ontology[r[0]]
rtype = r[1]
if rtype == "Self":
return fneg(prop.has_self())
r.pop(0)
r.pop(0)
f = getattr(prop, rtype)
if rtype == "value":
return fneg(f(_eval(r)))
elif rtype in ("some", "only"):
return fneg(f(_eval(r)))
elif rtype in ("min", "max", "exactly"):
cardinality = r.pop(0)
return fneg(f(cardinality, _eval(r)))
else:
raise ManchesterError(f"invalid restriction type: {rtype}")
elif r.dataProp: # r is a data property restriction
prop = ontology[r[0]]
rtype = r[1]
r.pop(0)
r.pop(0)
f = getattr(prop, rtype)
if rtype == "value":
return f(_parse_literal(r))
else:
raise ManchesterError(
f"unimplemented data property restriction: "
f"{prop} {rtype} {r}"
)
else:
raise ManchesterError(f"invalid expression: {r}")
grammar = manchester_expression()
return _eval(grammar.parseString(expr, parseAll=True))
manchester_expression()
¶
Returns pyparsing grammar for a Manchester expression.
This function is mostly for internal use.
See also: https://www.w3.org/TR/owl2-manchester-syntax/
Source code in ontopy/manchester.py
def manchester_expression():
"""Returns pyparsing grammar for a Manchester expression.
This function is mostly for internal use.
See also: https://www.w3.org/TR/owl2-manchester-syntax/
"""
# pylint: disable=global-statement,invalid-name,too-many-locals
global GRAMMAR
if GRAMMAR:
return GRAMMAR
# Subset of the Manchester grammar for expressions
# It is based on https://www.w3.org/TR/owl2-manchester-syntax/
# but allows logical constructs within restrictions (like Protege)
ident = pp.Word(pp.alphas + "_:-", pp.alphanums + "_:-", asKeyword=True)
uint = pp.Word(pp.nums)
alphas = pp.Word(pp.alphas)
string = pp.Word(pp.alphanums + ":")
quotedString = (
pp.QuotedString('"""', multiline=True) | pp.QuotedString('"')
)("string")
typedLiteral = pp.Combine(quotedString + "^^" + string("datatype"))
stringLanguageLiteral = pp.Combine(quotedString + "@" + alphas("language"))
stringLiteral = quotedString
numberLiteral = pp.pyparsing_common.number("number")
literal = (
typedLiteral | stringLanguageLiteral | stringLiteral | numberLiteral
)
logOp = pp.one_of(["and", "or"], asKeyword=True)
expr = pp.Forward()
restriction = pp.Forward()
primary = pp.Keyword("not")[...] + (
restriction | ident("cls") | pp.nested_expr("(", ")", expr)
)
objPropExpr = (
pp.Literal("inverse")
+ pp.Suppress("(")
+ ident("objProp")
+ pp.Suppress(")")
| pp.Literal("inverse") + ident("objProp")
| ident("objProp")
)
dataPropExpr = ident("dataProp")
restriction <<= (
objPropExpr + pp.Keyword("some") + expr
| objPropExpr + pp.Keyword("only") + expr
| objPropExpr + pp.Keyword("Self")
| objPropExpr + pp.Keyword("value") + ident("individual")
| objPropExpr + pp.Keyword("min") + uint + expr
| objPropExpr + pp.Keyword("max") + uint + expr
| objPropExpr + pp.Keyword("exactly") + uint + expr
| dataPropExpr + pp.Keyword("value") + literal
)
expr <<= primary + (logOp("op") + expr)[...]
GRAMMAR = expr
return expr