def grammar_parse(cls, text, index, sessiondata): tstring = text.string.upper() while (len(cls.string) + index > len(text.string)) and cls.string.upper().startswith(tstring[index:]): if text.eof: break text = yield (None, None) if text.string.upper().startswith(cls.string.upper(), index): yield (len(cls.string), cls(cls.string)) yield error_result(index, cls)
def grammar_parse(cls, text, index, sessiondata): while (len(cls.string) + index > len(text.string)) and cls.string.startswith(text.string[index:]): if text.eof: break text = yield (None, None) try: next_char = text.string[index + len(cls.string)] except IndexError: next_char = None if text.string.startswith(cls.string, index) and (not next_char or next_char not in cls.keyword_chars): yield (len(cls.string), cls(cls.string)) yield error_result(index, cls)
def grammar_parse(cls, text, index, sessiondata): while True: string = text.string if index == 0 and cls.boltest and not text.bol: # This will make sure that a "^" in the pattern can't match on the # beginning of the text. string = " " + string index = 1 m = cls.regexp.match(string, index) if not m: break end = m.end() if end < len(string) or text.eof: yield (end - index, cls(string[index:end])) break else: # We need more text before we can be sure we"re at the end. text = yield (None, None) yield util.error_result(index, cls)
def grammar_parse(cls, text, index, session): """This grammar will return an impossibly-large offset (which is a no-no)""" yield (len(text.string) + 1, cls('')) yield error_result(index, cls)
def grammar_parse(cls, text, index, session): """This grammar will return a negative offset (which is a no-no)""" yield (-1, cls('')) yield error_result(index, cls)
def grammar_parse(cls, text, index, session): """This grammar will return an offset which is not an int, None, or False (which is a no-no)""" yield (1.0, cls('')) yield error_result(index, cls)
def grammar_parse(cls, text, index, session): """This grammar will return a result which is not a 2-tuple (which is a no-no)""" yield (1, cls(''), 2) yield error_result(index, cls)
def grammar_parse(cls, text, index, session): """This grammar will return a None result even if eof=True (which is a no-no)""" yield (None, None) yield error_result(index, cls)
def grammar_parse(cls, text, index, sessiondata): """ This method is called by the :mod:`modgrammar` parser system to actually attempt to match this grammar against a piece of text. This method is not intended to be called directly by an application (use the :meth:`parser` method to obtain a :class:`GrammarParser` object and use that). In advanced cases, this method can be overridden to provide custom parsing behaviors for a particular grammar type. NOTE: Overriding this method is very complicated and currently beyond the scope of this documentation. This is not recommended for anyone who does not understand the :mod:`modgrammar` parser design very well. (Someday, with luck, there will be some more documentation written on this advanced topic.) """ grammar = cls.grammar grammar_min = cls.grammar_min grammar_max = cls.grammar_max greedy = cls.grammar_greedy if cls.grammar_whitespace is True: whitespace_re = util._whitespace_re else: whitespace_re = cls.grammar_whitespace objs = [] states = [] positions = [] best_error = None pos = index first_pos = None while True: # Forward ho! while True: if not greedy and len(objs) >= grammar_min: # If we're not "greedy", then try returning every match as soon as we # get it (which will naturally return the shortest matches first) yield (pos - index, cls(text.string, index, pos, objs)) # We need to copy objs for any further stuff, since it's now part of # the object we yielded above, which our caller may be keeping for # later, so if we modify it in-place we'll be screwing up the # 'entities' list of that object in the process. objs = list(objs) if len(objs) >= grammar_max: break prews_pos = pos if whitespace_re: while True: m = whitespace_re.match(text.string, pos) if m: pos = m.end() if pos < len(text.string) or text.eof: break text = yield (None, None) if first_pos is None: first_pos = pos s = grammar[len(objs)].grammar_parse(text, pos, sessiondata) offset, obj = next(s) while offset is None: if text.eof: # Subgrammars should not be asking for more data after eof. raise InternalError( "{0} requested more data when at EOF".format( grammar[len(objs)])) text = yield (None, None) offset, obj = s.send(text) if offset is False: best_error = util.update_best_error(best_error, obj) pos = prews_pos break objs.append(obj) states.append((pos, s)) pos += offset # Went as far as we can forward and it didn't work. Backtrack until we # find something else to follow... while True: if greedy and len(objs) >= grammar_min: # If we are greedy, then return matches only after we've gone as far # forward as possible, while we're backtracking (returns the longest # matches first) yield (pos - index, cls(text.string, index, pos, objs)) # We need to copy objs for any further stuff, since it's now part of # the object we yielded above, which our caller may be keeping for # later, so if we modify it in-place we'll be screwing up the # 'entities' list of that object in the process. objs = list(objs) if not states: break pos, s = states[-1] offset, obj = next(s) while offset is None: if text.eof: # Subgrammars should not be asking for more data after eof. raise InternalError( "{0} requested more data when at EOF".format( grammar[len(objs) - 1])) text = yield (None, None) offset, obj = s.send(text) if offset is False: best_error = util.update_best_error(best_error, obj) states.pop() objs.pop() else: objs[-1] = obj pos += offset break # Have we gone all the way back to the beginning? # If so, give up. If not, loop around and try going forward again. if not states: break if cls.grammar_error_override: # If our sub-grammars failed to match, but we've got # grammar_error_override set, return ourselves as the failed match # grammar instead. yield util.error_result(index, cls) elif ((len(cls.grammar) == 1) and (best_error[0] == first_pos) and (cls.grammar_desc != cls.grammar_name)): # We're just a simple wrapper (i.e. an alias) around another single # grammar class, and it failed to match, and we have a custom # grammar_desc. Return ourselves as the failed match grammar so the # ParseError will contain our grammar_desc instead. yield util.error_result(index, cls) else: yield util.error_result(*best_error)
def grammar_parse(cls, text, index, session): """This grammar will return an impossibly-large offset (which is a no-no)""" yield (len(text.string)+1, cls('')) yield error_result(index, cls)
def grammar_parse(cls, text, index, sessiondata): """ This method is called by the :mod:`modgrammar` parser system to actually attempt to match this grammar against a piece of text. This method is not intended to be called directly by an application (use the :meth:`parser` method to obtain a :class:`GrammarParser` object and use that). In advanced cases, this method can be overridden to provide custom parsing behaviors for a particular grammar type. NOTE: Overriding this method is very complicated and currently beyond the scope of this documentation. This is not recommended for anyone who does not understand the :mod:`modgrammar` parser design very well. (Someday, with luck, there will be some more documentation written on this advanced topic.) """ grammar = cls.grammar grammar_min = cls.grammar_min grammar_max = cls.grammar_max greedy = cls.grammar_greedy if cls.grammar_whitespace is True: whitespace_re = util._whitespace_re else: whitespace_re = cls.grammar_whitespace objs = [] states = [] positions = [] best_error = None pos = index first_pos = None while True: # Forward ho! while True: if not greedy and len(objs) >= grammar_min: # If we're not "greedy", then try returning every match as soon as we # get it (which will naturally return the shortest matches first) yield (pos - index, cls(text.string, index, pos, objs)) # We need to copy objs for any further stuff, since it's now part of # the object we yielded above, which our caller may be keeping for # later, so if we modify it in-place we'll be screwing up the # 'entities' list of that object in the process. objs = list(objs) if len(objs) >= grammar_max: break prews_pos = pos if whitespace_re: while True: m = whitespace_re.match(text.string, pos) if m: pos = m.end() if pos < len(text.string) or text.eof: break text = yield (None, None) if first_pos is None: first_pos = pos s = grammar[len(objs)].grammar_parse(text, pos, sessiondata) offset, obj = next(s) while offset is None: if text.eof: # Subgrammars should not be asking for more data after eof. raise InternalError("{0} requested more data when at EOF".format(grammar[len(objs)])) text = yield (None, None) offset, obj = s.send(text) if offset is False: best_error = util.update_best_error(best_error, obj) pos = prews_pos break objs.append(obj) states.append((pos, s)) pos += offset # Went as far as we can forward and it didn't work. Backtrack until we # find something else to follow... while True: if greedy and len(objs) >= grammar_min: # If we are greedy, then return matches only after we've gone as far # forward as possible, while we're backtracking (returns the longest # matches first) yield (pos - index, cls(text.string, index, pos, objs)) # We need to copy objs for any further stuff, since it's now part of # the object we yielded above, which our caller may be keeping for # later, so if we modify it in-place we'll be screwing up the # 'entities' list of that object in the process. objs = list(objs) if not states: break pos, s = states[-1] offset, obj = next(s) while offset is None: if text.eof: # Subgrammars should not be asking for more data after eof. raise InternalError("{0} requested more data when at EOF".format(grammar[len(objs) - 1])) text = yield (None, None) offset, obj = s.send(text) if offset is False: best_error = util.update_best_error(best_error, obj) states.pop() objs.pop() else: objs[-1] = obj pos += offset break # Have we gone all the way back to the beginning? # If so, give up. If not, loop around and try going forward again. if not states: break if cls.grammar_error_override: # If our sub-grammars failed to match, but we've got # grammar_error_override set, return ourselves as the failed match # grammar instead. yield util.error_result(index, cls) elif ((len(cls.grammar) == 1) and (best_error[0] == first_pos) and (cls.grammar_desc != cls.grammar_name) ): # We're just a simple wrapper (i.e. an alias) around another single # grammar class, and it failed to match, and we have a custom # grammar_desc. Return ourselves as the failed match grammar so the # ParseError will contain our grammar_desc instead. yield util.error_result(index, cls) else: yield util.error_result(*best_error)