]> Creatis software - cpPlugins.git/blob - lib/mstch/template_type.cpp
Moved to version 1.0
[cpPlugins.git] / lib / mstch / template_type.cpp
1 #include "template_type.hpp"
2
3 using namespace mstch;
4
5 template_type::template_type(const std::string& str, const delim_type& delims):
6     m_open(delims.first), m_close(delims.second)
7 {
8   tokenize(str);
9   strip_whitespace();
10 }
11
12 template_type::template_type(const std::string& str):
13     m_open("{{"), m_close("}}")
14 {
15   tokenize(str);
16   strip_whitespace();
17 }
18
19 void template_type::process_text(citer begin, citer end) {
20   if (begin == end)
21     return;
22   auto start = begin;
23   for (auto it = begin; it != end; ++it)
24     if (*it == '\n' || it == end - 1) {
25       m_tokens.push_back({{start, it + 1}});
26       start = it + 1;
27     }
28 }
29
30 void template_type::tokenize(const std::string& tmp) {
31   citer beg = tmp.begin();
32   auto npos = std::string::npos;
33
34   for (std::size_t cur_pos = 0; cur_pos < tmp.size();) {
35     auto open_pos = tmp.find(m_open, cur_pos);
36     auto close_pos = tmp.find(
37         m_close, open_pos == npos ? open_pos : open_pos + 1);
38
39     if (close_pos != npos && open_pos != npos) {
40       if (*(beg + open_pos + m_open.size()) == '{' &&
41           *(beg + close_pos + m_close.size()) == '}')
42         ++close_pos;
43
44       process_text(beg + cur_pos, beg + open_pos);
45       cur_pos = close_pos + m_close.size();
46       m_tokens.push_back({{beg + open_pos, beg + close_pos + m_close.size()},
47           m_open.size(), m_close.size()});
48
49       if (cur_pos == tmp.size()) {
50         m_tokens.push_back({{""}});
51         m_tokens.back().eol(true);
52       }
53
54       if (*(beg + open_pos + m_open.size()) == '=' &&
55           *(beg + close_pos - 1) == '=')
56       {
57         auto tok_beg = beg + open_pos + m_open.size() + 1;
58         auto tok_end = beg + close_pos - 1;
59         auto front_skip = first_not_ws(tok_beg, tok_end);
60         auto back_skip = first_not_ws(reverse(tok_end), reverse(tok_beg));
61         m_open = {front_skip, beg + tmp.find(' ', front_skip - beg)};
62         m_close = {beg + tmp.rfind(' ', back_skip - beg) + 1, back_skip + 1};
63       }
64     } else {
65       process_text(beg + cur_pos, tmp.end());
66       cur_pos = close_pos;
67     }
68   }
69 }
70
71 void template_type::strip_whitespace() {
72   auto line_begin = m_tokens.begin();
73   bool has_tag = false, non_space = false;
74
75   for (auto it = m_tokens.begin(); it != m_tokens.end(); ++it) {
76     auto type = (*it).token_type();
77     if (type != token::type::text && type != token::type::variable &&
78         type != token::type::unescaped_variable)
79       has_tag = true;
80     else if (!(*it).ws_only())
81       non_space = true;
82
83     if ((*it).eol()) {
84       if (has_tag && !non_space) {
85         store_prefixes(line_begin);
86
87         auto c = line_begin;
88         for (bool end = false; !end; (*c).ws_only() ? c = m_tokens.erase(c) : ++c)
89           if ((end = (*c).eol()))
90             it = c - 1;
91       }
92
93       non_space = has_tag = false;
94       line_begin = it + 1;
95     }
96   }
97 }
98
99 void template_type::store_prefixes(std::vector<token>::iterator beg) {
100   for (auto cur = beg; !(*cur).eol(); ++cur)
101     if ((*cur).token_type() == token::type::partial &&
102         cur != beg && (*(cur - 1)).ws_only())
103       (*cur).partial_prefix((*(cur - 1)).raw());
104 }