scan method
bool
scan(
- FsharpExternalScannerState state,
- TreeSitterExternalLexer lexer,
- List<
bool> validSymbols
override
Implementation
@override
bool scan(
FsharpExternalScannerState state,
TreeSitterExternalLexer lexer,
List<bool> validSymbols,
) {
bool valid(FsharpExternalToken token) =>
token.index < validSymbols.length && validSymbols[token.index];
void emit(FsharpExternalToken token) =>
lexer.setResultSymbol(symbols[token.index]);
if (valid(FsharpExternalToken.virtualOpenSection) &&
valid(FsharpExternalToken.virtualEndSection) &&
valid(FsharpExternalToken.virtualEndDeclaration)) {
return false;
}
if (state.runback.isNotEmpty &&
state.runback.last == 0 &&
valid(FsharpExternalToken.virtualEndDeclaration)) {
state.runback.removeLast();
emit(FsharpExternalToken.virtualEndDeclaration);
return true;
}
if (state.runback.isNotEmpty &&
state.runback.last == 1 &&
valid(FsharpExternalToken.virtualEndSection)) {
state.runback.removeLast();
emit(FsharpExternalToken.virtualEndSection);
return true;
}
state.runback.clear();
var hasNewline = false;
lexer.markEnd();
while (true) {
if (lexer.lookahead == 0x20) {
_skip(lexer);
} else if (lexer.lookahead == 0x0a) {
_skip(lexer);
hasNewline = true;
while (true) {
if (lexer.lookahead == 0x20) {
_skip(lexer);
} else {
state.indentLength = lexer.column;
break;
}
}
} else if (lexer.lookahead == 0x0d) {
_skip(lexer);
} else if (valid(FsharpExternalToken.virtualEndDeclaration) &&
lexer.lookahead == 0x3b) {
_advance(lexer);
lexer.markEnd();
emit(FsharpExternalToken.virtualEndDeclaration);
return true;
} else if (valid(FsharpExternalToken.virtualEndSection) &&
(lexer.lookahead == 0x29 ||
lexer.lookahead == 0x5d ||
lexer.lookahead == 0x7d)) {
emit(FsharpExternalToken.virtualEndSection);
state.indentLengthStack.removeLast();
return true;
} else if (valid(FsharpExternalToken.virtualEndSection) &&
lexer.lookahead == 0x7c) {
_skip(lexer);
if (lexer.lookahead == 0x7d || lexer.lookahead == 0x5d) {
emit(FsharpExternalToken.virtualEndSection);
state.indentLengthStack.removeLast();
return true;
}
} else if (lexer.isEof) {
if (valid(FsharpExternalToken.virtualEndSection)) {
emit(FsharpExternalToken.virtualEndSection);
return true;
}
if (valid(FsharpExternalToken.virtualEndDeclaration)) {
emit(FsharpExternalToken.virtualEndDeclaration);
return true;
}
break;
} else {
break;
}
}
final closing =
lexer.lookahead == 0x5d ||
lexer.lookahead == 0x29 ||
lexer.lookahead == 0x7d;
if (valid(FsharpExternalToken.virtualOpenSection) && !lexer.isEof) {
// Preserve the pinned scanner's mutation order: it pushes before
// rejecting a closing delimiter or a `|}`/`|]` sequence.
state.indentLengthStack.add(lexer.column);
if (closing) return false;
if (lexer.lookahead == 0x7c) {
_skip(lexer);
if (lexer.lookahead == 0x7d || lexer.lookahead == 0x5d) return false;
}
emit(FsharpExternalToken.virtualOpenSection);
return true;
} else if (valid(FsharpExternalToken.blockCommentContent)) {
// `can_call_mark_end` is permanently true in the pinned C++ source.
lexer.markEnd();
while (true) {
if (lexer.lookahead == 0) {
break;
} else if (lexer.lookahead != 0x28 && lexer.lookahead != 0x2a) {
_advance(lexer);
} else if (lexer.lookahead == 0x2a) {
lexer.markEnd();
_advance(lexer);
if (lexer.lookahead == 0x29) break;
} else if (_scanBlockComment(lexer)) {
lexer.markEnd();
_advance(lexer);
if (lexer.lookahead == 0x2a) break;
}
}
emit(FsharpExternalToken.blockCommentContent);
return true;
} else if (hasNewline) {
state.runback.clear();
while (state.indentLength <= state.indentLengthStack.last) {
if (state.indentLength == state.indentLengthStack.last) {
// Equal indentation before either comment form does not end a
// declaration in the pinned scanner.
if (lexer.lookahead == 0x2f) {
_skip(lexer);
if (lexer.lookahead == 0x2f) break;
}
if (lexer.lookahead == 0x28) {
_skip(lexer);
if (lexer.lookahead == 0x2a) break;
}
state.runback.add(0);
break;
} else if (state.indentLength < state.indentLengthStack.last) {
state.indentLengthStack.removeLast();
state.runback.add(1);
}
}
state.runback.setAll(0, state.runback.reversed.toList());
if (state.runback.isNotEmpty &&
state.runback.last == 0 &&
valid(FsharpExternalToken.virtualEndDeclaration)) {
state.runback.removeLast();
emit(FsharpExternalToken.virtualEndDeclaration);
return true;
}
if (state.runback.isNotEmpty &&
state.runback.last == 1 &&
valid(FsharpExternalToken.virtualEndSection)) {
state.runback.removeLast();
emit(FsharpExternalToken.virtualEndSection);
return true;
} else if (lexer.isEof && valid(FsharpExternalToken.virtualEndSection)) {
emit(FsharpExternalToken.virtualEndSection);
return true;
}
}
return false;
}