def bql_string_complete_p(string): """True if `string` has at least one complete BQL phrase or error. False if empty or if the last BQL phrase is incomplete. """ scanner = scan.BQLScanner(StringIO.StringIO(string), '(string)') semantics = BQLSemantics() parser = grammar.Parser(semantics) nonsemi = False while not semantics.failed: token = scanner.read() if token[0] == -1: # error # Say it's complete so the caller will try to parse it and # choke on the error. return True elif token[0] == 0: # EOF. Hope we have a complete phrase. break elif token[0] != grammar.T_SEMI: # Got a non-semicolon token. Clear any previous phrase, # if we had one. nonsemi = True semantics.phrase = None parser.feed(token) if 0 < len(semantics.errors): return True if semantics.failed: return True return (not nonsemi) or (semantics.phrase is not None)
def parse_bql_string_pos(string): """Yield ``(phrase, pos)`` for each BQL phrase in `string`. `phrase` is the parsed AST. `pos` is zero-based index of the code point at which `phrase` starts. """ scanner = scan.BQLScanner(StringIO.StringIO(string), '(string)') phrases = parse_bql_phrases(scanner) # XXX Don't dig out internals of scanner: fix plex to have a # public API for finding the current position. return ((phrase, scanner.cur_pos) for phrase in phrases)