| 2003 | } |
| 2004 | |
| 2005 | void TemplateParser::parse_stmt() |
| 2006 | { |
| 2007 | size_t pos = m_text.find("%}"); |
| 2008 | if (pos == std::string::npos) |
| 2009 | { |
| 2010 | throw TemplateException(m_current_line, "unterminated statement block"); |
| 2011 | } |
| 2012 | |
| 2013 | std::string stmt_text = m_text.substr(1, pos - 1); |
| 2014 | bool has_kill_newline = !stmt_text.empty() && stmt_text.back() == '>'; |
| 2015 | if (has_kill_newline) |
| 2016 | { |
| 2017 | stmt_text.pop_back(); |
| 2018 | } |
| 2019 | uint32_t lineCount = count_newlines(stmt_text); |
| 2020 | |
| 2021 | // Tokenize the control statement. |
| 2022 | token_vector stmt_tokens = tokenize_statement(stmt_text); |
| 2023 | if (!stmt_tokens.empty()) |
| 2024 | { |
| 2025 | token_type_t first_token_type = stmt_tokens[0].get_type(); |
| 2026 | |
| 2027 | // Create control statement nodes. |
| 2028 | switch (first_token_type) |
| 2029 | { |
| 2030 | case token_type_t::FOR_TOKEN: |
| 2031 | push_node(new NodeFor(stmt_tokens, m_node_stack.empty(), m_current_line), token_type_t::ENDFOR_TOKEN); |
| 2032 | break; |
| 2033 | |
| 2034 | case token_type_t::IF_TOKEN: |
| 2035 | push_node(new NodeIf(stmt_tokens, m_current_line), token_type_t::ENDIF_TOKEN); |
| 2036 | break; |
| 2037 | |
| 2038 | case token_type_t::ELIF_TOKEN: |
| 2039 | case token_type_t::ELSE_TOKEN: { |
| 2040 | auto current_if = dynamic_cast<NodeIf *>(m_current_node.get()); |
| 2041 | if (!current_if) |
| 2042 | { |
| 2043 | throw TemplateException(m_current_line, "else/elif without if"); |
| 2044 | } |
| 2045 | |
| 2046 | if (current_if->is_else()) |
| 2047 | { |
| 2048 | throw TemplateException(m_current_line, "if already has else"); |
| 2049 | } |
| 2050 | |
| 2051 | m_current_node = node_ptr(new NodeIf(stmt_tokens, m_current_line)); |
| 2052 | current_if->set_else_if(m_current_node); |
| 2053 | m_current_nodes = &m_current_node->get_children(); |
| 2054 | break; |
| 2055 | } |
| 2056 | |
| 2057 | case token_type_t::DEF_TOKEN: |
| 2058 | push_node(new NodeDef(stmt_tokens, m_current_line), token_type_t::ENDDEF_TOKEN); |
| 2059 | break; |
| 2060 | |
| 2061 | case token_type_t::SET_TOKEN: |
| 2062 | m_current_nodes->push_back(node_ptr(new NodeSet(stmt_tokens, m_current_line))); |
nothing calls this directly
no test coverage detected