def nlp(self, inputString, sourceTime=None, version=None):
orig_inputstring = inputString<EOL>inputString = re.sub(r'<STR_LIT>', r'<STR_LIT>', inputString).lower()<EOL>inputString = re.sub(r'<STR_LIT>', r'<STR_LIT>', inputString)<EOL>inputString = re.sub(r'<STR_LIT>', r'<STR_LIT>', inputString)<EOL>startpos = <NUM_LIT:0>  <EOL>matches = []<EOL>while startpos < len(inputString):<EOL><INDENT>leftmost_match = [<NUM_LIT:0>, <NUM_LIT:0>, None, <NUM_LIT:0>, None]<EOL>m = self.ptc.CRE_MODIFIER.search(inputString[startpos:])<EOL>if m is not None:<EOL><INDENT>if leftmost_match[<NUM_LIT:1>] == <NUM_LIT:0> orleftmost_match[<NUM_LIT:0>] > m.start() + startpos:<EOL><INDENT>leftmost_match[<NUM_LIT:0>] = m.start() + startpos<EOL>leftmost_match[<NUM_LIT:1>] = m.end() + startpos<EOL>leftmost_match[<NUM_LIT:2>] = m.group()<EOL>leftmost_match[<NUM_LIT:3>] = <NUM_LIT:0><EOL>leftmost_match[<NUM_LIT:4>] = '<STR_LIT>'<EOL><DEDENT><DEDENT>m = self.ptc.CRE_UNITS.search(inputString[startpos:])<EOL>if m is not None:<EOL><INDENT>debug and log.debug('<STR_LIT>')<EOL>if self._UnitsTrapped(inputString[startpos:], m, '<STR_LIT>'):<EOL><INDENT>debug and log.debug('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>if leftmost_match[<NUM_LIT:1>] == <NUM_LIT:0> orleftmost_match[<NUM_LIT:0>] > m.start('<STR_LIT>') + startpos:<EOL><INDENT>leftmost_match[<NUM_LIT:0>] = m.start('<STR_LIT>') + startpos<EOL>leftmost_match[<NUM_LIT:1>] = m.end('<STR_LIT>') + startpos<EOL>leftmost_match[<NUM_LIT:2>] = m.group('<STR_LIT>')<EOL>leftmost_match[<NUM_LIT:3>] = <NUM_LIT:3><EOL>leftmost_match[<NUM_LIT:4>] = '<STR_LIT>'<EOL>if m.start('<STR_LIT>') > <NUM_LIT:0> andinputString[m.start('<STR_LIT>') - <NUM_LIT:1>] == '<STR_LIT:->':<EOL><INDENT>leftmost_match[<NUM_LIT:0>] = leftmost_match[<NUM_LIT:0>] - <NUM_LIT:1><EOL>leftmost_match[<NUM_LIT:2>] = '<STR_LIT:->' + leftmost_match[<NUM_LIT:2>]<EOL><DEDENT><DEDENT><DEDENT><DEDENT>m = self.ptc.CRE_QUNITS.search(inputString[startpos:])<EOL>if m is not None:<EOL><INDENT>debug and log.debug('<STR_LIT>')<EOL>if self._UnitsTrapped(inputString[startpos:], m, '<STR_LIT>'):<EOL><INDENT>debug and log.debug('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>if leftmost_match[<NUM_LIT:1>] == <NUM_LIT:0> orleftmost_match[<NUM_LIT:0>] > m.start('<STR_LIT>') + startpos:<EOL><INDENT>leftmost_match[<NUM_LIT:0>] = m.start('<STR_LIT>') + startpos<EOL>leftmost_match[<NUM_LIT:1>] = m.end('<STR_LIT>') + startpos<EOL>leftmost_match[<NUM_LIT:2>] = m.group('<STR_LIT>')<EOL>leftmost_match[<NUM_LIT:3>] = <NUM_LIT:3><EOL>leftmost_match[<NUM_LIT:4>] = '<STR_LIT>'<EOL>if m.start('<STR_LIT>') > <NUM_LIT:0> andinputString[m.start('<STR_LIT>') - <NUM_LIT:1>] == '<STR_LIT:->':<EOL><INDENT>leftmost_match[<NUM_LIT:0>] = leftmost_match[<NUM_LIT:0>] - <NUM_LIT:1><EOL>leftmost_match[<NUM_LIT:2>] = '<STR_LIT:->' + leftmost_match[<NUM_LIT:2>]<EOL><DEDENT><DEDENT><DEDENT><DEDENT>m = self.ptc.CRE_DATE3.search(inputString[startpos:])<EOL>if m is not None:<EOL><INDENT>if leftmost_match[<NUM_LIT:1>] == <NUM_LIT:0> orleftmost_match[<NUM_LIT:0>] > m.start('<STR_LIT:date>') + startpos:<EOL><INDENT>leftmost_match[<NUM_LIT:0>] = m.start('<STR_LIT:date>') + startpos<EOL>leftmost_match[<NUM_LIT:1>] = m.end('<STR_LIT:date>') + startpos<EOL>leftmost_match[<NUM_LIT:2>] = m.group('<STR_LIT:date>')<EOL>leftmost_match[<NUM_LIT:3>] = <NUM_LIT:1><EOL>leftmost_match[<NUM_LIT:4>] = '<STR_LIT>'<EOL><DEDENT><DEDENT>m = self.ptc.CRE_DATE.search(inputString[startpos:])<EOL>if m is not None:<EOL><INDENT>if leftmost_match[<NUM_LIT:1>] == <NUM_LIT:0> orleftmost_match[<NUM_LIT:0>] > m.start('<STR_LIT:date>') + startpos:<EOL><INDENT>leftmost_match[<NUM_LIT:0>] = m.start('<STR_LIT:date>') + startpos<EOL>leftmost_match[<NUM_LIT:1>] = m.end('<STR_LIT:date>') + startpos<EOL>leftmost_match[<NUM_LIT:2>] = m.group('<STR_LIT:date>')<EOL>leftmost_match[<NUM_LIT:3>] = <NUM_LIT:1><EOL>leftmost_match[<NUM_LIT:4>] = '<STR_LIT>'<EOL><DEDENT><DEDENT>m = self.ptc.CRE_DAY.search(inputString[startpos:])<EOL>if m is not None:<EOL><INDENT>if leftmost_match[<NUM_LIT:1>] == <NUM_LIT:0> orleftmost_match[<NUM_LIT:0>] > m.start() + startpos:<EOL><INDENT>leftmost_match[<NUM_LIT:0>] = m.start() + startpos<EOL>leftmost_match[<NUM_LIT:1>] = m.end() + startpos<EOL>leftmost_match[<NUM_LIT:2>] = m.group()<EOL>leftmost_match[<NUM_LIT:3>] = <NUM_LIT:1><EOL>leftmost_match[<NUM_LIT:4>] = '<STR_LIT>'<EOL><DEDENT><DEDENT>m = self.ptc.CRE_WEEKDAY.search(inputString[startpos:])<EOL>if m is not None:<EOL><INDENT>if inputString[startpos:] not in self.ptc.dayOffsets:<EOL><INDENT>if leftmost_match[<NUM_LIT:1>] == <NUM_LIT:0> orleftmost_match[<NUM_LIT:0>] > m.start() + startpos:<EOL><INDENT>leftmost_match[<NUM_LIT:0>] = m.start() + startpos<EOL>leftmost_match[<NUM_LIT:1>] = m.end() + startpos<EOL>leftmost_match[<NUM_LIT:2>] = m.group()<EOL>leftmost_match[<NUM_LIT:3>] = <NUM_LIT:1><EOL>leftmost_match[<NUM_LIT:4>] = '<STR_LIT>'<EOL><DEDENT><DEDENT><DEDENT>m = self.ptc.CRE_TIME.search(inputString[startpos:])<EOL>if m is not None:<EOL><INDENT>if leftmost_match[<NUM_LIT:1>] == <NUM_LIT:0> orleftmost_match[<NUM_LIT:0>] > m.start() + startpos:<EOL><INDENT>leftmost_match[<NUM_LIT:0>] = m.start() + startpos<EOL>leftmost_match[<NUM_LIT:1>] = m.end() + startpos<EOL>leftmost_match[<NUM_LIT:2>] = m.group()<EOL>leftmost_match[<NUM_LIT:3>] = <NUM_LIT:2><EOL>leftmost_match[<NUM_LIT:4>] = '<STR_LIT>'<EOL><DEDENT><DEDENT>m = self.ptc.CRE_TIMEHMS2.search(inputString[startpos:])<EOL>if m is not None:<EOL><INDENT>if leftmost_match[<NUM_LIT:1>] == <NUM_LIT:0> orleftmost_match[<NUM_LIT:0>] > m.start('<STR_LIT>') + startpos:<EOL><INDENT>leftmost_match[<NUM_LIT:0>] = m.start('<STR_LIT>') + startpos<EOL>leftmost_match[<NUM_LIT:1>] = m.end('<STR_LIT>') + startpos<EOL>leftmost_match[<NUM_LIT:2>] = inputString[leftmost_match[<NUM_LIT:0>]:<EOL>leftmost_match[<NUM_LIT:1>]]<EOL>leftmost_match[<NUM_LIT:3>] = <NUM_LIT:2><EOL>leftmost_match[<NUM_LIT:4>] = '<STR_LIT>'<EOL><DEDENT><DEDENT>m = self.ptc.CRE_TIMEHMS.search(inputString[startpos:])<EOL>if m is not None:<EOL><INDENT>if leftmost_match[<NUM_LIT:1>] == <NUM_LIT:0> orleftmost_match[<NUM_LIT:0>] > m.start('<STR_LIT>') + startpos:<EOL><INDENT>leftmost_match[<NUM_LIT:0>] = m.start('<STR_LIT>') + startpos<EOL>if m.group('<STR_LIT>') is not None:<EOL><INDENT>leftmost_match[<NUM_LIT:1>] = m.end('<STR_LIT>') + startpos<EOL><DEDENT>else:<EOL><INDENT>leftmost_match[<NUM_LIT:1>] = m.end('<STR_LIT>') + startpos<EOL><DEDENT>leftmost_match[<NUM_LIT:2>] = inputString[leftmost_match[<NUM_LIT:0>]:<EOL>leftmost_match[<NUM_LIT:1>]]<EOL>leftmost_match[<NUM_LIT:3>] = <NUM_LIT:2><EOL>leftmost_match[<NUM_LIT:4>] = '<STR_LIT>'<EOL><DEDENT><DEDENT>if len(matches) > <NUM_LIT:0> and matches[-<NUM_LIT:1>][<NUM_LIT:3>] == <NUM_LIT:0>:<EOL><INDENT>m = self.ptc.CRE_UNITS_ONLY.search(inputString[startpos:])<EOL>if m is not None andinputString[startpos:startpos +<EOL>m.start()].strip() == '<STR_LIT>':<EOL><INDENT>debug and log.debug('<STR_LIT>',<EOL>m.group())<EOL>if leftmost_match[<NUM_LIT:1>] == <NUM_LIT:0> orleftmost_match[<NUM_LIT:0>] > m.start() + startpos:<EOL><INDENT>leftmost_match[<NUM_LIT:0>] = m.start() + startpos<EOL>leftmost_match[<NUM_LIT:1>] = m.end() + startpos<EOL>leftmost_match[<NUM_LIT:2>] = m.group()<EOL>leftmost_match[<NUM_LIT:3>] = <NUM_LIT:3><EOL>leftmost_match[<NUM_LIT:4>] = '<STR_LIT>'<EOL><DEDENT><DEDENT><DEDENT>startpos = leftmost_match[<NUM_LIT:1>]<EOL>if startpos == <NUM_LIT:0>:<EOL><INDENT>startpos = len(inputString)<EOL><DEDENT>else:<EOL><INDENT>if leftmost_match[<NUM_LIT:3>] > <NUM_LIT:0>:<EOL><INDENT>m = self.ptc.CRE_NLP_PREFIX.search(<EOL>inputString[:leftmost_match[<NUM_LIT:0>]] +<EOL>'<STR_LIT:U+0020>' + str(leftmost_match[<NUM_LIT:3>]))<EOL>if m is not None:<EOL><INDENT>leftmost_match[<NUM_LIT:0>] = m.start('<STR_LIT>')<EOL>leftmost_match[<NUM_LIT:2>] = inputString[leftmost_match[<NUM_LIT:0>]:<EOL>leftmost_match[<NUM_LIT:1>]]<EOL><DEDENT><DEDENT>matches.append(leftmost_match)<EOL><DEDENT><DEDENT>proximity_matches = []<EOL>if len(matches) > <NUM_LIT:1>:<EOL><INDENT>combined = '<STR_LIT>'<EOL>from_match_index = <NUM_LIT:0><EOL>date = matches[<NUM_LIT:0>][<NUM_LIT:3>] == <NUM_LIT:1><EOL>time = matches[<NUM_LIT:0>][<NUM_LIT:3>] == <NUM_LIT:2><EOL>units = matches[<NUM_LIT:0>][<NUM_LIT:3>] == <NUM_LIT:3><EOL>for i in range(<NUM_LIT:1>, len(matches)):<EOL><INDENT>endofprevious = matches[i - <NUM_LIT:1>][<NUM_LIT:1>]<EOL>begofcurrent = matches[i][<NUM_LIT:0>]<EOL>if orig_inputstring[endofprevious:<EOL>begofcurrent].lower().strip() != '<STR_LIT>':<EOL><INDENT>if date or time or units:<EOL><INDENT>combined = orig_inputstring[matches[from_match_index]<EOL>[<NUM_LIT:0>]:matches[i - <NUM_LIT:1>][<NUM_LIT:1>]]<EOL>parsed_datetime, flags = self.parse(combined,<EOL>sourceTime,<EOL>version)<EOL>proximity_matches.append((<EOL>datetime.datetime(*parsed_datetime[:<NUM_LIT:6>]),<EOL>flags,<EOL>matches[from_match_index][<NUM_LIT:0>],<EOL>matches[i - <NUM_LIT:1>][<NUM_LIT:1>],<EOL>combined))<EOL><DEDENT>from_match_index = i<EOL>date = matches[i][<NUM_LIT:3>] == <NUM_LIT:1><EOL>time = matches[i][<NUM_LIT:3>] == <NUM_LIT:2><EOL>units = matches[i][<NUM_LIT:3>] == <NUM_LIT:3><EOL>continue<EOL><DEDENT>else:<EOL><INDENT>if matches[i][<NUM_LIT:3>] == <NUM_LIT:1>:<EOL><INDENT>date = True<EOL><DEDENT>if matches[i][<NUM_LIT:3>] == <NUM_LIT:2>:<EOL><INDENT>time = True<EOL><DEDENT>if matches[i][<NUM_LIT:3>] == <NUM_LIT:3>:<EOL><INDENT>units = True<EOL><DEDENT><DEDENT><DEDENT>if date or time or units:<EOL><INDENT>combined = orig_inputstring[matches[from_match_index][<NUM_LIT:0>]:<EOL>matches[len(matches) - <NUM_LIT:1>][<NUM_LIT:1>]]<EOL>parsed_datetime, flags = self.parse(combined, sourceTime,<EOL>version)<EOL>proximity_matches.append((<EOL>datetime.datetime(*parsed_datetime[:<NUM_LIT:6>]),<EOL>flags,<EOL>matches[from_match_index][<NUM_LIT:0>],<EOL>matches[len(matches) - <NUM_LIT:1>][<NUM_LIT:1>],<EOL>combined))<EOL><DEDENT><DEDENT>elif len(matches) == <NUM_LIT:0>:<EOL><INDENT>return None<EOL><DEDENT>else:<EOL><INDENT>if matches[<NUM_LIT:0>][<NUM_LIT:3>] == <NUM_LIT:0>:  <EOL><INDENT>return None<EOL><DEDENT>else:<EOL><INDENT>combined = orig_inputstring[matches[<NUM_LIT:0>][<NUM_LIT:0>]:matches[<NUM_LIT:0>][<NUM_LIT:1>]]<EOL>parsed_datetime, flags = self.parse(matches[<NUM_LIT:0>][<NUM_LIT:2>], sourceTime,<EOL>version)<EOL>proximity_matches.append((<EOL>datetime.datetime(*parsed_datetime[:<NUM_LIT:6>]),<EOL>flags,<EOL>matches[<NUM_LIT:0>][<NUM_LIT:0>],<EOL>matches[<NUM_LIT:0>][<NUM_LIT:1>],<EOL>combined))<EOL><DEDENT><DEDENT>return tuple(proximity_matches)<EOL>
Utilizes parse() after making judgements about what datetime
        information belongs together.

        It makes logical groupings based on proximity and returns a parsed
        datetime for each matched grouping of datetime text, along with
        location info within the given inputString.

        @type  inputString: string
        @param inputString: natural language text to evaluate
        @type  sourceTime:  struct_time
        @param sourceTime:  C{struct_time} value to use as the base
        @type  version:     integer
        @param version:     style version, default will use L{Calendar}
                            parameter version value

        @rtype:  tuple or None
        @return: tuple of tuples in the format (parsed_datetime as
                 datetime.datetime, flags as int, start_pos as int,
                 end_pos as int, matched_text as string) or None if there
                 were no matches