102 [[nodiscard]]
inline std::vector<token>
layout(std::span<const token> tokens,
103 const std::vector<bool>& mode_significant = {})
105 std::vector<token> out;
106 std::vector<std::size_t> levels {0};
107 bool started {
false};
108 std::size_t previous_line {0};
109 position end_position {0, 1, 1};
111 for (
const token& current : tokens) {
113 end_position = current.start;
118 const bool significant {mode_significant.empty()
119 || current.mode_id >= mode_significant.size()
120 || mode_significant[current.mode_id]};
121 if (significant && (!started || current.start.line != previous_line)) {
123 out.push_back(token {
newline, {}, current.start});
125 const std::size_t width {current.start.
column - 1};
126 if (width > levels.back()) {
127 levels.push_back(width);
128 out.push_back(token {
indent, {}, current.start});
131 while (width < levels.back()) {
133 out.push_back(token {
dedent, {}, current.start});
135 if (width != levels.back()) {
136 throw layout_error(
"inconsistent indentation", current.start);
139 previous_line = current.start.line;
142 out.push_back(current);
146 out.push_back(token {
newline, {}, end_position});
148 while (levels.back() > 0) {
150 out.push_back(token {
dedent, {}, end_position});