toParsedLines function
Converts source text to parsed lines
Implementation
ScanResult toParsedLines(String source, int indentSize, bool strict) {
if (source.trim().isEmpty) {
return const ScanResult(lines: [], blankLines: []);
}
final rawLines = source.split('\n');
final parsed = <ParsedLine>[];
final blankLines = <BlankLineInfo>[];
for (int i = 0; i < rawLines.length; i++) {
final raw = rawLines[i];
final lineNumber = i + 1;
int indent = 0;
while (indent < raw.length && raw[indent] == space) {
indent++;
}
final content = raw.substring(indent);
// Track blank lines
if (content.trim().isEmpty) {
final depth = _computeDepthFromIndent(indent, indentSize);
blankLines.add(BlankLineInfo(
lineNumber: lineNumber,
indent: indent,
depth: depth,
));
continue;
}
final depth = _computeDepthFromIndent(indent, indentSize);
// Strict mode validation
if (strict) {
// Find the full leading whitespace region (spaces and tabs)
int wsEnd = 0;
while (wsEnd < raw.length && (raw[wsEnd] == space || raw[wsEnd] == tab)) {
wsEnd++;
}
// Check for tabs in leading whitespace (before actual content)
if (raw.substring(0, wsEnd).contains(tab)) {
throw FormatException(
'Line $lineNumber: Tabs are not allowed in indentation in strict mode');
}
// Check for exact multiples of indentSize
if (indent > 0 && indent % indentSize != 0) {
throw FormatException(
'Line $lineNumber: Indentation must be exact multiple of $indentSize, but found $indent spaces');
}
}
parsed.add(ParsedLine(
raw: raw,
indent: indent,
content: content,
depth: depth,
lineNumber: lineNumber,
));
}
return ScanResult(lines: parsed, blankLines: blankLines);
}