scan method
bool
scan(
- BitBakeExternalScannerState state,
- TreeSitterExternalLexer lexer,
- List<
bool> validSymbols
override
Implementation
@override
bool scan(
BitBakeExternalScannerState state,
TreeSitterExternalLexer lexer,
List<bool> validSymbols,
) {
if (state.indents.isEmpty) state.indents.add(0);
final errorRecoveryMode =
_valid(validSymbols, BitBakeExternalToken.stringContent) &&
_valid(validSymbols, BitBakeExternalToken.indent);
final withinBrackets =
_valid(validSymbols, BitBakeExternalToken.closeBrace) ||
_valid(validSymbols, BitBakeExternalToken.closeParen) ||
_valid(validSymbols, BitBakeExternalToken.closeBracket);
if (_valid(validSymbols, BitBakeExternalToken.concat) &&
!errorRecoveryMode) {
final c = lexer.lookahead;
if (c != 0 &&
!_isWhitespace(c) &&
c != 0x28 &&
c != 0x3a &&
c != 0x5b &&
c != 0x3d) {
_emit(lexer, BitBakeExternalToken.concat);
return true;
}
}
var advancedOnce = false;
if (_valid(validSymbols, BitBakeExternalToken.escapeInterpolation) &&
state.delimiters.isNotEmpty &&
(lexer.lookahead == 0x7b || lexer.lookahead == 0x7d) &&
!errorRecoveryMode) {
final delimiter = state.delimiters.last;
if (_isFormat(delimiter)) {
lexer.markEnd();
final isLeftBrace = lexer.lookahead == 0x7b;
lexer.advance(skip: false);
advancedOnce = true;
if ((lexer.lookahead == 0x7b && isLeftBrace) ||
(lexer.lookahead == 0x7d && !isLeftBrace)) {
lexer.advance(skip: false);
lexer.markEnd();
_emit(lexer, BitBakeExternalToken.escapeInterpolation);
return true;
}
return false;
}
}
if (_valid(validSymbols, BitBakeExternalToken.stringContent) &&
state.delimiters.isNotEmpty &&
!errorRecoveryMode) {
final delimiter = state.delimiters.last;
final endCharacter = _endCharacter(delimiter);
var hasContent = advancedOnce;
while (lexer.lookahead != 0) {
if ((advancedOnce ||
lexer.lookahead == 0x7b ||
lexer.lookahead == 0x7d) &&
_isFormat(delimiter)) {
lexer.markEnd();
_emit(lexer, BitBakeExternalToken.stringContent);
return hasContent;
}
if (lexer.lookahead == 0x5c) {
if (_isRaw(delimiter)) {
lexer.advance(skip: false);
if (lexer.lookahead == endCharacter || lexer.lookahead == 0x5c) {
lexer.advance(skip: false);
}
if (lexer.lookahead == 0x0d) {
lexer.advance(skip: false);
if (lexer.lookahead == 0x0a) lexer.advance(skip: false);
} else if (lexer.lookahead == 0x0a) {
lexer.advance(skip: false);
}
continue;
}
if (_isBytes(delimiter)) {
lexer.markEnd();
lexer.advance(skip: false);
if (lexer.lookahead == 0x4e ||
lexer.lookahead == 0x75 ||
lexer.lookahead == 0x55) {
lexer.advance(skip: false);
} else {
_emit(lexer, BitBakeExternalToken.stringContent);
return hasContent;
}
} else {
lexer.markEnd();
_emit(lexer, BitBakeExternalToken.stringContent);
return hasContent;
}
} else if (lexer.lookahead == endCharacter) {
if (_isTriple(delimiter)) {
lexer.markEnd();
lexer.advance(skip: false);
if (lexer.lookahead == endCharacter) {
lexer.advance(skip: false);
if (lexer.lookahead == endCharacter) {
if (hasContent) {
_emit(lexer, BitBakeExternalToken.stringContent);
} else {
lexer.advance(skip: false);
lexer.markEnd();
state.delimiters.removeLast();
_emit(lexer, BitBakeExternalToken.stringEnd);
state.insideFString = false;
}
return true;
}
lexer.markEnd();
_emit(lexer, BitBakeExternalToken.stringContent);
return true;
}
lexer.markEnd();
_emit(lexer, BitBakeExternalToken.stringContent);
return true;
}
if (hasContent) {
_emit(lexer, BitBakeExternalToken.stringContent);
} else {
lexer.advance(skip: false);
state.delimiters.removeLast();
_emit(lexer, BitBakeExternalToken.stringEnd);
state.insideFString = false;
}
lexer.markEnd();
return true;
} else if (lexer.lookahead == 0x0a &&
hasContent &&
!_isTriple(delimiter)) {
return false;
}
lexer.advance(skip: false);
hasContent = true;
}
}
lexer.markEnd();
var foundEndOfLine = false;
var indentLength = 0;
var firstCommentIndentLength = -1;
var scanningIndent = true;
while (scanningIndent) {
switch (lexer.lookahead) {
case 0x0a:
foundEndOfLine = true;
indentLength = 0;
lexer.advance(skip: true);
case 0x20:
indentLength++;
lexer.advance(skip: true);
case 0x0d || 0x0c:
indentLength = 0;
lexer.advance(skip: true);
case 0x09:
indentLength += 8;
lexer.advance(skip: true);
case 0x23:
if (!foundEndOfLine) return false;
if (firstCommentIndentLength == -1) {
firstCommentIndentLength = indentLength;
}
while (lexer.lookahead != 0 && lexer.lookahead != 0x0a) {
lexer.advance(skip: true);
}
lexer.advance(skip: true);
indentLength = 0;
case 0x5c:
if (!_valid(validSymbols, BitBakeExternalToken.stringContent)) {
scanningIndent = false;
continue;
}
lexer.advance(skip: true);
if (lexer.lookahead == 0x0d) lexer.advance(skip: true);
if (lexer.lookahead == 0x0a || lexer.isEof) {
lexer.advance(skip: true);
} else {
return false;
}
case 0:
if (lexer.isEof) {
indentLength = 0;
foundEndOfLine = true;
}
scanningIndent = false;
default:
scanningIndent = false;
}
}
if (foundEndOfLine) {
final currentIndentLength = state.indents.last;
if (_valid(validSymbols, BitBakeExternalToken.indent) &&
indentLength > currentIndentLength) {
state.indents.add(indentLength & 0xffff);
_emit(lexer, BitBakeExternalToken.indent);
return true;
}
final nextTokenIsStringStart =
lexer.lookahead == 0x22 ||
lexer.lookahead == 0x27 ||
lexer.lookahead == 0x60;
if ((_valid(validSymbols, BitBakeExternalToken.dedent) ||
(!_valid(validSymbols, BitBakeExternalToken.newline) &&
!(_valid(validSymbols, BitBakeExternalToken.stringStart) &&
nextTokenIsStringStart) &&
!withinBrackets)) &&
indentLength < currentIndentLength &&
!state.insideFString &&
firstCommentIndentLength < currentIndentLength) {
state.indents.removeLast();
_emit(lexer, BitBakeExternalToken.dedent);
return true;
}
if (_valid(validSymbols, BitBakeExternalToken.newline) &&
!errorRecoveryMode) {
_emit(lexer, BitBakeExternalToken.newline);
return true;
}
}
if (firstCommentIndentLength == -1 &&
_valid(validSymbols, BitBakeExternalToken.stringStart)) {
var delimiter = 0;
var hasFlags = false;
var scanningFlags = true;
while (scanningFlags && lexer.lookahead != 0) {
switch (lexer.lookahead) {
case 0x66 || 0x46:
delimiter |= _format;
case 0x72 || 0x52:
delimiter |= _raw;
case 0x62 || 0x42:
delimiter |= _bytes;
case 0x75 || 0x55:
break;
default:
scanningFlags = false;
continue;
}
hasFlags = true;
lexer.advance(skip: false);
}
switch (lexer.lookahead) {
case 0x60:
delimiter |= _backQuote;
lexer.advance(skip: false);
lexer.markEnd();
case 0x27:
delimiter |= _singleQuote;
lexer.advance(skip: false);
lexer.markEnd();
if (lexer.lookahead == 0x27) {
lexer.advance(skip: false);
if (lexer.lookahead == 0x27) {
lexer.advance(skip: false);
lexer.markEnd();
delimiter |= _triple;
}
}
case 0x22:
delimiter |= _doubleQuote;
lexer.advance(skip: false);
lexer.markEnd();
if (lexer.lookahead == 0x22) {
lexer.advance(skip: false);
if (lexer.lookahead == 0x22) {
lexer.advance(skip: false);
lexer.markEnd();
delimiter |= _triple;
}
}
}
if (_endCharacter(delimiter) != 0) {
state.delimiters.add(delimiter);
_emit(lexer, BitBakeExternalToken.stringStart);
state.insideFString = _isFormat(delimiter);
return true;
}
if (hasFlags) return false;
}
if (_valid(validSymbols, BitBakeExternalToken.shellContent) &&
!errorRecoveryMode) {
while (_isWhitespace(lexer.lookahead)) {
lexer.advance(skip: true);
if (lexer.lookahead == 0x0a) {
lexer.advance(skip: true);
break;
}
}
var advanceOnce = false;
var braceDepth = 0;
while (!lexer.isEof && lexer.lookahead != 0x0a) {
switch (lexer.lookahead) {
case 0x24: // $
lexer.markEnd();
lexer.advance(skip: false);
if (lexer.lookahead == 0x7b) {
lexer.advance(skip: false);
braceDepth = (braceDepth + 1) & 0xff;
if (lexer.lookahead == 0x40) {
lexer.advance(skip: false);
_emit(lexer, BitBakeExternalToken.shellContent);
return advanceOnce;
}
}
advanceOnce = true;
case 0x7b: // {
lexer.advance(skip: false);
braceDepth = (braceDepth + 1) & 0xff;
case 0x7d: // }
lexer.advance(skip: false);
braceDepth = (braceDepth - 1) & 0xff;
case 0x0d || 0x09 || 0x0c || 0x0b || 0x20:
lexer.advance(skip: false);
default:
lexer.advance(skip: false);
advanceOnce = true;
}
}
lexer.markEnd();
_emit(lexer, BitBakeExternalToken.shellContent);
return advanceOnce && braceDepth == 0;
}
return false;
}