def parse_query_string(self, query):
if not query:<EOL><INDENT>return None<EOL><DEDENT>if query[<NUM_LIT:0>] == '<STR_LIT:(>':<EOL><INDENT>index = self.find_closing_braces(query)<EOL>if index != len(query) - <NUM_LIT:1>:<EOL><INDENT>raise Exception("<STR_LIT>")<EOL><DEDENT>else:<EOL><INDENT>return self.parse_query_string(query[<NUM_LIT:1>:-<NUM_LIT:1>])<EOL><DEDENT><DEDENT>start_index = query.find("<STR_LIT:(>")<EOL>if start_index < <NUM_LIT:0>:<EOL><INDENT>try:<EOL><INDENT>constant = float(query)<EOL>return constant<EOL><DEDENT>except ValueError:<EOL><INDENT>raise Exception("<STR_LIT>")<EOL><DEDENT><DEDENT>token = query[:start_index]<EOL>if token not in self.operators:<EOL><INDENT>raise Exception("<STR_LIT>" + token)<EOL><DEDENT>rest_of_the_query = query[start_index:]<EOL>braces_end_index = self.find_closing_braces(rest_of_the_query)<EOL>if braces_end_index != len(rest_of_the_query) - <NUM_LIT:1>:<EOL><INDENT>raise Exception("<STR_LIT>")<EOL><DEDENT>parts = self.get_sub_parts(rest_of_the_query[<NUM_LIT:1>:-<NUM_LIT:1>])<EOL>if token == "<STR_LIT>":<EOL><INDENT>return self.operators[token](parts)<EOL><DEDENT>children = []<EOL>for part in parts:<EOL><INDENT>children.append(self.parse_query_string(part))<EOL><DEDENT>node = self.operators[token](children)<EOL>return node<EOL>
Returns a parse tree for the query, each of the node is a
        subclass of Operator. This is both a lexical as well as syntax analyzer step.