Skip to content

Commit bf21828

Browse files
committed
Account for suggested changes
1 parent 4528396 commit bf21828

File tree

1 file changed

+37
-35
lines changed

1 file changed

+37
-35
lines changed

src/libexpr/parser-state.hh

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
///@file
33

44
#include "eval.hh"
5+
#include <variant>
56

67
namespace nix {
78

@@ -172,57 +173,58 @@ enum IndentChar {
172173
Space = ' ',
173174
};
174175

176+
struct StripState {
177+
std::optional<IndentChar> indentChar = std::nullopt;
178+
bool start = true;
179+
size_t min = -1;
180+
size_t cur = 0;
181+
bool indent(char c) {
182+
if (!start) return true;
183+
indentChar = indentChar.value_or(IndentChar(c));
184+
bool ok = (indentChar == c);
185+
cur += ok;
186+
return ok;
187+
}
188+
void stop() {
189+
start = false;
190+
min = std::min(min, cur);
191+
}
192+
void reset() {
193+
start = true;
194+
cur = 0;
195+
}
196+
};
197+
175198
inline Expr * ParserState::stripIndentation(const PosIdx pos,
176199
std::vector<std::pair<PosIdx, std::variant<Expr *, StringToken>>> && es)
177200
{
178201
if (es.empty()) return new ExprString("");
179202

180203
/* Figure out the minimum indentation. Note that by design
181204
whitespace-only final lines are not taken into account. (So
182-
the " " in "\n ''" is ignored, but the " " in "\n foo''" is.) */
205+
the " " in "\n ''" is ignored, but the " " in "\n foo''" is not.) */
183206
std::optional<IndentChar> indentChar = std::nullopt;
184-
bool atStartOfLine = true; /* = seen only whitespace in the current line */
185-
size_t minIndent = 1000000;
186-
size_t curIndent = 0;
207+
StripState state;
187208
for (auto & [i_pos, i] : es) {
188-
auto * str = std::get_if<StringToken>(&i);
189-
if (!str || !str->hasIndentation) {
190-
/* Anti-quotations and escaped characters end the current start-of-line whitespace. */
191-
if (atStartOfLine) {
192-
atStartOfLine = false;
193-
if (curIndent < minIndent) minIndent = curIndent;
194-
}
209+
StringToken* x = std::get_if<StringToken>(&i);
210+
if (!x || !x->hasIndentation) {
211+
state.stop();
195212
continue;
196-
}
197-
for (size_t j = 0; j < str->l; ++j) {
198-
auto cur = str->p[j];
199-
if (atStartOfLine) {
200-
if (
201-
indentChar == cur
202-
|| (!indentChar && (cur == ' ' || cur == '\t'))
203-
) {
204-
if (!indentChar) {
205-
indentChar = IndentChar(cur);
206-
}
207-
curIndent++;
208-
} else if (cur == '\n') {
209-
/* Empty line, doesn't influence minimum
210-
indentation. */
211-
curIndent = 0;
212-
} else {
213-
atStartOfLine = false;
214-
if (curIndent < minIndent) minIndent = curIndent;
215-
}
216-
} else if (cur == '\n') {
217-
atStartOfLine = true;
218-
curIndent = 0;
213+
};
214+
std::string_view view = *x;
215+
for (auto cur: view) {
216+
if (cur == '\n') {
217+
state.reset();
218+
continue;
219219
}
220+
if (!state.indent(cur)) state.stop();
220221
}
221222
}
222223

224+
size_t minIndent = state.min;
223225
/* Strip spaces from each line. */
224226
auto * es2 = new std::vector<std::pair<PosIdx, Expr *>>;
225-
atStartOfLine = true;
227+
bool atStartOfLine = true;
226228
size_t curDropped = 0;
227229
size_t n = es.size();
228230
auto i = es.begin();

0 commit comments

Comments
 (0)