#!/usr/bin/python3 from lark import Lark, InlineTransformer, inline_args import sys, re from owlready2 import * grammar=r''' start : ontologia "."? ontologia : "ontologia"i ID (conceitos | relacoes | individuos| triplos)* conceitos : "conceitos"i "{" conceito ("," conceito )* "}" relacoes : ("relacoes"i|"relações"i) "{" relacao ("," relacao )* "}" individuos : ("individuos"i|"indivíduos"i) "{" individuo ("," individuo)* "}" triplos : "triplos"i "{" triplo* "}" conceito : id | id "[" dataprops "]" -> conceito_2 dataprops : (id ":" type ","? )+ type : id relacao : id | id "/" id -> relacao_inv individuo : id | id "=" id -> individuo1 | id "=" id "[" (id ":" val ","? )+ "]" -> individuo2 triplo : id "=" (id "=>" val ","? )+ ";" | id "=" "iof" "=>" id ( "[" (id (":"|"=") val ","? )+ "]" )? ";" -> individuo2 val : id -> id | STR -> id | TOK -> id id : ID ID .3 : /\w+(-\w+)*/ STR .1 : /"([^"])*"|"""(.|\n)*?"""/ TOK .1 : /'([^'])*'/ WS .1 : /[ \t\n]/ COMS .3 : /#.*/ %ignore COMS %ignore WS ''' def l2dict(v): return dict(zip(v[0::2],v[1::2])) ## list to dict def l2lofpairs(v): return zip(v[0::2],v[1::2]) ## list to listOfPairs def norm(c): a=re.sub(r'\W','_',c.strip()) a=re.sub(r'^_|_$','',a) return a def norm2(c): if re.match(r'["\'0.9]',c): return c else: return re.sub(r'\W','_',c.strip()) class CalculateOnto(InlineTransformer): def ontologia(self,name,*v): self.onto["meta"]["name"]=name def __init__(self) : self.onto = { "meta":{"name":None}, "con":{}, "datap":{}, "rel": {}, ##FIXME {"is-a":{},"iof":{},"pof":{}}, "inv":{}, "ind":{}, "tri":{}} def start(self,o): return(self.onto) def id(self,i): return str(i) def dataprops(self, *v): return l2dict(v) def type(self, v): return v def individuo(self,c): nc = norm(c) self.onto["ind"][nc] ={"dataprop":{}, "owl": f''' {nc} = Thing("{nc}") '''} return c def individuo1(self,c1,c2): nc1 = norm(c1) nc2 = norm(c2) self.onto["ind"][nc1] ={"dataprop":{}, "owl": f''' {nc1} = {nc2}("{nc1}") '''} return c1 def individuo2(self,c1,c2,*p): nc1 = norm(c1) nc2 = norm(c2) x=l2dict(p) ## FIXME continuar self.onto["ind"][nc1] ={"dataprop":{}, "owl": f''' {nc1} = {nc2}("{nc1}") '''} for a in x: add_triplo(self,c1,a,x[a]) return c1 def relacao(self,c): nc=norm(c) self.onto["rel"][nc] ={"objprop":{}, "owl": f''' class {nc}(ObjectProperty): pass '''} return c def relacao_inv(self,i1,i2): ni1=norm(i1) ni2=norm(i2) self.onto["inv"][ni2] = i1 self.onto["inv"][ni1] = i2 self.onto["rel"][ni1] ={"objprop":{}, "owl": f''' class {ni1}(ObjectProperty): pass '''} self.onto["rel"][ni2] ={"objprop":{}, "owl": f''' class {ni2}(ObjectProperty): pass {ni1}.inverse_property = {ni2} {ni2}.inverse_property = {ni1} '''} return (i1,i2) def triplo(self,i1,i2,i3,*p): add_triplo(self,i1,i2,i3) for x,y in l2lofpairs(p): add_triplo(self,i1,x,y) return (i1,i2,i3,p) def conceito(self,c): self.onto["con"][c] ={"dataprop":{}, "owl": f''' class {c}(Thing):pass '''} return c def conceito_2(self, c, p): self.onto["con"][c] ={"dataprop":p, "owl": f''' class {c}(Thing):pass '''} for x in p: x=norm(x) if x not in self.onto["datap"]: self.onto["datap"][x]={"domain":{},"range":{}} self.onto["datap"][x]["domain"][c]=1 self.onto["datap"][x]["range"][p[x]]=1 self.onto["datap"][x]["owl"]= f''' class {x}(DataProperty, FunctionalProperty):pass # domain = {c} # range = {p[x]} ''' return c def add_triplo(self,s,p,o): ns=norm(s) np=norm(p) no=norm2(o) if (ns not in self.onto["con"] and ns not in self.onto["ind"]) : print(f"ERROR: {ns} desconhecido") if (np not in self.onto["rel"] and np not in self.onto["datap"] and np not in ["is_a","iof","pof"]): print(f"Err: rel {np} desconhecido") if (no not in self.onto["con"] and no not in self.onto["ind"] and not re.match(r'["\'0-9]',no)) : print(f"ERROR: {no} desconhecido") if ( p in self.onto["datap"] and ns in self.onto["ind"] ): self.onto["tri"][(ns,np,o)] = {"owl": f''' {ns}.{np} = {o} '''} else: self.onto["tri"][(ns,np,no)]={"owl": f''' {ns}.{np}.append({no}) #FIXME {ns}.{np}.append({o}) '''} parser = Lark(grammar, parser='lalr', transformer=CalculateOnto()) ONTO = "nada" def pexec(x): print(x) def gera(ont): ONTO = get_ontology(ont["meta"]["name"]) ONTO.name = ont["meta"]["name"] ONTO.base_iri = "" ## "ol:" with ONTO: class iof(ObjectProperty): pass class is_a(ObjectProperty): pass class pof(ObjectProperty): pass for c in ont["con"]: exec(f"""with ONTO: {ont["con"][c]["owl"]} """) for c in ont["rel"]: exec(f"""with ONTO: {ont["rel"][c]["owl"]} """) for c in ont["datap"]: exec(f"""with ONTO: {ont["datap"][c]["owl"]} """) for c in ont["ind"]: exec(f"""with ONTO: {ont["ind"][c]["owl"]} """) for c in ont["tri"]: exec(f"""with ONTO: {ont["tri"][c]["owl"]} """) # with ONTO: # sync_reasoner() ONTO.save(file= f"ONT-{ont['meta']['name']}") def main(): with open(sys.argv[1],"r") as f: p=parser.parse(f.read()) gera(p) if __name__ == '__main__': main() # print(p.pretty())