def parse(self, template): """ Parse a template string starting at some index. This method uses the current tag delimiter. Arguments: template: a unicode string that is the template to parse. index: the index at which to start parsing. Returns: a ParsedTemplate instance. """ self._compile_delimiters() start_index = 0 content_end_index, parsed_section, section_key = None, None, None parsed_template = ParsedTemplate() states = [] while True: match = self._template_re.search(template, start_index) if match is None: break match_index = match.start() end_index = match.end() matches = match.groupdict() # Normalize the matches dictionary. if matches['change'] is not None: matches.update(tag='=', tag_key=matches['delims']) elif matches['raw'] is not None: matches.update(tag='&', tag_key=matches['raw_name']) tag_type = matches['tag'] tag_key = matches['tag_key'] leading_whitespace = matches['whitespace'] # Standalone (non-interpolation) tags consume the entire line, # both leading whitespace and trailing newline. did_tag_begin_line = match_index == 0 or template[match_index - 1] in END_OF_LINE_CHARACTERS did_tag_end_line = end_index == len(template) or template[end_index] in END_OF_LINE_CHARACTERS is_tag_interpolating = tag_type in ['', '&'] if did_tag_begin_line and did_tag_end_line and not is_tag_interpolating: if end_index < len(template): end_index += template[end_index] == '\r' and 1 or 0 if end_index < len(template): end_index += template[end_index] == '\n' and 1 or 0 elif leading_whitespace: match_index += len(leading_whitespace) leading_whitespace = '' # Avoid adding spurious empty strings to the parse tree. if start_index != match_index: parsed_template.add(template[start_index:match_index]) start_index = end_index if tag_type in ('#', '^', '%'): # Cache current state. state = (tag_type, end_index, section_key, parsed_template) states.append(state) # Initialize new state section_key, parsed_template = tag_key, ParsedTemplate() continue if tag_type == '/': if tag_key != section_key: raise ParsingError("Section end tag mismatch: %s != %s" % (tag_key, section_key)) # Restore previous state with newly found section data. parsed_section = parsed_template (tag_type, section_start_index, section_key, parsed_template) = states.pop() node = self._make_section_node(template, tag_type, tag_key, parsed_section, section_start_index, match_index) else: node = self._make_interpolation_node(tag_type, tag_key, leading_whitespace) parsed_template.add(node) # Avoid adding spurious empty strings to the parse tree. if start_index != len(template): parsed_template.add(template[start_index:]) return parsed_template
def parse(self, template): """ Parse a template string starting at some index. This method uses the current tag delimiter. Arguments: template: a unicode string that is the template to parse. index: the index at which to start parsing. Returns: a ParsedTemplate instance. """ self._compile_delimiters() start_index = 0 content_end_index, parsed_section, section_key = None, None, None parsed_template = ParsedTemplate() states = [] while True: match = self._template_re.search(template, start_index) if match is None: break match_index = match.start() end_index = match.end() matches = match.groupdict() # Normalize the matches dictionary. if matches['change'] is not None: matches.update(tag='=', tag_key=matches['delims']) elif matches['raw'] is not None: matches.update(tag='&', tag_key=matches['raw_name']) tag_type = matches['tag'] tag_key = matches['tag_key'] leading_whitespace = matches['whitespace'] # Standalone (non-interpolation) tags consume the entire line, # both leading whitespace and trailing newline. did_tag_begin_line = match_index == 0 or template[ match_index - 1] in END_OF_LINE_CHARACTERS did_tag_end_line = end_index == len( template) or template[end_index] in END_OF_LINE_CHARACTERS is_tag_interpolating = tag_type in ['', '&'] if did_tag_begin_line and did_tag_end_line and not is_tag_interpolating: if end_index < len(template): end_index += template[end_index] == '\r' and 1 or 0 if end_index < len(template): end_index += template[end_index] == '\n' and 1 or 0 elif leading_whitespace: match_index += len(leading_whitespace) leading_whitespace = '' # Avoid adding spurious empty strings to the parse tree. if start_index != match_index: parsed_template.add(template[start_index:match_index]) start_index = end_index if tag_type in ('#', '^'): # Cache current state. state = (tag_type, end_index, section_key, parsed_template) states.append(state) # Initialize new state section_key, parsed_template = tag_key, ParsedTemplate() continue if tag_type == '/': if tag_key != section_key: raise ParsingError("Section end tag mismatch: %s != %s" % (tag_key, section_key)) # Restore previous state with newly found section data. parsed_section = parsed_template (tag_type, section_start_index, section_key, parsed_template) = states.pop() node = self._make_section_node(template, tag_type, tag_key, parsed_section, section_start_index, match_index) else: node = self._make_interpolation_node(tag_type, tag_key, leading_whitespace) parsed_template.add(node) # Avoid adding spurious empty strings to the parse tree. if start_index != len(template): parsed_template.add(template[start_index:]) return parsed_template
def parse(self, template, start_index=0, section_key=None): """ Parse a template string starting at some index. This method uses the current tag delimiter. Arguments: template: a unicode string that is the template to parse. index: the index at which to start parsing. Returns: a ParsedTemplate instance. """ parse_tree = [] index = start_index while True: match = self._template_re.search(template, index) if match is None: break match_index = match.start() end_index = match.end() before_tag = template[index : match_index] parse_tree.append(before_tag) matches = match.groupdict() # Normalize the matches dictionary. if matches['change'] is not None: matches.update(tag='=', tag_key=matches['delims']) elif matches['raw'] is not None: matches.update(tag='&', tag_key=matches['raw_name']) tag_type = matches['tag'] tag_key = matches['tag_key'] leading_whitespace = matches['whitespace'] # Standalone (non-interpolation) tags consume the entire line, # both leading whitespace and trailing newline. did_tag_begin_line = match_index == 0 or template[match_index - 1] in END_OF_LINE_CHARACTERS did_tag_end_line = end_index == len(template) or template[end_index] in END_OF_LINE_CHARACTERS is_tag_interpolating = tag_type in ['', '&'] if did_tag_begin_line and did_tag_end_line and not is_tag_interpolating: if end_index < len(template): end_index += template[end_index] == '\r' and 1 or 0 if end_index < len(template): end_index += template[end_index] == '\n' and 1 or 0 elif leading_whitespace: parse_tree.append(leading_whitespace) match_index += len(leading_whitespace) leading_whitespace = '' if tag_type == '/': if tag_key != section_key: raise ParsingError("Section end tag mismatch: %s != %s" % (tag_key, section_key)) return ParsedTemplate(parse_tree), match_index, end_index index = self._handle_tag_type(template, parse_tree, tag_type, tag_key, leading_whitespace, end_index) # Save the rest of the template. parse_tree.append(template[index:]) return ParsedTemplate(parse_tree)