in lib/src/scanner.dart [1263:1444]
Token _scanFlowScalar({bool singleQuote = false}) {
var start = _scanner.state;
var buffer = StringBuffer();
// Eat the left quote.
_scanner.readChar();
while (true) {
// Check that there are no document indicators at the beginning of the
// line.
if (_isDocumentIndicator) {
_scanner.error('Unexpected document indicator.');
}
if (_scanner.isDone) {
throw YamlException('Unexpected end of file.', _scanner.emptySpan);
}
var leadingBlanks = false;
while (!_isBlankOrEnd) {
var char = _scanner.peekChar();
if (singleQuote &&
char == SINGLE_QUOTE &&
_scanner.peekChar(1) == SINGLE_QUOTE) {
// An escaped single quote.
_scanner.readChar();
_scanner.readChar();
buffer.writeCharCode(SINGLE_QUOTE);
} else if (char == (singleQuote ? SINGLE_QUOTE : DOUBLE_QUOTE)) {
// The closing quote.
break;
} else if (!singleQuote && char == BACKSLASH && _isBreakAt(1)) {
// An escaped newline.
_scanner.readChar();
_skipLine();
leadingBlanks = true;
break;
} else if (!singleQuote && char == BACKSLASH) {
var escapeStart = _scanner.state;
// An escape sequence.
int? codeLength;
switch (_scanner.peekChar(1)) {
case NUMBER_0:
buffer.writeCharCode(NULL);
break;
case LETTER_A:
buffer.writeCharCode(BELL);
break;
case LETTER_B:
buffer.writeCharCode(BACKSPACE);
break;
case LETTER_T:
case TAB:
buffer.writeCharCode(TAB);
break;
case LETTER_N:
buffer.writeCharCode(LF);
break;
case LETTER_V:
buffer.writeCharCode(VERTICAL_TAB);
break;
case LETTER_F:
buffer.writeCharCode(FORM_FEED);
break;
case LETTER_R:
buffer.writeCharCode(CR);
break;
case LETTER_E:
buffer.writeCharCode(ESCAPE);
break;
case SP:
case DOUBLE_QUOTE:
case SLASH:
case BACKSLASH:
// libyaml doesn't support an escaped forward slash, but it was
// added in YAML 1.2. See section 5.7:
// http://yaml.org/spec/1.2/spec.html#id2776092
buffer.writeCharCode(_scanner.peekChar(1)!);
break;
case LETTER_CAP_N:
buffer.writeCharCode(NEL);
break;
case UNDERSCORE:
buffer.writeCharCode(NBSP);
break;
case LETTER_CAP_L:
buffer.writeCharCode(LINE_SEPARATOR);
break;
case LETTER_CAP_P:
buffer.writeCharCode(PARAGRAPH_SEPARATOR);
break;
case LETTER_X:
codeLength = 2;
break;
case LETTER_U:
codeLength = 4;
break;
case LETTER_CAP_U:
codeLength = 8;
break;
default:
throw YamlException(
'Unknown escape character.', _scanner.spanFrom(escapeStart));
}
_scanner.readChar();
_scanner.readChar();
if (codeLength != null) {
var value = 0;
for (var i = 0; i < codeLength; i++) {
if (!_isHex) {
_scanner.readChar();
throw YamlException(
'Expected $codeLength-digit hexidecimal number.',
_scanner.spanFrom(escapeStart));
}
value = (value << 4) + _asHex(_scanner.readChar());
}
// Check the value and write the character.
if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
throw YamlException('Invalid Unicode character escape code.',
_scanner.spanFrom(escapeStart));
}
buffer.writeCharCode(value);
}
} else {
buffer.writeCharCode(_scanner.readChar());
}
}
// Check if we're at the end of a scalar.
if (_scanner.peekChar() == (singleQuote ? SINGLE_QUOTE : DOUBLE_QUOTE)) {
break;
}
var whitespace = StringBuffer();
var leadingBreak = '';
var trailingBreaks = StringBuffer();
while (_isBlank || _isBreak) {
if (_isBlank) {
// Consume a space or a tab.
if (!leadingBlanks) {
whitespace.writeCharCode(_scanner.readChar());
} else {
_scanner.readChar();
}
} else {
// Check if it's a first line break.
if (!leadingBlanks) {
whitespace.clear();
leadingBreak = _readLine();
leadingBlanks = true;
} else {
trailingBreaks.write(_readLine());
}
}
}
// Join the whitespace or fold line breaks.
if (leadingBlanks) {
if (leadingBreak.isNotEmpty && trailingBreaks.isEmpty) {
buffer.writeCharCode(SP);
} else {
buffer.write(trailingBreaks);
}
} else {
buffer.write(whitespace);
whitespace.clear();
}
}
// Eat the right quote.
_scanner.readChar();
return ScalarToken(_scanner.spanFrom(start), buffer.toString(),
singleQuote ? ScalarStyle.SINGLE_QUOTED : ScalarStyle.DOUBLE_QUOTED);
}