1"""Dispatch-processor API 2 3This is a post-processing processor API based on dispatching 4each element of a result tree in a top-down recursive call 5structure. It is the API used by the SimpleParseGrammar Parser, 6and likely will be the default processor for SimpleParse. 7""" 8from simpleparse.processor import Processor 9 10class DispatchProcessor(Processor): 11 """Dispatch results-tree in a top-down recursive pattern with 12 attribute lookup to determine production -> method correspondence. 13 14 To use the class, subclass it, then define methods for 15 processing each production. The methods should take this form: 16 def production_name( self, (tag, left, right, children), buffer): 17 pass 18 Where children may be either a list, or None, and buffer is the 19 entire buffer being parsed. 20 """ 21 def __call__( self, value, buffer ): 22 """Process the results of the parsing run over buffer 23 24 Value can either be: (success, tags, next) for a top-level 25 production, or (tag, left, right, children) for a non-top 26 production. 27 """ 28 if len( value ) == 3: 29 # is a top-level production 30 success, tags, next = value 31 if success: 32 result = dispatchList( self, tags, buffer ) 33 return success, result, next 34 else: 35 return success, tags, next 36 else: 37 # is a 4-item result tuple/tree 38 return dispatch( self, value, buffer ) 39 40 41def dispatch( source, tag, buffer ): 42 """Dispatch on source for tag with buffer 43 44 Find the attribute or key tag[0] of source, 45 then call it with (tag, buffer) 46 """ 47 try: 48 function = getattr (source, tag[0]) 49 except AttributeError: 50 try: 51 function = source[tag[0]] 52 except: 53 raise AttributeError( '''No processing function for tag "%s" in object %s! Check the parser definition!'''%(tag[0], repr(source))) 54 return function( tag, buffer ) 55 56def dispatchList( source, taglist, buffer ): 57 """Dispatch on source for each tag in taglist with buffer""" 58 if taglist: 59 return list(map( dispatch, [source]*len(taglist), taglist, [buffer]*len(taglist))) 60 else: 61 return [] 62 63def multiMap( taglist, source=None, buffer=None ): 64 """Convert a taglist to a mapping from tag-object:[list-of-tags] 65 66 For instance, if you have items of 3 different types, in any order, 67 you can retrieve them all sorted by type with multimap( childlist) 68 then access them by tagobject key. 69 """ 70 set = {} 71 if not taglist: 72 return set 73 for tag in taglist: 74 key = tag[0] 75 if source and buffer: 76 tag = dispatch( source, tag, buffer ) 77 set.setdefault(key,[]).append( tag ) 78 return set 79def singleMap( taglist, source=None, buffer=None ): 80 """Convert a taglist to a mapping from tag-object:tag, overwritting early with late tags""" 81 set = {} 82 if not taglist: 83 return set 84 for tag in taglist: 85 key = tag[0] 86 if source and buffer: 87 tag = dispatch( source, tag, buffer ) 88 set[key] = tag 89 return set 90 91def getString(info, buffer): 92 """Return the string value of the tag passed""" 93 (tag, left, right, sublist) = info 94 return buffer[ left:right ] 95 96try: 97 from simpleparse.stt.TextTools import countlines 98except ImportError: 99 def lines( start=None, end=None, buffer=None ): 100 """Return line number in file at character index (string.count version)""" 101 return buffer.count('\n', start or 0, end or len(buffer)) 102else: 103 def lines( start=None, end=None, buffer=None ): 104 """Return line number in file at character index (mx.TextTools version)""" 105 return countlines (buffer[start or 0:end or len(buffer)]) 106 107 108