import Prelude as pre import Resource as r import Utils as utils import Triple as tr import RDFDB, time import sys, PVa, N3Http, string, copy import InfData, Param, os from Tkinter import * import tkMessageBox class N3Parser: """ This parses a notation3 file. function interact() permits to do this in an interactive way. Function getRDFDB() returns a RDFDB object that contains all the structures for inferencing. It needs as input an infData object that keeps track of persistent data. originList is class data too. It keeps track of the origin of all triples. """ # the dictionary that contains the prefixes prefixDictionary = {":":"http://www.test#"} # get the file prefix pers = PVa.PersistentString("pathPrefix.txt") filePrefix = os.getcwd() + "\\" + pers.get() # get the proxy # proxy with authentication: put the proxy address and port in # "proxy.txt" and the userid and password (userid:password) in # the file "userPass.txt" # for proxy without authentication put "noAuth" # in the file "proxy.txt" and put the address and port number of # the proxy in the environment variable "http-proxy". # both files should exist. # if no proxy is required, leave the files empty. pr = PVa.PersistentString("proxy.txt") proxy = pr.get() # get the proxy userid and password pr1 = PVa.PersistentString("userPass.txt") userPass = pr1.get() # proxy flag 0 = proxy with authentication; 1 = no proxy; # 2 = proxy without authentication authProxy = 0 # the internet access object http = N3Http.N3Http() # parameter for length error output errLength = 50 # # the list of testcases testCases = ["project.a.n3","project.q.n3", "http://www.w3.org/2002/03owlt/ontAx.n3", "animal-result.n3","animal-simple.n3", "animal.n3", "authen.axiom.n3", "authen.lemma.n3", "authen.proof.n3", "danb-query.n3", "danb-result.n3", "danb.n3", "danc-query.n3", "danc-result.n3", "danc.n3", "etc.n3", "gedcom-facts.n3", "gedcom-proof.n3", "gedcom-query.n3", "gedcom-relations-result.n3", "gedcom-relations-test.n3", "gedcom-relations.n3", "graph.axiom.n3", "graph.lemma.n3", "graph.proof.n3", "janet-result.n3", "janet-test.n3", "janet.n3", "lists-query.n3", "lists-result.n3", "lists.n3", "vogel.q.n3", "rdf-facts.n3", "rdf-query.n3", "rdf-result.n3", "rdf-rules.n3", "rdfc25May-result.n3", "rdfc25May-test.n3", "rdfc25May.n3", "rdfs-query.n3", "rdfs-result.n3", "rdfs-rules.n3", "russell.axiom.n3", "russell.lemma.n3", "russell.proof.n3", "subclass-query.n3", "subclass-result.n3", "subclass.n3", "subprop-query.n3", "subprop-result.n3", "subprop.n3", "test-result.n3", "test-test.n3", "test.n3", "tpoint-all.n3", "tpoint-facts.n3", "tpoint-query.n3", "tpoint-result.n3", "tpoint.n3", "varprop-query.n3", "varprop-result.n3", "varprop.n3", "ziv-query.n3", "ziv-result.n3", "ziv.n3", "wol-facts.n3", "wol-query.n3", "wol-rules.n3", "VOGEL.N3", "vogel.l.n3", "boole.lemma.n3", "boole.axiom.n3", "induction.axiom.n3", "induction.query.n3", "allValuesFrom.n3", "Owls.n3"] def __init__(self, proxy = ""): if proxy == " " or proxy == "": authProxy = 1 elif proxy == "noAuth": authProxy = 2 # the error list self.errorlist = [] # flag signaling an error during parser self.errorflag = "F" # flag whether this is a query or not self.queryFlag = "T" # an RDFDB Object self.tripleset = RDFDB.RDFDB() # reverse list of resources # permits to get a resource by number. The number of the resource # is the index in the list minus 1 # this list is a list of resources. self.revres = [] # dictionary of resources; index is a resource full label # content is a pair (nr, resource) self.resdic = {} # the list of origins. # the position in the list is added to each triple self.originList = [] # detection of: " .. is .. of ... " # a counter for assigning anonymous subjects self.anonCounter = 0 # a counter for tranforming local variables into global variables self.locCounter = 0 # a counter for instantiating existential variables self.existCounter = 0 # a debug flag self.debug = 1 # flag for directing the output self.saveOnDisk = 0 # the name of the file that is being parsed self.fileName = "" # structures for inferencing # dictionary with access based on predicate number except for variable predicates self.infDB = {} # list of triples with variable predicates self.varPred = [] self.revres = [] self.resdic = {} self.currRes = 1000 self.resStart = 1000 self.originList = [] # a counter for assigning anonymous subjects self.anonCounter = 1 # a counter for tranforming local variables into global variables self.locCounter = 1 # a counter for instantiating existential variables self.existCounter = 1 # when full_generation = 1, only "simple" resources are generated i.e. with the list # attribute = []. E.g. :a :b {:s :p :o} becomes : :a :b :s. :s :p :o. # This parameter will generate different results in the inference engine. self.full_generation = 0 # counter for lists self.listCounter = 1 # counter for rules self.ruleNr = 1 # read a N3 file into a string def readN3(self, fileName): inFile = open(fileName,"r") self.n3String = inFile.read() inFile.close() def analyzeOWL(self): """ This function makes an analysis for OWL and creates an OWL object """ pass def genFull(self): """ this generates extra triples so that only 'simple' resources rest. (for a simple resource the attribute 'list' = [] """ out = [] for t in self.tripleset.db: if t.subject.simple == "F": for t1 in t.subject.list: out.append(t1) h = copy.deepcopy(t) h.subject = t1.object out.append(h) elif t.object.simple == "F": for t1 in t.object.list: h = copy.deepcopy(t) out.append(t1) h.object = t1.subject out.append(h) else: out.append(t) self.tripleset.db = out def getRDFDB(self, fileName, infData): """ getRDFDB return an RDFDB object containing all the necessary data structures for inferencing. infData contains global inferencing data that is needed """ self.revres = infData.revres self.resdic = infData.resdic self.currRes = infData.currRes self.originList = infData.originList # a counter for assigning anonymous subjects self.anonCounter = infData.anonCounter # a counter for tranforming local variables into global variables self.locCounter = infData.locCounter # a counter for instantiating existential variables self.existCounter = infData.existCounter # a counter for naming lists format: (res1 ...resn) self.listCounter = infData.listCounter self.ruleNr = infData.ruleNr self.parseAFile(fileName) if self.errorflag == "T": self.writeOutput1() (infDB, varPred) = makePredDic(self.tripleset.db, self.ruleNr) self.tripleset.infDB = infDB self.tripleset.varPred = varPred self.tripleset.prefixDictionary = self.prefixDictionary infData.revres = self.revres infData.resdic = self.resdic infData.currRes = self.currRes infData.resStart = Param.resStart infData.originList = self.originList # a counter for assigning anonymous subjects infData.anonCounter = self.anonCounter # a counter for tranforming local variables into global variables infData.locCounter = self.locCounter # a counter for instantiating existential variables infData.existCounter = self.existCounter # a counter for naming lists format: (res1 ...resn) infData.listCounter = self.listCounter infData.ruleNr = self.ruleNr return (self.tripleset, infData) def testGetRDFDB(self,fileName): """ test the function getRDFDB """ (ts, infData) = self.getRDFDB(fileName, InfData.InfData()) print ts.toString() def writeOutput1(self): """ write output for the gui procedure """ root = Tk() #root.protocol("WM_DELETE_WINDOW", root.destroy()) textw = Text(root) textw.config(background = "LightYellow", font = "Times 14") textw.pack() textw.insert(INSERT,"ERRORFILE " + self.fileName +\ "\n=========================\n\n") for line in self.errorlist: textw.insert(INSERT, line + "\n") # function for entering a number # the input string is displayed as prompt def enterNumber(self, s): done = 0 while (not done): try: i = input(s) done = 1 except: print("Please enter a number.\n") return i # interactive part def interact(self): self.printMenu() i = -1 while (not i == 0): try: prefixDictionary = {":":""} i = self.enterNumber("") if i == 0: print ("\nThe program is stopped.") return elif i == 1: print "The testcases must be in a directory named \"testCases\"." print "The path prefix for this directory must be in the file:" print "\"pathPrefix.txt\" (with trailing slash)." elif i == 2: print "Please enter the name of the file to be parsed:" print "For access to the web please enter a complete url." print "For a file just give the absolute or relative path." self.fileName = raw_input("") if (utils.startsWith(self.fileName,"http://")== "T"): self.readUrl(self.fileName) else: self.readN3(self.fileName) self.parseN3(self.n3String) self.writeOutput() elif i == 3: print "Do you want to save the output to disk?" print "The filename will be: input_filename + .pr." print "Answer Y or N." s = raw_input("") done = 0 while (not done ): if s == "Y": self.saveOnDisk = 1 print ("!!!! Output will be to disk. !!!!!") done = 1 elif s == "N": self.saveOnDisk = 0 done = 1 print ("!!!! Output will be to the screen. !!!!!") else: s = raw_input("Please enter Y or N.\n") elif i == 4: self.choiceTestCases() i = self.enterNumber("") li = self.testFiles(i) p = makePredDic(self.tripleset.db, self.ruleNr) printPredicates(p[0], p[1]) self.writeOutput() self.__init__() elif i == 5: print "Proxy with authentication: put the proxy address and port in" print " \"proxy.txt\" and the userid and password (userid:password) in" print " the file \"userPass.txt\"." print " For a proxy without authentication put \"noAuth\"" print " in the file \"proxy.txt\" and put the address and port" print " number of the proxy in the environmnet variable:" print " \"http-proxy\"." print " If no proxy is required leave the files empty." print " Both files should exist." elif i == 6: print "Create the parameter files (see items 1 and 5 of the menu)." print " 1) create the file \"pathPrefix.txt\"" print " 2) create the file \"proxy.txt\"" print " 3) create the file \"userPass.txt\"" print " 4) stop" print "Please enter a number." i = self.enterNumber("") print "Please enter the content of the file:" while i < 4: if i == 1: print "pathPrefix.txt" fileName = "pathPrefix.txt" elif i == 2: print "proxy.txt" fileName = "proxy.txt" elif i == 3: print "userPass.txt" fileName = "userPass.txt" s = raw_input("") if s == "": s = " " file = PVa.PersistentString(fileName) file.modify(s) self.printMenu() except IOError, (errno, strerror): print "I/O error(%s): %s" % (errno, strerror) print("Please retry.") self.printMenu() return def testParseAFile(self): print "testParseAFile" bool = self.parseAFile(self.filePrefix + "testCases/authen.axiom.n3") if bool == "F": print "!!!PARSING DID NOT SUCCEED!!!" self.errorflag = "T" self.writeOutput() self.errorlist = [] def parseAFile(self, fileName): if (utils.startsWith(fileName,"http://") == "T"): self.readUrl(fileName) else: self.readN3(fileName) bool = self.parseN3(self.n3String) return bool # write the output to screen or to disk def writeOutput(self): def callback(): if tkMessageBox.askokcancel("Quit",\ "Do you really wish to quit?"): textw.destroy() root.destroy() self.interact() return if self.saveOnDisk == 0: root = Tk() root.protocol("WM_DELETE_WINDOW", callback) textw = Text(root) textw.config(background = "LightYellow", font = "Times 14") textw.pack() textw.delete(1.0,END) textw.insert(INSERT,"ERRORFILE\n=========================\n\n") if self.errorflag == "T": textw.insert(INSERT, "!!!ERROR!!!\n An error occurred during parsing.\n\n") else: textw.insert(INSERT,"\n!!! No errors were detected.\n\n") for line in self.errorlist: textw.insert(INSERT, line + "\n") #root.mainloop() print "\n\nParsed triples\n==========================\n\n" print self.tripleset.toString() print "\n\nDictionary\n===============================\n\n" print ("Dictionary:",self.prefixDictionary) print "\n *** parsing time: ", self.parseTime else: outFile = open(self.fileName + ".pr", "w") outFile.write("Dictionary:" + `self.prefixDictionary` + "\n\n") outFile.write("ERRORFILE " + self.fileName +\ "\n=========================\n\n") for line in self.errorlist: outFile.write(line + "\n") outFile.close() # handling of the test cases def testFiles(self, i): web = 0 n = 0 n1 = len(self.testCases) done = 0 while not done and n ""): s = utils.skipBlancs1(s) line = "" if s[0] == "#": # comment p = self.parseComment(s[1:]) if p == []: self.errorflag = "T" (bool, line, s) = self.synchronize(s) if bool == "F": print "Parsed = " + line return "F" else: print "!!!error parsing comment!!!" + line + "!!!!END" self.errorlist.append("/@/!!!error!!! parsing comment!!!. Line: " + line + "!!!!END\n") else: (line, s) = p[0] print "#" + line self.errorlist.append("#" + line) else: # parse parameter or prefix or bind or triple if utils.startsWith(s, "@param") == "T": # format: @param name value. p = self.parseParam(s) if p == []: self.errorflag = "T" (bool, line, s) = self.synchronize(s) if bool == "F": print "Parsed = " + line return "F" else: print "!!!error parsing param!!!" + line self.errorlist.append("/@/!!!error!!! parsing param!!!. Line: " + line + "/@/END\n") else: rest = pre.snd(p[0]) l1 = len(s) l2 = len(rest) l1 = l1 - l2 line = s[0:l1] print line s = rest t = pre.fst(p[0]) self.tripleset.addTriple(t) self.errorlist.append(line) elif s[0] == "@": p = self.parsePrefix(s) if p == []: self.errorflag = "T" (bool, line, s) = self.synchronize(s) if bool == "F": print "Parsed = " + line return "F" else: print "!!!error parsing prefix!!!" + line self.errorlist.append("/@/!!!error!!! parsing prefix!!!. Line: " + line + "/@/END\n") else: rest = pre.snd(p[0]) l1 = len(s) l2 = len(rest) l1 = l1 - l2 line = s[0:l1] print line s = rest t = pre.fst(p[0]) self.tripleset.addTriple(t) self.errorlist.append(line) elif utils.startsWith(s, "bind") == "T": p = self.parseBind(s) if p == []: self.errorflag = "T" (bool, line, s) = self.synchronize(s) if bool == "F": print "Parsed = " + line return "F" else: print "!!!error parsing bind!!!" + line self.errorlist.append("/@/!!!error!!! parsing bind!!!. Line: " + line + "/@/END\n") else: rest = pre.snd(p[0]) l1 = len(s) l2 = len(rest) l1 = l1 - l2 line = s[0:l1] print line s = rest t = pre.fst(p[0]) self.tripleset.addTriple(t) self.prefixDictionary[t.subject.label] = t.object.label self.errorlist.append(line) else: # parse a triple tl = self.parseTriple(s) if tl == []: self.errorflag = "T" (bool, parsed, s) = self.synchronize(s) if bool == "F": print "Parsed = " + line return "F" else: self.errorlist.append("/@/!!!error!!! parsing triple!!!. Line: " + parsed + "/@/END\n") else: [(ts, rest)] = tl l1 = [] for tr in ts: (tr, list) = self.addGlobalVariables(tr, []) l1 = l1 + [tr] ts = l1 self.tripleset.addTriples(ts) l1 = len(s) l2 = len(rest) l1 = l1 - l2 line = s[0:l1] self.errorlist.append(line + ".") print line + "." rest = utils.skipBlancs(rest) # skip dot if rest[0] == ".": s = rest[1:] else: s = rest s = utils.skipBlancs(s) s = utils.skipBlancs1(s) if self.full_generation: self.genFull() #self.tripleset.db = tr.elimDoubles(self.tripleset.db) return "T" # synchronize: parse the input string till the first dot def synchronize(self, s): # parse s till the first dot (bool, parsed, rest) = utils.parseUntilString(s,".") print "SYNCHRONIZING !!!!!!!!!!!!!!" if bool == "F": print "!!! MAJOR ERROR -- MISSING POINT NO SYNCHRONIZATION POSSIBLE" print "PARSING ABORTED!!!" return ("F", s, "") else: return ("T", parsed + ".", utils.skipBlancs1(rest[1:])) def synchronize1(self, s, char): # parse s till char is met (bool, parsed, rest) = utils.parseUntilString(s,char) if bool == "F": return ("F", s, "") else: return ("T", parsed + ".", utils.skipBlancs1(rest[1:])) def parseComment(self, s): # function for parsing comment. # input is the string to be parsed. # the comment goes till "\r\n" is encountered. # returns the comment and the rest string if len(s) == 0: return ("", "") else: (bool, comment, rest) = utils.parseUntilString (s, "\n") if bool == "T": return [(comment, utils.skipBlancs(rest[1:]))] else: (bool, comment, rest) = utils.parseUntilString (s, "\r") if bool == "T": return [(comment, utils.skipBlancs(rest[1:]))] else: return [] def testParseComment(self): self.parseN3("# blabla\n gaga") print self.errorlist self.errorlist = [] self.parseN3("# blabla gaga. tata.") print self.errorlist self.errorlist = [] self.parseN3("# blabla gaga tata") print self.errorlist def testParsePrefix(self): self.parseN3("@prefix blabla\n gaga") print self.errorlist self.errorlist = [] self.parseN3("@prefix c: http:# blabla gaga. tata.") print self.errorlist self.errorlist = [] self.parseN3("@prefix c: .# blabla gaga tata.\n") print self.errorlist def testParseBind(self): self.parseN3("bind blabla\n gaga") print self.errorlist self.errorlist = [] self.parseN3("bind c: http:# blabla gaga. tata.") print self.errorlist self.errorlist = [] self.parseN3("bind c: .# blabla gaga tata.\n") print self.errorlist def testParseTriple(self): print "testParseTriple:\n" p = self.parseTriple (":s :p [:a :b],[:c :d], [:e :f].") if p == []: print "failure parsing: " + ":s :p [:a :b],[:c :d], [:e :f].\n" else: print "parsing: " + ":s :p [:a :b],[:c :d], [:e :f].\n" [(tl, rest)] = p print "triple = \n" + tr.tsToString(tl) + "\nrest = " + rest + "\n" p = self.parseTriple (":a :b :c.") if p == []: print "failure parsing: " + ":a :b :c.\n" else: print "parsing: " + ":a :b :c.\n" [(tl, rest)] = p print "triple = \n" + tr.tsToString(tl) + "\nrest = " + rest + "\n" p = self.parseTriple ("{:a :b :c.:d :e :f.} :g :h.") if p == []: print "failure parsing: " + "{:a :b :c.:d :e :f.} :g :h.\n" else: print "parsing: " + "{:a :b :c.:d :e :f.} :g :h.\n" [(tl, rest)] = p print "triple = \n" + tr.tsToString(tl) + "\nrest = " + rest + "\n" p = self.parseTriple ("[:b :c;[:d :e; :m :n] :r] :g :h.") if p == []: print "failure parsing: " + "[:b :c;[:d :e; :m :n] :r] :g :h.\n" else: print "parsing: " + "[:b :c;[:d :e; :m :n] :r] :g :h.\n" [(tl, rest)] = p print "triple = \n" + tr.tsToString(tl) + "\nrest = " + rest + "\n" p = self.parseTriple ("{:person :member :institution." + ":institution :w3cmember ." + ":institution :subscribed :mailinglist} :implies" + "{:person :authenticated :mailinglist}.") if p == []: print ("failure parsing: " + "{:person :member :institution." + ":institution :w3cmember ." + ":institution :subscribed :mailinglist} log:implies" + "{:person :authenticated :mailinglist}.") else: print ("parsing: " + "{:person :member :institution." + ":institution :w3cmember ." + ":institution :subscribed :mailinglist} log:implies" + "{:person :authenticated :mailinglist}.") [(tl, rest)] = p print "triple = \n" + tr.tsToString(tl) + "\nrest = " + rest + "\n" # test the function parseTripleSet. def testParseTripleSet(self): print("\ntestParseTripleSet\n******************") print (( "", "{:a :b :c.}", 0), self.parseTripleSet("", "{:a :b :c.}", 0)) print (( "", "{{:a :b :c. :d :d :f} :g" + " {:h :i :j. :k :l :m}}", 0), self.parseTripleSet("", "{{:a :b :c. :d :d :f} :g" + " {:h :i :j. :k :l :m}}", 0)) print (("", "{{:a :b :c} :d :e}", 0), self.parseTripleSet("", "{{:a :b :c} :d :e}", 0)) print (( "", "{:a :b :c}", 0),self.parseTripleSet( "", "{:a :b :c}", 0)) print (("", "{:a :b :c. :d :e :f.}", 0), self.parseTripleSet("", "{:a :b :c. :d :e :f.}", 0)) print (("", "{:: :b :c. :d :e :f.", 0), self.parseTripleSet("", "{:: :b :c. :d :e :f.", 0)) print (("", ":a :b :c.", 0), self.parseTripleSet("", ":a :b :c.", 0)) print (("", "{:a is :b of :c.}.", 0), self.parseTripleSet("", ":a is :b of :c.}", 0)) print (("", "{:d :e :f. :a has :b of :c.}", 0), self.parseTripleSet("", ":d :e :f.:a has :b of :c.}", 0)) print (("", ":a :b :c", 0), self.parseTripleSet("", ":a :b :c", 0)) # parse a set of triples. # Returns a tripleset and a reststring def parseTripleSet(self, ts, s): sd = utils.skipBlancs(s) if sd == "": return [(ts, s)] else: first = sd[0] # begin of set detected; check for end of set and call recursively if first == "{": tr = self.parseTriple (utils.skipBlancs(sd[1:])) if tr == []: print "!!!failure parsing triple!!! Line: " + pre.getfirst(s, self.errLength) return [] else: [(t, rest)] = tr return self.parseTripleSet (ts + t, rest) # "}" found - return. elif first == "}": return [(ts, sd[1:])] # must be the next triple : parseSubject and call parsePropertyList. elif first == ".": sd = utils.skipBlancs(sd[1:]) if sd == "": return [(ts,s)] if sd[0] == "}": return [(ts, sd[1:])] else: tr = self.parseTriple (sd) if tr == []: print "!!!failure parsing triple!!! Line: " + pre.getfirst(s, self.errLength) return [] else: [(t, rest)] = tr return self.parseTripleSet (ts + t, rest) else: print ("!!! error parsing tripleset - missing . or { or } !!!\n Line: " + pre.getfirst(s,self.errLength)) return [] # parseTriple parses a singel triple. # returns a set of triples!!! and a reststring # if inverse flag subject and object are interchanged. def parseTriple(self, s): self.inverseFlag = 0 sd = utils.skipBlancs(s) if sd == "": return [] else: first = sd[0] p = self.parseSubject (sd) if p == []: print ("!!!error on parsing subject!!!\n" + "synchronizing is done on dot. Line: " + pre.getfirst(s, self.errLength)) return [] else: [(sub, rest)] = p rest = utils.skipBlancs(rest) c = rest[0] if c == "}" or c == "]" or c == ".": if sub.list == []: return [] else: return [(sub.list, rest)] if sub.label[0:3] == ":T$$$" and self.queryFlag == "T"\ and sub.number > 0: sub.number = -sub.number p1 = self.parsePropertyList ([], rest) if p1 == []: return [] else: [(pl, rest)] = p1 # extract the verb if pl == []: print ("!!!error on parsing propertylist!!!\n" + "synchronizing is done on dot. Line: " + pre.getfirst(s, self.errLength)) return [] ts = self.makeTrSPL(sub, pl) # check for logical constants and do something ts = self.checkAnonInRule(ts) return [(ts, rest)] def checkAnonInRule(self,tl): """ Anonymous subjects in rules must be variables """ for t in tl: if t.predicate.fullname == self.log + "implies": if utils.startsWith(t.subject.label, ":T$$$") == "T"\ and t.subject.number > 0: t.subject.number = - t.subject.number return tl def addGlobalVariables(self, t, list): """ add and change the global variables in a triple call with empty list """ (list, t.subject) = self.addGlobalVariablesToRes(t.subject, list) (list, t.predicate) = self.addGlobalVariablesToRes(t.predicate, list) (list, t.object) = self.addGlobalVariablesToRes(t.object, list) return (t, list) def addGlobalVariablesToRes(self, r, list): """ add and change the global variables in a resource """ if r.simple == "F": for t in r.list: (t, list) = self.addGlobalVariables(t, list) if r.RDFList <> []: for res in r.RDFList: (res, list) = self.addGlobalVariablesToRes(res, list) if r.label == "" or (not (r.label[0] == "?")): return (list, r) i = 0 try: ltmp = [lab for (lab, n) in list] i = ltmp.index(r.label) (lab, n) = list[i] name = ":G$$$" + str(n) + lab (n1, r) = self.resdic[name] return (list, r) except: list = [(r.label, self.locCounter)] + list if not (utils.startsWith(r.label, ":G$$$") == "T"): r.label = ":G$$$" + str(self.locCounter) + r.label r.fullname = r.label self.locCounter += 1 if not self.resdic.has_key(r.label): r.number = -self.currRes self.resdic[r.label] = (self.currRes, r) self.revres.append(r) self.currRes += 1 return (list, r) def checkLogical(self, tl): """ react to log: instructions: log:forSome, log:forAll; log:Truth variable handling: variables recieve a negative number for the 'number' property or Resource the entry in revres uses the corresponding positive number local univarsal variables are transformed to global universal variables by giving them a unique name starting with ":G$$$" local existential variables are instantiated with a unique name; global existential variables are instantiated with a unique name; the name of existential variables starts with ":E$$$" Handles also the "... is ... of ..." construct. """ tlout = [] for t in tl: ## if t.predicate.isof: ## save = t.subject ## t.subject = t.object ## t.object = save if t.predicate.fullname == self.log + "forAll": if t.subject.fullname == self.getFromDictionary(":"): # this is a global universal variable # mark the object as such # do not return the triple # variables have a negative number if t.object.number > 0: t.object.number = -t.object.number t.object.varType = "gul" else: # this defines a local universal variable # transform into a global variable # the subject should be a tripleset if t.subject.simple <> "F": print "!!! error in log:forAll instruction !!!" self.errorflag = "T" else: ofullname = t.object.fullname nfullname = ":G$$$" + `self.locCounter` + ofullname t.object.fullname = nfullname self.locCounter += 1 nr = t.object.number t.object.varType = "gu" if nr > 0: t.object.number = -nr else: nr = -nr # change in revres if nr < 0: nr = -nr if nr 0: t.object.number = -nr else: # this defines a local existential variable # the subject should be a tripleset ofullname = t.object.fullname nfullname = ":E$$$" + `self.existCounter` + t.object.fullname t.object.fullname = nfullname self.existCounter += 1 nr = t.object.number t.object.varType = "ge" if nr > 0: if self.queryFlag == "T" and t.object.number > 0: t.object.number = -nr else: nr = -nr # change in revres if nr < 0: nr = -nr if nr "F": print "!!! error in log:forSome instruction !!!" self.errorflag = "T" else: tlout = tlout + t.subject.list elif t.object.fullname == self.log + "Truth": # this defines a truth; just add the subject # the subject should be a tripleset if t.subject.simple <> "F": print "!!! error in log:Truth instruction !!!" else: tlout = tlout + t.subject.list else: tlout.append(t) # now eliminate doubles in tlout return self.elimDoubles(tlout) def isIn(self, t, tl): """ check whether triple t is in triplelist tl """ if tl == []: return 0 else: if t.compare(tl[0]): return 1 else: return self.isIn(t, tl[1:]) def elimDoubles(self, tl): """ eliminate double triples in a list""" if len(tl) < 2: return tl else: if self.isIn(tl[0], tl[1:]): return self.elimDoubles(tl[1:]) else: return ([tl[0]] + self.elimDoubles(tl[1:])) # test the function parseAnonSet. def testParseAnonSet(self): print ("\ntestParseAnonSet\n****************\n") print(("", "[:b :c.].", 0), self.parseObject("", "[:b :c.].", 0)) print(( "", "[ :b :c; :e :f; :g :h, :i, :p]", 0), self.parseObject( "", "[ :b :c; :e :f; :g :h, :i, :p]", 0)) print(( "", "[ :b :c; :d [:e :f]; :g :h]", 0), self.parseObject ("", "[ :b :c; :d [:e :f]; :g :h]", 0)) # parse a set of anonymous triples : insert an anonymous subject # and call parsePropertyList. def parseAnonSet(self, as, s): if s == "": return [] else: sd = utils.skipBlancs(s) first = sd[0] # parse a set of anonymous triples: assign a subject # and then call parsePropertyList. if first == "[": subject = self.createAnonSubject() pl = self.parsePropertyList([], sd[1:]) if pl == []: print("!!!error parsing anonymous node. Line: " + pre.getfirst(s, self.errLength)\ + "!!!END\n") return [] else: [(pli, rest)] = pl ts = self.makeTrSPL(subject, pli) return self.parseAnonSet (as + ts, rest) # "]" found - insert "EndOfSet " and return. elif first == "]": return [(as, sd[1:])] # what happened? else: print("!!!error parsing anonymous node. Line: " + pre.getfirst(s, self.errLength)) return [] # make a list of triples from a subject and a propertylist def makeTrSPL(self, sub, pl): ts = [] for p in pl: (pr, ol) = p for o in ol: t = tr.Triple() if t.predicate.isof: t.subject = o t.predicate = pr t.object = sub else: t.subject = sub t.predicate = pr t.object = o ts.append(t) ts = self.checkLogical(ts) return ts # test the function parsePropertyList. def testParsePropertyList(self): print("\ntestParsePropertyList\n*******************\n") p = self.parsePropertyList([], ":b :c; :d :e; :f :g.") if p <> []: [(pl, rest)] = p print (":b :c; :d :e; :f :g. rest: " + rest + " parsed: \n" + tr.plToString(pl) + "\n") else: print ("failure parsing: :b :c; :d :e; :f :g.\n") print(":b :c.", self.parsePropertyList([], ":b :c.")) print(":b :c; :d :e; :f :g:", self.parsePropertyList([], ":b :c; :d :e; :f :g:")) print(":a, :b,:c", self.parsePropertyList([], ":a, :b,:c")) p = self.parsePropertyList([],":p [:a :b],[:c :d], [:e :f].") if p <> []: [(pl, rest)] = p print (":p [:a :b],[:c :d], [:e :f]. rest: " + rest +\ " parsed: \n" + tr.plToString(pl) + "\n") else: print ("failure parsing: :p [:a :b],[:c :d], [:e :f].\n") # parses one or more properties. # returns a list of properties: [(pl, reststring)] def parsePropertyList (self, pl, s): if s == "": return [] else: sd = utils.skipBlancs(s) first = sd[0] # end of propertyList if sd[0] == "}": return [(pl, s)] # end of propertyList elif sd[0] == ".": return [(pl, s)] # end of anonymous set elif sd[0] == "]": return [(pl, s)] # propertylist with subject already defined. elif sd[0] == ";": p = self.parseProperty (sd[1:]) else: # parse first (and maybe only) node p = self.parseProperty (sd) if pl <> []: # first property has been parsed already print "!!!missing ; while parsing propertylist!!! Line: " + pre.getfirst(s, self.errLength) return [] if p == []: return [] else: [(pr, rest)] = p if pr == "n": return [(pl,rest)] (verb, nl) = pr pl = pl + [pr] return self.parsePropertyList (pl, rest) # parse a single property. # a property is a pair (property, objectlist) # this function returns: [(property,reststring)] or [] def parseProperty(self, s): self.inverseFlag = 0 if s == "": return [] else: sd = utils.skipBlancs(s) first = sd[0] if first == "}": # possibly ;} return [("n",sd)] elif first == "]": # possibly ;] return [("n", sd)] elif first == ".": # possibly ;. return [("n", sd)] else: # # "is" detected, set inverse flag if sd[0:2] == "is": sd = utils.skipBlancs(s[2:]) self.inverseFlag = 1 p = self.parseVerb (sd) if p == []: print "!!!error parsing predicate!!! Line: " + pre.getfirst(s,self.errLength)\ + "!!!!" return [] [(verb, rest)] = p if self.inverseFlag: verb.isof = 1 p = self.parseNodeList([], rest) if p <> []: [(nl, rest)] = p return [((verb, nl), rest)] else: return [] # test the function parseNodeList. def testParseNodeList(self): print ("\ntestParseNodeList\n***********************\n") p = self.parseNodeList([], "[:a :b],[:c :d], [:e :f].") if p <> []: [(rl, rest)] = p print ("[:a :b],[:c :d], [:e :f] rest: " + rest +\ " parsed: \n" + r.rlToString(rl)+"\n") else: print ("failure parsing: [:a :b],[:c :d], [:e :f]\n") p = self.parseNodeList([], ":a, :b,:c.") if p <> []: [(rl, rest)] = p print (":a, :b,:c. rest: " + rest + " parsed: \n" + r.rlToString(rl) + "\n") else: print ("failure parsing: :a, :b, :c.\n") p = self.parseNodeList([], ":a, :b :c.") if p <> []: [(rl, rest)] = p print (":a, :b :c. rest: " + rest + " parsed: \n" + r.rlToString(rl)+ "\n") else: print ("failure parsing: :a, :b :c.\n") p = self.parseNodeList([], ":a, b,:c.") if p <> []: [(rl, rest)] = p print (":a, b,:c. rest: " + rest + " parsed: \n" + r.rlToString(rl)+ "\n") else: print ("failure parsing: :a, b,:c.\n") p = self.parseNodeList([], ":a.") if p <> []: [(rl, rest)] = p print (":a. rest: " + rest + " parsed: \n" + r.rlToString(rl)+"\n") else: print ("failure parsing: :a.\n") p = self.parseNodeList([], ":a, :b,:c") if p <> []: [(rl, rest)] = p print (":a, :b,:c rest: " + rest + " parsed: \n" + r.rlToString(rl)+"\n") else: print ("failure parsing: :a, :b, :c\n") p = self.parseNodeList([], ":a, :b,:c") # parses nodes separated by , . # nodelist = [Resource] # returns: [(nodelist, reststring)] # first call: parseNodeList ([], s) def parseNodeList(self, ol, s): if s == "": return [] else: sd = utils.skipBlancs(s) first = sd[0] if first == "." or first == ";" or first == "]" or first == "}": # higher separators -- return return [(ol, sd)] elif first == ",": # parse the next node (= object) p = self.parseObject (sd[1:]) if p == []: # print "!!!error while parsing nodelist!!! Line: " + pre.getfirst(s, self.errLength)\ + "!!!!" return [] else: (o, s) = p[0] return self.parseNodeList(ol + [o], s) else: # parse the first (and possibly last) node if ol <> []: # first node has been parsed already print "!!! missing comma while parsing nodelist!!! Line: " + pre.getfirst(s, self.errLength) return [] p = self.parseObject (sd) if p == []: print "!!!error while parsing nodelist!!! Line: " + pre.getfirst(s, self.errLength)\ + "!!!!" return [] else: (o, s) = p[0] return self.parseNodeList (ol + [o], s) # parse a subject . def parseSubject(self, s): return self.parseObject(s) def testParseVerb(self): p = self.parseVerb(":v :o.") print ("Test parseVerb: ", pre.fst(p[0]).toString(), pre.snd(p[0])) # parse a verb. def parseVerb(self, s): if s[0:3] == "has": # has detected - must be skipped sd1 = utils.skipBlancs(s[3:]) return self.parseObject(sd1) else: return self.parseObject(s) def testParseObject(self): p = self.parseObject(":c .") print ("Test parseObject: ", pre.fst(p[0]).toString(), pre.snd(p[0])) p = self.parseObject("{{:a :b :c} :d {:e :f :g}} :h :j.") print ("Test parseObject: ", pre.fst(p[0]).toString(), pre.snd(p[0])) p = self.parseObject("[ ont:first ?a; ont:rest ?b ]") print ("Test parseObject: ", pre.fst(p[0]).toString(), pre.snd(p[0])) # parse an object. def parseObject(self, s): if s == "": return [] else: sd = utils.skipBlancs(s) first = sd[0] if first == "{": # embedded sets p = self.parseTripleSet ([], sd) if p == []: (bool, parsed,rest) = self.synchronize1(s, "}") if bool == "F": self.errorlist.append("!!! error parsing tripleset missing }!!!") print "Error parsing tripleset: missing }" + pre.getFirst(sd, self.errLength) return [] else: res = r.Resource() res.multres(pre.fst(p[0])) return [(res, pre.snd(p[0]))] elif first == "[": # embedded anonymous sets p = self.parseAnonSet ([], sd) if p == []: (bool, parsed,rest) = self.synchronize1(s, "]") if bool == "F": self.errorlist.append("!!! error parsing anonset missing ]!!!") print "Error parsing tripleset: missing ] " + pre.getFirst(sd, self.errLength) return [] else: res = r.Resource() res.multres(pre.fst(p[0])) return [(res, pre.snd(p[0]))] elif sd[0:2] == "of": # of detected - must be skipped sd1 = utils.skipBlancs(sd[2:]) return self.parseObject(sd1) else: # parse an object p = self.parseNode (utils.skipBlancs (sd)) if p == []: # print "!!!error while parsing subject or object!!! Line: " + pre.getfirst(s, self.errLength)\ + "!!!!" return [] [(res, rest)] = p rest = utils.skipBlancs(rest) if len(rest) > 2 and rest[0] == "." and (not (utils.elem(rest[1], utils.delimNode) == "T")): return self.parsePath(1, res, rest) if len(rest) > 2 and rest[0] == "^" and (not (utils.elem(rest[1], utils.delimNode) == "T")): return self.parsePath(2, res, rest) return p def createAnonSubject(self): """create an anonymous subject; form= :T$$$n .""" self.anonCounter = self.anonCounter + 1 s = ":T$$$" + `self.anonCounter` res = r.Resource() res.res(s,"",s) nr = self.currRes if self.queryFlag == "T": res.number = -nr else: res.number = nr self.resdic[s] = (nr, res) self.revres.append(res) self.currRes += 1 return res def parseNode(self, s): """ function for parsing nodes. input is the string to be parsed. returns [(resource, rest_string)] or [] in case of error. Formats of a node (=URI): <#...> <> :... prefix:... "..." (constant)""" if s == "": return [] else: # parse all blanks s = utils.skipBlancs(s) # get first character y = s[0] sd = s [1:] # starts with ":" This refers to the parsed document. if y == ":": return self.parseNodeThis (sd) # starts with ==>. This is log:implies elif (utils.startsWith (s, "==>") == "T"): flabel = self.log + "implies" (bool, re) = self.createRes(flabel) if bool == "F": re.res(flabel,"","a") return [(re,utils.skipBlancs(s[3:]))] # starts with "<" Three cases : <> <#..> elif y == "<": return self.parseNodeLesser(sd) # starts with ( = elif y == "(": return self.parseList(sd) # starts with "?:" This is a variable. elif y == "?": return self.parseVariableQ(s) # starts with "_:" This is a variable. elif y == "_": return self.parseVariable(s) # intercept special comment """ elif utils.startsWith (s, "\"\"\"") == "T": return self.parseSpecialComment(s[3:]) # starts with '"' Constant elif y == '"': return self.parseConstant(sd) # = is a special case elif y == "=": flabel = ("=") (bool, re) = self.createRes(flabel) if bool == "F": re.res(flabel,"","=") return [(re,utils.skipBlancs(sd))] elif utils.startsWith(s, "/=")== "T": flabel = ("/=") (bool, re) = self.createRes(flabel) if bool == "F": re.res(flabel, "", "/=") return [(re, utils.skipBlancs(sd[1:]))] # the verb is "a" elif (utils.startsWith (s, "a") == "T" and utils.testBlancs (s[1]) == "T"): flabel = self.rdf + "type" (bool, re) = self.createRes(flabel) if bool == "F": re.res(flabel,"","a") return [(re,utils.skipBlancs(sd))] # skip "of" normally detected in parseObject elif (utils.startsWith (s, "of") == "T" and utils.testBlancs (s[2]) == "T"): return self.parseNode (s[2:]) # "has" detected skip this normally detected in parseVerb elif (utils.startsWith (s, "has") == "T" and utils.testBlancs (s[3]) == "T"): return self.parseNode (s[3:]) # "this" detected elif (utils.startsWith (s, "this") == "T" and utils.testBlancs (s[4]) == "T"): flabel = self.getFromDictionary(":") (bool, re) = self.createRes(flabel) if bool == "F": re.res(flabel,"",":") return [(re, s[5:])] # "is" detected, skip and set inverse flag (handled in parseTriple) elif (utils.startsWith (s, "is") == "T" and utils.testBlancs (s[2]) == "T"): return self.parseNode (utils.skipBlancs(s[2:])) # lonely : detected. Must be format: prefix:postfix. # The prefix must be known. else: return self.parseNodePrefix(s) def parsePath(self, bool, res, s): """ parses a path. Returns a complex resource and a reststring res is the first parsed node Format: [(res, rest)] """ rest = s[1:] # skip dot or ^ # create a resource name = "list" + `self.listCounter` self.listCounter += 1 (bool1, re) = self.createRes(name) if bool1 == "F": re.res(name, ":", name) # create a triple triple = tr.Triple() # get the next node p = self.parseNode(rest) if p == []: self.errorlist.append("!!! error parsing path!!!") print "Error parsing path" + pre.getFirst(rest, self.errLength) return [] [(res1, rest)] = p lastAnon = self.createAnonSubject() if bool == 1: # a dot was detected; the resource is a subject triple.subject = res triple.predicate = res1 triple.object = lastAnon else: # a ^ was detected; the resource is an object triple.subject = lastAnon triple.predicate = res1 triple.object = res # add the triple re.multres([triple]) # now parse the other nodes (if there are some) or stop cont = 1 while cont: dot = 0 hat = 0 rest = utils.skipBlancs(rest) # now detect whether next is a dot or a ^ or the end of the path if (rest[0] == ".") and (not (utils.elem(rest[1], utils.delimNode) == "T")): dot = 1 elif (rest[0] == "^") and (not (utils.elem(rest[1], utils.delimNode) == "T")): hat = 1 else: # apparently the path is finished return [(re, rest)] # parse the next node p = self.parseNode(rest[1:]) if p == []: self.errorlist.append("!!! error parsing path!!!") print "Error parsing path" + pre.getFirst(rest, self.errLength) return [] [(res1, rest)] = p print "sec res1 ", res1 # create a new triple triple1 = tr.Triple() newAnon = self.createAnonSubject() if dot: triple1.subject = lastAnon triple1.predicate = res1 triple1.object = newAnon else: triple1.subject = newAnon triple1.predicate = res1 triple1.object = lastAnon lastAnon = newAnon re.list.append(triple1) def toString(self, p): """ transform parsing result to string""" p = p[0] return (pre.fst(p)).toString() + "/// " + pre.snd(p) def testParseNode(self): """ test the function parseNode.""" print ("<> :a :b", "$$$Result: :",self.toString(self.parseNode ("<> :a :b"))) print (":]", "$$$Result: :",self.toString(self.parseNode (":]"))) print (":a :b :c .", "$$$Result: :",self.toString(self.parseNode (":a :b :c ."))) print ("dc:a dc:b dc:c . { dc:ho \"oke\".}", "$$$Result: :",self.toString(self.parseNode ("dc:a dc:b dc:c . { dc:ho \"oke\".}"))) print (" dc:b dc:c .","$$$Result: :", self.toString(self.parseNode (" dc:b dc:c ."))) print (";<#pat> :a :b.","$$$Result: :", self.toString(self.parseNode (";<#pat> :a :b."))) print ("<#pat> :a :b","$$$Result: :", self.toString(self.parseNode ("<#pat> :a :b"))) print ("\"Hallo\" dc:b dc:c . { dc:ho \"oke\".}", "$$$Result: :",self.toString(self.parseNode ("\"Hallo\" dc:b dc:c . { dc:ho \"oke\".}"))) print ("<>", "$$$Result: :",self.toString(self.parseNode ("<> :a :b"))) print (" :a :b.", "$$$Result: :",self.toString(self.parseNode (" :a :b."))) print ("\"\"\" hhh\nelklklke\"\"\"","$$$Result: :", self.toString(self.parseNode ("\"\"\" hhh\nelklklke\"\"\""))) return ("Test OK") def parseNodePrefix(self, s): """ parse a node with format prefix:postfix""" global utils sd = utils.skipBlancs(s) if sd == "": return [] else: bool1, prefix, rest1 = utils.parseUntil (":", sd) # format (Bool, String, String) bool2, postfix, rest2 = utils.parseUntilDelim (utils.delimNode, utils.skipBlancs(rest1)) # format (Bool, String, String) pre = self.getFromDictionary(prefix + ":") # normal case if bool1 == "T" and bool2 == "T" and pre != "Error": flabel = pre + postfix (bool, re) = self.createRes(flabel) if bool == "F": re.res(flabel, prefix, prefix + ":" + postfix) return [(re, rest2)] else: # error print ("Error parsing prefix:postfix : ", "", s) return [] def parseConstant (self, inString): """ parse a constant""" if inString == "": (bool, re) = self.createRes("") if bool == "F": re.res("","","") re.const = "T" return [(re, "")] else: bool1, const, rest1 = utils.parseUntil ("\"", utils.skipBlancs (inString)) # format (Bool, String, String) if bool1 == "T": # " found (bool, re) = self.createRes(const) if bool == "F": re.res(const,"",const) re.const = "T" return [(re, rest1)] else: print ("Error parsing constant: " + inString) return [] def parseSpecialComment (self, inString): """ parse a special comment (starts with 3x") and skip it""" if inString == "": (bool, re) = self.createRes("") if bool == "F": re.res("","","") re.const = "T" return [(re, "")] else: bool, const, rest = utils.parseUntilString(inString, "\"\"\"") if bool == "T": (bool, re) = self.createRes(const) if bool == "F": re.res(const,"",const) re.const = "T" return [(re, rest[3:])] else: print ("Error parsing special constant: ", inString) return [] def parseVariable(self, s): """ parse a node that starts with _: (global existential variable) """ bool1, node1, rest1 = utils.parseUntilDelim(utils.delimNode, s) if bool1 == "T": # normal case (bool, re) = self.createRes(node1) if bool == "F": # make the number negative re.number = -re.number re.res(node1,"",node1) re.varType = "_" return [(re,rest1)] else: # error print ("Error parsing variable (_:xxx) : ", pre.getfirst(s, self.errLength)) return [] def parseVariableQ(self, s): """ parse a node that starts with ? (local universal variable) Is only entered in the dictionary at the triple level. Scope is on triple level. """ bool1, node1, rest1 = utils.parseUntilDelim(utils.delimNode, s) if bool1 == "T": # normal case re = r.Resource() re.res(node1,"", node1) re.varType = "?" return [(re,rest1)] else: # error print ("Error parsing variable (?xxx) : ",pre.getfirst(s, self.errLength)) return [] def parseNodeThis(self, s): """ parse a node that starts with :""" if s == "": return [] else: bool1, node1, rest1 = utils.parseUntilDelim(utils.delimNode, s) if bool1 == "T": if utils.startsWith(node1, "G$$$") == "T" or\ utils.startsWith(node1, "E$$$") == "T" or\ utils.startsWith(node1, "T$$$") == "T": flabel = ":" + node1 else: flabel = self.getFromDictionary(":") + node1 (bool, re) = self.createRes(flabel) if bool == "F": re.res(self.getFromDictionary(":")+ node1,":", ":" + node1) return [(re,rest1)] else: # an error has happened print ("Error parsing : node " , s) return [] def parseNodeLesser(self, s): """ parse a node that starts with <""" if s == "": return [] else: bool1, rest1 = utils.takec(">", utils.skipBlancs(s)) if bool1 == "T": # parse <> = the parsed document flabel = self.getFromDictionary(":") (bool, re) = self.createRes(flabel) if bool == "F": re.res(flabel,":", "<>") return [(re,rest1)] else: bool2, rest2 = utils.takec("#", utils.skipBlancs1(s)) bool3, node1, rest3 = utils.parseUntil(">", utils.skipBlancs (rest2)) # parse <#...> if (bool2 == "T" and bool3 == "T"): flabel = self.getFromDictionary(":")[:-1] + "#" + node1 (bool, re) = self.createRes(flabel) if bool == "F": re.res(flabel, ":", "<#" + node1 + ">") return [(re, rest3)] else: bool4, node2, rest4 = utils.parseUntil(">", utils.skipBlancs(s)) if bool4 == "T": # parse (bool, re) = self.createRes(node2) if bool == "F": re.res(node2,"", "<" + node2 +">") return [(re, rest4)] else: print ("Error missing > :", s) return [] def createRes(self, label): """ create a resource update the current resource number after creating check if the resource exists already input is the full label of the resource output is a boolean and a resource""" if self.resdic.has_key(label): return ("T",pre.snd(self.resdic[label])) else: re = r.Resource() nr = self.currRes if utils.startsWith(label, ":G$$$") == "T": re.number = - nr elif self.queryFlag and utils.startsWith(label, ":E$$$")\ == "T": re.number = -nr elif self.queryFlag and utils.startsWith(label, ":T$$$")\ == "T": re.number = -nr else: re.number = nr self.resdic[label] = (nr, re) self.revres.append(re) self.currRes = self.currRes + 1 return ("F", re) def parseList(self, s): """ function for parsing a list Format: (x1 x2 ... xn) Returns: [(list, reststring)] """ (bool, parsed, rest) = self.synchronize1(s, ")") if bool == "F": self.errorlist.append("!!! error parsing list missing )!!!") print "Error parsing list: missing )" + s[0:40] return [] if s == "": return [] else: list = [] sd = utils.skipBlancs(s) cont = 1 while cont: p = self.parseObject(sd) if p == []: # error return [] [(res, rest)]= p list.append(res) sd = utils.skipBlancs(rest) if sd[0] == ")": cont = 0 node = "RDFE:list" + `self.listCounter` (bool, re) = self.createRes(node) self.listCounter += 1 if bool == "F": re.res(node,"", node) re.RDFList = list return [(re, sd[1:])] def parseParam(self, s): """ function for parsing parameters that determine the parsing process. input is the string to be parsed. returns a triple and the rest string format of a param : @param name value A triple is made: RDFE:name RDFE:param value_of_param The value is normally: "0" or "1" """ if s == "": return [] else: sd = utils.skipBlancs(s) bool1, rest1 = utils.parseString( "@param", sd) bool2, name, rest2 = utils.parseUntil (" ", utils.skipBlancs1 (rest1)) bool3, value, rest3 = utils.parseUntil (".", utils.skipBlancs1(rest2)) if (bool1 == "T" and bool2 == "T" and bool3 == "T"): if name == "full_generation": if utils.startsWith(value,"0") == "T": self.full_generation = 0 elif utils.startsWith(value,"1") == "T": self.full_generation = 1 else: # error return [] triple = tr.Triple() (bool, re) = self.createRes("RDFE:" + name) if bool == "F": # resource does not exist re.res("RDFE:" + name,"RDFE:","RDFE:" + name) triple.subject = re (bool, re) = self.createRes("RDFE:param") if bool == "F": re.res("RDFE:param", "RDFE:" , "RDFE:param") triple.predicate = re (bool, re) = self.createRes(value) if bool == "F": re.res(value,"",value) re.const = "T" triple.object = re return [(triple, utils.skipBlancs(rest3))] else: # an error has happened return [] def parsePrefix(self, s): """ function for parsing prefixes. input is the string to be parsed. returns a triple and the rest string format of a prefix : @prefix ...: the prefix is added in the global prefix dictionary as ("prefix","value-of-prefix")""" if s == "": return [] else: sd = utils.skipBlancs(s) bool1, rest1 = utils.parseString( "@prefix", sd) bool2, prefix, rest2 = utils.parseUntil (":", utils.skipBlancs1 (rest1)) bool3, rest3 = utils.takec ("<", utils.skipBlancs1(rest2)) bool4, uri, rest4 = utils.parseUntil (">", utils.skipBlancs1(rest3)) bool5, rest5 = utils.takec (".", utils.skipBlancs1 (rest4)) if (bool1 == "T" and bool2 == "T" and bool3 == "T" and bool4 == "T" and bool5 == "T"): self.prefixDictionary [prefix + ":"] = uri triple = tr.Triple() (bool, re) = self.createRes("prefix:" + prefix) if bool == "F": # resource does not exist re.res("prefix:" + prefix,"prefix:","prefix:" + prefix) triple.subject = re (bool, re) = self.createRes("prefix:abbrev") if bool == "F": re.res("prefix:abbrev", "prefix:" , "prefix:abbrev") triple.predicate = re (bool, re) = self.createRes(uri) if bool == "F": re.res(uri,"","<" + uri + ">") triple.object = re return [(triple, rest5)] else: # an error has happened return [] def parseBind(self, s): """ parse the bind directive; has become obsolete.""" sd = utils.skipBlancs( s) bool1, rest1 = utils.parseString ("bind", sd) bool2, prefix, rest2 = utils.parseUntil (":", utils.skipBlancs (rest1)) bool3, rest3 = utils.takec ("<", utils.skipBlancs (rest2)) bool4, uri, rest4 = utils.parseUntil (">", utils.skipBlancs (rest3)) bool5, rest5 = utils.takec (".", utils.skipBlancs (rest4)) # normal case if (bool1 == "T" and bool2 == "T" and bool3 == "T" and bool4 == "T" and bool5 == "T"): self.prefixDictionary [prefix + ":"] = uri triple = tr.Triple() (bool, re) = self.createRes("prefix:" + prefix) if bool == "F": # resource does not exist re.res("prefix:" + prefix,"prefix:","prefix:" + prefix) triple.subject = re (bool, re) = self.createRes("prefix:abbrev") if bool == "F": re.res("prefix:abbrev", "prefix:" , "prefix:abbrev") triple.predicate = re (bool, re) = self.createRes(uri) if bool == "F": re.res(uri,"",uri) triple.object = re return [(triple, rest5)] else: # an error has happened return [] def getFromDictionary(self, s): """ get an entry from the dictionary""" if self.prefixDictionary.has_key(s): return self.prefixDictionary[s] else: return "" def toStringErrorlist(self): """ transforms the errorlist to a string""" s = "" for line in self.errorlist: s.append(line + "\n") return s # ************* known uri's ****************** rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#" rdfs = "http://www.w3.org/2000/01/rdf-schema#" daml = "http://www.daml.org/2001/03/daml+oil#" log = "http://www.w3.org/2000/10/swap/log#" # ************* --------------- ************** # # The bnf grammar #---------------------- # # Taken from # on 2001-08-03 (version of 2001-04-10) # # Modifications: # # $Log$ # Revision 1.2 2004/04/19 14:47:57 josd # RDFEngineV2 committed on Guido's behalf # # Revision 1.4 2001/08/06 20:56:21 sandro # added space* and space+ in several places # removed "#" from forbidden chars in URI_Reference # handles comments # made directives actually part of the grammar (!) # allowed nprefix to be zero-length # # Revision 1.3 2001/08/03 13:44:43 sandro # filled in remaining non-terminals # # Revision 1.2 2001/08/03 13:02:48 sandro # standardized BNF so blindfold can compile it # added ::= for each rule # added | for branches # added ; at end of rule # added # before comments # put quotes around literals # turn hypen into underscore in identifiers # rename prefix to nprefix (hack around blindfold keyword for now) # # Revision 1.1 2001/08/03 12:34:38 sandro # added opening comments # # # # document ::= void # | statementlist; # # space ::= " " | "\n" | "\r" | comment; # # comment ::= "#" [^\r\n]*; # # statement ::= subject space+ property_list # | directive # ; # # statementlist ::= (statement space* ("." space*)?)* ; # # subject ::= node; # # verb ::= ">-" prop "->" # has xxx of # | "<-" prop "<-" # is xxx of # # | operator # has operator:xxx of??? NOT IMPLMENTED # | prop # has xxx of -- shorthand # | "has" prop # has xxx of # | "is" prop "of" # is xxx of # | "a" # has rdf:type of # | "=" # has daml:equivalent of # ; # # prop ::= node; # # node ::= uri_ref2 # | anonnode # | "this" # | node # ; # # nodelist ::= void # (used in lists) # | node # | node nodelist # ; # # anonnode ::= "[" property_list "]" # something which ... # | "{" statementlist "}" # the statementlist itself as a resource # | "(" nodelist ")" # short for eg [ n3:first node1; n3:rest [ n3:first node2; n3:rest: n3:null ]] # ; # # property_list ::= void # to allow [...]. # | verb space+ object_list # | verb space+ object_list space+ ";" space+ property_list # | ":-" anonnode #to allow two anonymous forms to be given eg [ a :Truth; :- { :sky :color :blue } ] ) # | ":-" anonnode ";" property_list # ; # # object_list ::= object # | object "," object_list # ; # # uri_ref2 ::= qname # | "<" URI_Reference ">" # ; # # qname ::= nprefix ":" localname; # ??? Allow omit colon when prefix void - keyword clash # # object ::= subject # | string1 # " constant-value-with-escaping " # | string2 # """ constant value with escaping including single or double occurences of quotes and/or newlines """ # # well-formed-xml-element ???? legacy or structured stuff - not implemented or distinguished # ; # # directive ::= "bind" space+ nprefix ":" uri_ref2 # Namespace declartion. Trailing "#" is omitted & assumed. Obsolete. # | "@prefix" space+ nprefix ":" space+ uri_ref2 # Namespace declaration # ; # ## operator ::= (Not implemented) ## + >- operator:plus -> ## - >- operator:minus -> ## / >- operator:slash-> ## * >- operator:star-> (etc? @@) # # fragid ::= alpha alphanumeric* ; # # alpha ::= [a-zA-Z]; # # alphanumeric ::= alpha | [0-9] | "_"; # # void ::= "" ; # nothing # # URI_Reference ::= [^{}<>]*; # short version # # nprefix ::= "" | ((alpha | "_") alphanumeric*); # # localname ::= fragid; # # string1 ::= '"' string1_char* '"'; # # string1_char ::= '\\"' | [^\"] ; # should disallow some other characters, etc. # # string2 ::= '"""' string2_char* '"""'; # # string2_char ::= [^"] | ([^] [^] [^"]); # something like this; need to think about it some more # #-----------------------------------------------------------------------} def makePredDic(ts, ruleNr): """ make a dictionary accessed by predicate number returning a list of triples with the same predicate. Put triples with variable predicate into a list. Rules are added with the predicates of the consequents. A a side effect rules are marked as rules. Returns a dictionary and a list. Input is a list of triples """ infDB = {} varPred = [] log = "http://www.w3.org/2000/10/swap/log#" for triple in ts: nr = triple.predicate.number sname = triple.predicate.label if sname == "=": nr = triple.subject.number nr1 = triple.object.number triple.object.number = nr # keeps track of the old number triple.object.onr = nr1 fname = triple.predicate.fullname # print "fname = " + fname if fname == log + "implies": # this is a rule triple.rule = 1 triple.ruleNr = ruleNr ruleNr += 1 ts = triple.object.list for t in ts: nr = t.predicate.number if nr > 0: if infDB.has_key(nr): infDB[nr].append(triple) else: infDB[nr] = [triple] else: varPred.append(triple) else: if nr > 0: if infDB.has_key(nr): infDB[nr].append(triple) else: infDB[nr] = [triple] else: varPred.append(triple) return (infDB, varPred) def printPredDic(predDic): for key in predDic.keys(): print "\nkey: ", key, " content:\n", tr.tsToStringVar(predDic[key]) def printVarPred(varPred): for triple in varPred: print "\n", triple.toStringVar() def printPredicates(predDic, varPred): print "\nTriples by predicate:\n\n" printPredDic(predDic) print "\nTriples with variable predicates:\n\n" printVarPred(varPred) if __name__ == "__main__": #testParseNode() #N3Parser().testParseComment() #N3Parser().testParsePrefix() #N3Parser().testParseBind() parser = N3Parser() #parser.readN3("c:/python/agfa/authen.axiom.n3") #parser.parseN3(parser.n3String) #print parser.toStringErrorlist() #parser.testParseObject() #parser.testParseVerb() #parser.testParseNodeList() #parser.testParsePropertyList() #parser.testParseTriple() #parser.testParseAFile() if len(sys.argv) == 1: parser.interact() else: if len(sys.argv) > 2: print "Format: N3Parser.py [fileName]" else: fileName = sys.argv[1] if (utils.startsWith(fileName,"http://")== "T"): parser.readUrl(fileName) else: parser.readN3(fileName) parser.parseN3(parser.n3String) p = makePredDic(parser.tripleset.db, parser.ruleNr) printPredicates(p[0], p[1]) parser.writeOutput()