home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / var / lib / python-support / python2.6 / rdflib / sparql / parser.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  14.1 KB  |  315 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. """ SPARQL Lexer, Parser and Function-Mapper
  5. By Shawn Brown <http://shawnbrown.com/contact>
  6.  
  7. TO DO:
  8.   swap current parser functions for Michelp's pyparsing setup
  9.   add mapping for FILTER/constraints
  10.   typed literals
  11.   integer, double or boolean abbreviations
  12.   language tags (e.g., @fr)
  13.   nested OPTIONALs ???
  14.   blank node and RDF collection syntax ???
  15.   GRAPH statements ???
  16.  
  17. CURRENTLY SUPPORTED:
  18.   Simple SELECT queries
  19.   Predicate-object and object list shorthand
  20.     (e.g., ?x  foaf:name  ?name ; foaf:mbox  ?mbox ; vcard:TITLE  ?title)
  21.   Multi-line/triple-quoted literals
  22.   BASE, PREFIX, SELECT, WHERE, UNION, OPTIONAL, multiple UNIONs and multiple
  23.     OPTIONALs (but not nested OPTIONALs)
  24.  
  25. USAGE:
  26.     #from sparql_lpm import doSPARQL
  27.     from rdflib.sparql.parser import doSPARQL
  28.     ...load graph...
  29.     ...define SPARQL query as string...
  30.     result = doSPARQL(queryStr, sparqlGr)
  31.  
  32. """
  33. import base64
  34. import re
  35. from rdflib.URIRef import URIRef
  36. from rdflib.sparql.graphPattern import GraphPattern
  37.  
  38. def _escape(text):
  39.     return base64.encodestring(text).replace('\n', '')
  40.  
  41.  
  42. def _unescape(text):
  43.     return base64.decodestring(text)
  44.  
  45.  
  46. def _escapeLiterals(query):
  47.     ''' escape all literals with escape() '''
  48.     
  49.     fn = lambda m: "'" + _escape(m.group(2)) + "'" + m.group(3)
  50.     pat = '(\\"\\"\\"|\'\'\'|[\\"\'])([^\\1]*?[^\\\\]?)\\1'
  51.     return re.sub(pat + '(\\s*[.,;\\}])', fn, query)
  52.  
  53.  
  54. def _resolveShorthand(query):
  55.     ''' resolve some of the syntactic shorthand (2.8 Other Syntactic Forms) '''
  56.     
  57.     def doList(pat, text):
  58.         pat = re.compile(pat)
  59.         while pat.search(text):
  60.             text = re.sub(pat, '\\1\\2\\3 . \\2\\4', text)
  61.         return text
  62.  
  63.     pat = '(\\{.*?)([^ ]+ )([^ ]+ [^ ]+)\\s?; ([^ ]+ [^ ]+\\s?[,;\\.\\}])'
  64.     query = doList(pat, query)
  65.     pat = '(\\{.*?)([^ ]+ [^ ]+ )([^ ]+\\s?), ([^ ]+\\s?[,\\.\\}])'
  66.     query = doList(pat, query)
  67.     return query
  68.  
  69.  
  70. def _resolvePrefixes(query):
  71.     ''' resolve prefixed IRIs, remove PREFIX statements '''
  72.     prefixes = re.findall('PREFIX ([\\w\\d]+:) <([^<>]+)>', query)
  73.     prefixes.extend([
  74.         ('rdf:', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'),
  75.         ('rdfs:', 'http://www.w3.org/2000/01/rdf-schema#'),
  76.         ('xsd:', 'http://www.w3.org/2001/XMLSchema#'),
  77.         ('fn:', 'http://www.w3.org/2004/07/xpath-functions')])
  78.     matches = re.search('PREFIX : <([^<>]+)>', query)
  79.     if matches != None:
  80.         prefixes.append((':', matches.group(1)))
  81.     
  82.     query = re.sub('PREFIX [\\w\\d]*:[ ]?<[^<>]+>[ ]?', '', query)
  83.     
  84.     fn = lambda m: '<' + _escape(m.group(1)) + '>'
  85.     query = re.sub('<([^<>]+)>', fn, query)
  86.     for fn in prefixes:
  87.         pair = None
  88.         query = re.sub(pair[0] + '([^ .\\}]+)', fn, query)
  89.     
  90.     return query
  91.  
  92.  
  93. def _resolveBase(query):
  94.     ''' resolve relative IRIs using BASE IRI, remove BASE statement '''
  95.     pat = re.compile('BASE <([^<>]+)>\\s?')
  96.     base = pat.search(query)
  97.     if base != None:
  98.         
  99.         fn = lambda m: '<' + base.group(1) + m.group(1) + '>'
  100.         query = re.sub('<([^<>: ]+)>', fn, query)
  101.         query = re.sub(pat, '', query)
  102.     
  103.     return query
  104.  
  105.  
  106. def _parseSelect(query):
  107.     ''' returns tuple of SELECTed variables or None '''
  108.     var = '[?$][\\w\\d]+'
  109.     select = re.search('SELECT(?: ' + var + ')+', query)
  110.     if select != None:
  111.         select = re.findall(var, select.group(0))
  112.         select = tuple(select)
  113.     
  114.     return select
  115.  
  116.  
  117. class _StackManager:
  118.     ''' manages token stack for _parser() '''
  119.     
  120.     def _StackManager__tokenGen(self, tokens):
  121.         for token in tokens:
  122.             yield token
  123.         
  124.  
  125.     
  126.     def __init__(self, tokenList):
  127.         self.stack = self._StackManager__tokenGen(tokenList)
  128.         self.current = self.stack.next()
  129.  
  130.     
  131.     def next(self):
  132.         
  133.         try:
  134.             self.current = self.stack.next()
  135.             if self.current == '':
  136.                 self.next()
  137.         except StopIteration:
  138.             self.current = None
  139.  
  140.  
  141.     
  142.     def token(self):
  143.         return self.current
  144.  
  145.  
  146.  
  147. class Where(list):
  148.     pass
  149.  
  150.  
  151. class Union(list):
  152.     pass
  153.  
  154.  
  155. class Optional(list):
  156.     pass
  157.  
  158. _listTypes = {
  159.     'OPTIONAL': (lambda : Optional([])),
  160.     'UNION': (lambda : Union([])),
  161.     'WHERE': (lambda : Where([])) }
  162.  
  163. def _makeList(keyword):
  164.     ''' return list of given type or None '''
  165.     if keyword in _listTypes:
  166.         return _listTypes[keyword]()
  167.  
  168.  
  169. def _parser(stack, listType = 'WHERE'):
  170.     ''' simple recursive descent SPARQL parser '''
  171.     typedList = _makeList(listType)
  172.     nestedType = listType
  173.     while stack.token() != None:
  174.         token = stack.token()
  175.         if _makeList(token) != None:
  176.             nestedType = token
  177.         elif token == '{':
  178.             stack.next()
  179.             typedList.append(_parser(stack, nestedType))
  180.             nestedType = listType
  181.         elif token == '}':
  182.             return typedList
  183.         if token != '.':
  184.             statement = ''
  185.             while token != None and token != '.' and token != '{' and token != '}':
  186.                 statement += ' ' + token
  187.                 stack.next()
  188.                 token = stack.token()
  189.             statement = statement.strip()
  190.             typedList.append(statement)
  191.             continue
  192.         
  193.         stack.next()
  194.     return typedList
  195.  
  196.  
  197. def _parseWhere(query):
  198.     ''' split query into tokens, return parsed object '''
  199.     stackObj = _StackManager(query)
  200.     return _parser(stackObj)
  201.  
  202.  
  203. def _findStatements(stmntType, stmntList):
  204.     ''' recurse over nested list, compile & return flat list of matching
  205.         statement strings used by _getStatements() '''
  206.     statements = []
  207.     typedList = _makeList(stmntType)
  208.     for stmnt in stmntList:
  209.         if type(stmnt) is str:
  210.             statements.append(stmnt)
  211.         
  212.         if type(stmnt) == type(typedList):
  213.             statements.extend(_findStatements(stmntType, stmnt))
  214.             continue
  215.     
  216.     return statements
  217.  
  218.  
  219. def _getStatements(stmntType, stmntList):
  220.     ''' gets statements of given type from given list '''
  221.     statements = []
  222.     typedList = _makeList(stmntType)
  223.     for item in stmntList:
  224.         if type(item) == type(typedList):
  225.             statements.append(_findStatements(stmntType, item))
  226.             continue
  227.     
  228.     return statements
  229.  
  230.  
  231. def _buildGraphPattern(triples):
  232.     triples = map((lambda x: tuple(re.split(' ', x))), triples)
  233.     
  234.     isIRI = lambda x: if x[0] == '<':
  235. passx[-1] == '>'
  236.     
  237.     isLit = lambda x: if (x[0] == "'" or x[-1] == "'") and x[0] == '"':
  238. passx[-1] == '"'
  239.     for i in range(len(triples)):
  240.         sub = triples[i][0]
  241.         pred = triples[i][1]
  242.         obj = triples[i][2]
  243.         if isIRI(sub):
  244.             sub = URIRef(_unescape(sub[1:-1]))
  245.         
  246.         if isIRI(pred):
  247.             pred = URIRef(_unescape(pred[1:-1]))
  248.         
  249.         if isIRI(obj):
  250.             obj = URIRef(_unescape(obj[1:-1]))
  251.         elif isLit(obj):
  252.             obj = _unescape(obj[1:-1])
  253.         
  254.         triples[i] = (sub, pred, obj)
  255.     
  256.     return GraphPattern(triples)
  257.  
  258.  
  259. def _buildQueryArgs(query):
  260.     ''' '''
  261.     query = _escapeLiterals(query)
  262.     query = re.sub('\\s+', ' ', query).strip()
  263.     query = _resolveShorthand(query)
  264.     query = _resolveBase(query)
  265.     query = _resolvePrefixes(query)
  266.     query = re.sub('\\s*([.;,\\{\\}])\\s*', ' \\1 ', query)
  267.     whereObj = query[query.find('{') + 1:query.rfind('}')].strip()
  268.     whereObj = whereObj.split(' ')
  269.     select = _parseSelect(query)
  270.     whereObj = _parseWhere(whereObj)
  271.     where = _getStatements('WHERE', [
  272.         whereObj])
  273.     where.extend(_getStatements('UNION', whereObj))
  274.     where = map(_buildGraphPattern, where)
  275.     optional = _getStatements('OPTIONAL', whereObj)
  276.     optional = map(_buildGraphPattern, optional)
  277.     return {
  278.         'select': select,
  279.         'where': where,
  280.         'optional': optional }
  281.  
  282.  
  283. def doSPARQL(query, sparqlGr):
  284.     ''' Takes SPARQL query & SPARQL graph, returns SPARQL query result object. '''
  285.     x = _buildQueryArgs(query)
  286.     return sparqlGr.query(x['select'], x['where'], x['optional'])
  287.  
  288. if __name__ == '__main__':
  289.     testCases = [
  290.         '\nSELECT ?name\nWHERE { ?a <http://xmlns.com/foaf/0.1/name> ?name }\n',
  291.         '\nPREFIX foaf: <http://xmlns.com/foaf/0.1/>\nSELECT ?name\nWHERE { ?a foaf:name ?name }\n',
  292.         '\nBASE <http://xmlns.com/foaf/0.1/>\nSELECT ?name\nWHERE { ?a <name> ?name }\n',
  293.         '\nPREFIX : <http://xmlns.com/foaf/0.1/>\nPREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#>\nSELECT ?name ?title\nWHERE {\n    ?a :name ?name .\n    ?a vcard:TITLE ?title\n}\n',
  294.         '\nPREFIX foaf: <http://xmlns.com/foaf/0.1/>\nSELECT ?name ?mbox\nWHERE {\n    ?x  foaf:name  ?name ;\n        foaf:mbox  ?mbox .\n}\n',
  295.         '\nPREFIX foaf: <http://xmlns.com/foaf/0.1/>\nSELECT ?x\nWHERE {\n    ?x foaf:nick  "Alice" ,\n                  "Alice_" .\n}\n',
  296.         '\nPREFIX tag: <http://xmlns.com/foaf/0.1/>\nPREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#>\nSELECT ?name\nWHERE {\n    ?a tag:name ?name ;\n       vcard:TITLE "escape test vcard:TITLE " ;\n       <tag://test/escaping> "This is a \'\'\' Test """" ;\n       <tag://test/escaping> ?d\n}\n',
  297.         '\nPREFIX foaf: <http://xmlns.com/foaf/0.1/>\nSELECT ?PREFIX ?WHERE\nWHERE {\n    ?x  foaf:name  ?PREFIX ;\n        foaf:mbox  ?WHERE .\n}\n',
  298.         '\nPREFIX WHERE: <http://xmlns.com/foaf/0.1/>\nSELECT ?name ?mbox\nWHERE {\n    ?x  WHERE:name  ?name ;\n        WHERE:mbox  ?mbox .\n}\n',
  299.         'SELECT ?title WHERE { <http://example.org/book/book1> <http://purl.org/dc/elements/1.1/title> ?title . }',
  300.         'PREFIX foaf: <http://xmlns.com/foaf/0.1/>\nSELECT ?name ?mbox\nWHERE { ?person foaf:name ?name .\nOPTIONAL { ?person foaf:mbox ?mbox}\n}',
  301.         'PREFIX foaf: <http://xmlns.com/foaf/0.1/>\nSELECT ?name ?name2\nWHERE { ?person foaf:name ?name .\nOPTIONAL { ?person foaf:knows ?p2 . ?p2 foaf:name   ?name2 . }\n}',
  302.         'PREFIX foaf: <http://xmlns.com/foaf/0.1/>\n#PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\nSELECT ?name ?mbox\nWHERE\n{\n{ ?person rdf:type foaf:Person } .\nOPTIONAL { ?person foaf:name  ?name } .\nOPTIONAL {?person foaf:mbox  ?mbox} .\n}']
  303.     print 'Content-type: text/plain\n\n'
  304.     for query in testCases:
  305.         print '\n-----\n'
  306.         print '>>> query = """' + query.replace('\n', '\n... ') + '"""'
  307.         print '>>> result = doSPARQL(query, sparqlGr)\n'
  308.         result = _buildQueryArgs(query)
  309.         print 'select = ', result['select'], '\n'
  310.         print 'where = ', result['where'], '\n'
  311.         print 'optional = ', result['optional'], '\n'
  312.         print 'result = sparqlGr.query(select, where, optional)'
  313.     
  314.  
  315.