/**
* @file
* This file is about scanner.
*/
package yaml4cj.yaml
func parserFetchMoreTokens(parser: ParserT): Bool {
while (true) {
if (parser.tokensHead != parser.tokens.size) {
let headTokIdx = parser.simpleKeysByTok.get(parser.tokensParsed)
match (headTokIdx) {
case None => break
case Some(idx) =>
let (valid, ok) = simpleKeyIsValid(parser, parser.simpleKeys[idx])
if (!ok) {
return false
}
if (!valid) {
break
}
}
}
if (!parserFetchNextToken(parser)) {
return false
}
}
parser.tokenAvailable = true
true
}
func simpleKeyIsValid(parser: ParserT, simpleKey: SimpleKeyT): (Bool, Bool) {
if (!simpleKey.possible) {
return (false, true)
}
if (simpleKey.mark.line < parser.mark.line || simpleKey.mark.index + 1024 < parser.mark.index) {
if (simpleKey.required) {
return (false, parserSetScannerError(
parser,
"while scanning a simple key",
simpleKey.mark,
"could not find expected ':'"
))
}
simpleKey.possible = false
return (false, true)
}
(true, true)
}
func parserSetScannerError(parser: ParserT, context: String, contextMark: MarkT, problem: String): Bool {
parser.error = ErrorTypeT_SCANNER_ERROR
parser.context = context
parser.contextMark = contextMark
parser.problem = problem
parser.problemMark = parser.mark
false
}
func parserSetScannerTagError(
parser: ParserT,
directive: Bool,
contextMark: MarkT,
problem: String
): Bool {
let context = if (directive) {
"while parsing a %TAG directive"
} else {
"while parsing a tag"
}
parserSetScannerError(parser, context, contextMark, problem)
}
func parserFetchNextTokenResolve0(parser: ParserT): ?Bool {
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return false
}
}
if (!parser.streamStartProduced) {
return parserFetchStreamStart(parser)
}
if (!parserScanToNextToken(parser)) {
return false
}
if (!parserUnrollIndent(parser, parser.mark.column)) {
return false
}
if (parser.unread < 4) {
if (!parserUpdateBuffer(parser, 4)) {
return false
}
}
if (isZ(parser.buffer, parser.bufferPos)) {
return parserFetchStreamEnd(parser)
}
if (parser.mark.column == 0 && parser.buffer[parser.bufferPos] == 0x25) {
return parserFetchDirective(parser)
}
None
}
func parserFetchNextTokenResolve1(parser: ParserT): ?Bool {
let buf = parser.buffer
let pos = parser.bufferPos
if (parser.mark.column == 0 && buf[pos] == 0x2D && buf[pos + 1] == 0x2D && buf[pos + 2] == 0x2D && isBlankz(
buf,
pos + 3
)) {
return parserFetchDocumentIndicator(parser, TokenTypeT_DOCUMENT_START_TOKEN)
}
if (parser.mark.column == 0 && buf[pos] == 0x2E && buf[pos + 1] == 0x2E && buf[pos + 2] == 0x2E && isBlankz(
buf,
pos + 3
)) {
return parserFetchDocumentIndicator(parser, TokenTypeT_DOCUMENT_END_TOKEN)
}
if (buf[pos] == 0x5B) {
return parserFetchFlowCollectionStart(parser, TokenTypeT_FLOW_SEQUENCE_START_TOKEN)
}
None
}
func parserFetchNextTokenResolve2(parser: ParserT): ?Bool {
if (parser.buffer[parser.bufferPos] == 0x7B) {
return parserFetchFlowCollectionStart(parser, TokenTypeT_FLOW_MAPPING_START_TOKEN)
}
if (parser.buffer[parser.bufferPos] == 0x5D) {
return parserFetchFlowCollectionEnd(
parser,
TokenTypeT_FLOW_SEQUENCE_END_TOKEN
)
}
if (parser.buffer[parser.bufferPos] == 0x7D) {
return parserFetchFlowCollectionEnd(
parser,
TokenTypeT_FLOW_MAPPING_END_TOKEN
)
}
if (parser.buffer[parser.bufferPos] == 0x2C) {
return parserFetchFlowEntry(parser)
}
if (parser.buffer[parser.bufferPos] == 0x2D && isBlankz(parser.buffer, parser.bufferPos + 1)) {
return parserFetchBlockEntry(parser)
}
if (parser.buffer[parser.bufferPos] == 0x3F && (parser.flowLevel > 0 || isBlankz(
parser.buffer,
parser.bufferPos + 1
))) {
return parserFetchKey(parser)
}
if (parser.buffer[parser.bufferPos] == 0x3A && (parser.flowLevel > 0 || isBlankz(
parser.buffer,
parser.bufferPos + 1
))) {
return parserFetchValue(parser)
}
None
}
func parserFetchNextTokenResolve3(parser: ParserT): ?Bool {
if (parser.buffer[parser.bufferPos] == 0x2A) {
return parserFetchAnchor(parser, TokenTypeT_ALIAS_TOKEN)
}
if (parser.buffer[parser.bufferPos] == 0x26) {
return parserFetchAnchor(parser, TokenTypeT_ANCHOR_TOKEN)
}
if (parser.buffer[parser.bufferPos] == 0x21) {
return parserFetchTag(parser)
}
if (parser.buffer[parser.bufferPos] == 0x7C && parser.flowLevel == 0) {
return parserFetchBlockScalar(parser, true)
}
if (parser.buffer[parser.bufferPos] == 0x3E && parser.flowLevel == 0) {
return parserFetchBlockScalar(parser, false)
}
if (parser.buffer[parser.bufferPos] == 0x27) {
return parserFetchFlowScalar(parser, true)
}
if (parser.buffer[parser.bufferPos] == 0x22) {
return parserFetchFlowScalar(parser, false)
}
let bc = Rune(UInt32(parser.buffer[parser.bufferPos]))
if (!(isBlankz(parser.buffer, parser.bufferPos) || bc == r'-' || bc == r'?' || bc == r':' || bc == r',' || bc == r'[' ||
bc == r']' || bc == r'{' || bc == r'}' || bc == r'#' || bc == r'&' || bc == r'*' || bc == r'!' || bc == r'|' || bc == r'>' ||
bc == r'\'' || bc == r'"' || bc == r'%' || bc == r'@' || bc == r'`') || (bc == r'-' &&
!isBlank(parser.buffer, parser.bufferPos + 1)) || (parser.flowLevel == 0 && (bc == r'?' || bc == r':') &&
!isBlankz(parser.buffer, parser.bufferPos + 1))) {
return parserFetchPlainScalar(parser)
}
None
}
func parserFetchNextToken(parser: ParserT): Bool {
if (let Some(ok) <- parserFetchNextTokenResolve0(parser)) {
return ok
}
if (let Some(ok) <- parserFetchNextTokenResolve1(parser)) {
return ok
}
if (let Some(ok) <- parserFetchNextTokenResolve2(parser)) {
return ok
}
if (let Some(ok) <- parserFetchNextTokenResolve3(parser)) {
return ok
}
return parserSetScannerError(
parser,
"while scanning for the next token",
parser.mark,
"found character that cannot start any token"
)
}
func parserFetchStreamStart(parser: ParserT): Bool {
parser.indent = -1
parser.simpleKeys.add(SimpleKeyT())
parser.simpleKeysByTok = HashMap<Int64, Int64>()
parser.simpleKeyAllowed = true
parser.streamStartProduced = true
let token = TokenT()
token.typ = TokenTypeT_STREAM_START_TOKEN
token.startMark = parser.mark
token.endMark = parser.mark
token.encoding = parser.encoding
insertToken(parser, -1, token)
return true
}
func parserFetchPlainScalar(parser: ParserT): Bool {
if (!parserSaveSimpleKey(parser)) {
return false
}
parser.simpleKeyAllowed = false
let (token, ok) = parserScanPlainScalar(parser)
if (!ok) {
return false
}
insertToken(parser, -1, token)
return true
}
func parserScanToNextTokenResolve(parser: ParserT): ?Bool {
while (parser.buffer[parser.bufferPos] == 0x20 || ((parser.flowLevel > 0 || !parser.simpleKeyAllowed) &&
parser.buffer[parser.bufferPos] == 0x09)) {
skip(parser)
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return false
}
}
}
if (parser.buffer[parser.bufferPos] == 0x23) {
while (!isBreakz(parser.buffer, parser.bufferPos)) {
skip(parser)
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return false
}
}
}
}
None
}
func parserScanToNextTokenLoop(parser: ParserT): ?(Bool, Bool) {
if (parser.unread < 1 && !parserUpdateBuffer(parser, 1)) {
return (false, false)
}
if (parser.mark.column == 0) {
if (isBom(parser.buffer)) {
skip(parser)
}
}
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (false, false)
}
}
if (let Some(ok) <- parserScanToNextTokenResolve(parser)) {
return (ok, false)
}
if (isBreak(parser.buffer, parser.bufferPos)) {
if (parser.unread < 2) {
if (!parserUpdateBuffer(parser, 2)) {
return (false, false)
}
}
skipLine(parser)
if (parser.flowLevel == 0) {
parser.simpleKeyAllowed = true
}
return None
} else {
return (false, true)
}
}
func parserScanToNextToken(parser: ParserT): Bool {
while (true) {
if (let Some((ok, isBreak)) <- parserScanToNextTokenLoop(parser)) {
if (isBreak) {
break
}
return ok
}
}
return true
}
func skip(parser: ParserT) {
parser.mark.index++
parser.mark.column++
parser.unread--
parser.bufferPos += width(parser.buffer[parser.bufferPos])
}
func skipLine(parser: ParserT) {
if (isCRLF(parser.buffer, parser.bufferPos)) {
parser.mark.index += 2
parser.mark.column = 0
parser.mark.line++
parser.unread -= 2
parser.bufferPos += 2
} else if (isBreak(parser.buffer, parser.bufferPos)) {
parser.mark.index++
parser.mark.column = 0
parser.mark.line++
parser.unread--
parser.bufferPos += width(parser.buffer[parser.bufferPos])
}
}
func read(parser: ParserT): Array<UInt8> {
let w = width(parser.buffer[parser.bufferPos])
if (w == 0) {
throw Exception("invalid character sequence")
}
var s: Array<UInt8>
if (w == 1) {
s = [parser.buffer[parser.bufferPos]]
parser.bufferPos++
} else {
s = (parser.buffer[parser.bufferPos..(parser.bufferPos + w)]).toArray()
parser.bufferPos += w
}
parser.mark.index++
parser.mark.column++
parser.unread--
s
}
func readLine(parser: ParserT): Array<UInt8> {
let buf = parser.buffer
let pos = parser.bufferPos
var s: Array<UInt8>
if (buf[pos] == 0xD && buf[pos + 1] == 0xA) {
s = [0xA]
parser.bufferPos += 2
parser.mark.index++
parser.unread--
} else if (buf[pos] == 0xD || buf[pos] == 0xA) {
s = [0xA]
parser.bufferPos += 1
} else if (buf[pos] == 0xC2 && buf[pos + 1] == 0x85) {
s = [0xA]
parser.bufferPos += 2
} else if (buf[pos] == 0xE2 && buf[pos + 1] == 0x80 && (buf[pos + 2] == 0xA8 || buf[pos + 2] == 0xA9)) {
s = (buf[parser.bufferPos..(pos + 3)]).toArray()
parser.bufferPos += 3
} else {
return []
}
parser.mark.index++
parser.mark.column = 0
parser.mark.line++
parser.unread--
s
}
func parserUnrollIndent(parser: ParserT, column: Int64): Bool {
if (parser.flowLevel > 0) {
return true
}
while (parser.indent > column) {
let token = TokenT()
token.typ = TokenTypeT_BLOCK_END_TOKEN
token.startMark = parser.mark
token.endMark = parser.mark
insertToken(parser, -1, token)
parser.indent = parser.indents[parser.indents.size - 1]
parser.indents = parser.indents[0..(parser.indents.size - 1)]
}
true
}
func parserFetchStreamEnd(parser: ParserT): Bool {
if (parser.mark.column != 0) {
parser.mark.column = 0
parser.mark.line++
}
if (!parserUnrollIndent(parser, -1)) {
return false
}
if (!parserRemoveSimpleKey(parser)) {
return false
}
parser.simpleKeyAllowed = false
let token = TokenT()
token.typ = TokenTypeT_STREAM_END_TOKEN
token.startMark = parser.mark
token.endMark = parser.mark
insertToken(parser, -1, token)
true
}
func parserRemoveSimpleKey(parser: ParserT): Bool {
let i = parser.simpleKeys.size - 1
if (parser.simpleKeys[i].possible) {
if (parser.simpleKeys[i].required) {
return parserSetScannerError(
parser,
"while scanning a simple key",
parser.simpleKeys[i].mark,
"could not find expected ':'"
)
}
parser.simpleKeys[i].possible = false
parser.simpleKeysByTok.remove(parser.simpleKeys[i].tokenNumber)
}
true
}
func parserFetchDirective(parser: ParserT): Bool {
// Reset the indentation level.
if (!parserUnrollIndent(parser, -1)) {
return false
}
// Reset simple keys.
if (!parserRemoveSimpleKey(parser)) {
return false
}
parser.simpleKeyAllowed = false
// Create the YAML-DIRECTIVE or TAG-DIRECTIVE token.
let (token, ok) = parserScanDirective(parser)
if (!ok) {
return false
}
// Append the token to the queue.
insertToken(parser, -1, token)
return true
}
func parserScanDirective(parser: ParserT): (TokenT, Bool) {
let token = TokenT()
let startMark = parser.mark
skip(parser)
let (name, nok) = parserScanDirectiveName(parser, startMark)
if (!nok) {
return (token, false)
}
if ("YAML" == String.fromUtf8(name)) {
let (major, minor, ok) = parserScanVersionDirectiveValue(parser, startMark)
if (!ok) {
return (token, false)
}
token.typ = TokenTypeT_VERSION_DIRECTIVE_TOKEN
token.startMark = startMark
token.endMark = parser.mark
token.major = major
token.minor = minor
} else if ("TAG" == String.fromUtf8(name)) {
let (handle, prefix, ok) = parserScanTagDirectiveValue(parser, startMark)
if (!ok) {
return (token, false)
}
token.typ = TokenTypeT_TAG_DIRECTIVE_TOKEN
token.startMark = startMark
token.endMark = parser.mark
token.value = handle
token.prefix = prefix
} else {
parserSetScannerError(
parser,
"while scanning a directive",
startMark,
"found unknown directive name"
)
return (token, false)
}
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (token, false)
}
}
while (isBlank(parser.buffer, parser.bufferPos)) {
skip(parser)
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (token, false)
}
}
}
if (parser.buffer[parser.bufferPos] == 0x23) {
while (!isBreakz(parser.buffer, parser.bufferPos)) {
skip(parser)
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (token, false)
}
}
}
}
if (!isBreakz(parser.buffer, parser.bufferPos)) {
parserSetScannerError(
parser,
"while scanning a directive",
startMark,
"did not find expected comment or line break"
)
return (token, false)
}
if (isBreak(parser.buffer, parser.bufferPos)) {
if (parser.unread < 2) {
if (!parserUpdateBuffer(parser, 2)) {
return (token, false)
}
}
skipLine(parser)
}
(token, true)
}
func parserScanDirectiveName(parser: ParserT, startMark: MarkT): (Array<UInt8>, Bool) {
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return ([], false)
}
}
var s = ArrayList<UInt8>()
while (isAlpha(parser.buffer, parser.bufferPos)) {
s.add(all: read(parser))
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return ([], false)
}
}
}
if (s.size == 0) {
parserSetScannerError(
parser,
"while scanning a directive",
startMark,
"could not find expected directive name"
)
return ([], false)
}
if (!isBlankz(parser.buffer, parser.bufferPos)) {
parserSetScannerError(
parser,
"while scanning a directive",
startMark,
"found unexpected non-alphabetical character"
)
return ([], false)
}
(s.toArray(), true)
}
func parserScanVersionDirectiveValue(parser: ParserT, startMark: MarkT): (Int8, Int8, Bool) {
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (0, 0, false)
}
}
while (isBlank(parser.buffer, parser.bufferPos)) {
skip(parser)
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (0, 0, false)
}
}
}
let (major, mok) = parserScanVersionDirectiveNumber(parser, startMark)
if (!mok) {
return (major, 0, false)
}
if (parser.buffer[parser.bufferPos] != 0x2E) {
return (major, 0, parserSetScannerError(
parser,
"while scanning a %YAML directive",
startMark,
"did not find expected digit or '.' character"
))
}
skip(parser)
let (minor, nok) = parserScanVersionDirectiveNumber(parser, startMark)
if (!nok) {
return (major, minor, false)
}
(major, minor, true)
}
let maxNumberLength: Int8 = 2
func parserScanVersionDirectiveNumber(parser: ParserT, startMark: MarkT): (Int8, Bool) {
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (0, false)
}
}
var value: Int8 = 0
var length: Int8 = 0
while (isDigit(parser.buffer, parser.bufferPos)) {
length++
if (length > maxNumberLength) {
return (0, parserSetScannerError(
parser,
"while scanning a %YAML directive",
startMark,
"found extremely long version number"
))
}
value = value * 10 + Int8(asDigit(parser.buffer, parser.bufferPos))
skip(parser)
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (0, false)
}
}
}
(value, true)
}
func parserScanTagDirectiveValue(parser: ParserT, startMark: MarkT): (Array<UInt8>, Array<UInt8>, Bool) {
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return ([], [], false)
}
}
while (isBlank(parser.buffer, parser.bufferPos)) {
skip(parser)
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return ([], [], false)
}
}
}
let (handle_value, hok) = parserScanTagHandle(parser, true, startMark)
if (!hok) {
return ([], [], false)
}
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return ([], [], false)
}
}
if (!isBlank(parser.buffer, parser.bufferPos)) {
parserSetScannerError(
parser,
"while scanning a %TAG directive",
startMark,
"did not find expected whitespace"
)
return ([], [], false)
}
while (isBlank(parser.buffer, parser.bufferPos)) {
skip(parser)
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return ([], [], false)
}
}
}
let (prefix_value, pok) = parserScanTagURI(parser, true, None, startMark)
if (!pok) {
return ([], [], false)
}
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return ([], [], false)
}
}
if (!isBlankz(parser.buffer, parser.bufferPos)) {
parserSetScannerError(
parser,
"while scanning a %TAG directive",
startMark,
"did not find expected whitespace or line break"
)
return ([], [], false)
}
(handle_value, prefix_value, true)
}
func parserScanTagHandle(parser: ParserT, directive: Bool, startMark: MarkT): (Array<UInt8>, Bool) {
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return ([], false)
}
}
if (parser.buffer[parser.bufferPos] != 0x21) {
parserSetScannerTagError(
parser,
directive,
startMark,
"did not find expected '!'"
)
return ([], false)
}
let s = ArrayList<UInt8>()
s.add(all: read(parser))
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return ([], false)
}
}
while (isAlpha(parser.buffer, parser.bufferPos)) {
s.add(all: read(parser))
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return ([], false)
}
}
}
if (parser.buffer[parser.bufferPos] == 0x21) {
s.add(all: read(parser))
} else {
// It's either the '!' tag or not really a tag handle. If it's a %TAG
// directive, it's an error. If it's a tag token, it must be a part of URI.
if (directive && b'!' == s[0]) {
parserSetScannerTagError(
parser,
directive,
startMark,
"did not find expected '!'"
)
return ([], false)
}
}
(s.toArray(), true)
}
func checkBufferChar(buffer: ArrayList<UInt8>, bufferPos: Int64): Bool {
let bc = Rune(UInt32(buffer[bufferPos]))
bc == r';' || bc == r'/' || bc == r'?' || bc == r':' || bc == r'@' || bc == r'&' || bc == r'=' || bc == r'+' || bc == r'$' ||
bc == r',' || bc == r'.' || bc == r'!' || bc == r'~' || bc == r'*' || bc == r'\'' || bc == r'(' || bc == r')' || bc ==
r'[' || bc == r']' || bc == r'%'
}
func parserScanTagURI(parser: ParserT, directive: Bool, head: ?Array<UInt8>, startMark: MarkT): (Array<UInt8>, Bool) {
let s = ArrayList<UInt8>()
var hasTag = false
match (head) {
case Some(h) =>
if (h.size > 0) {
hasTag = true
}
if (h.size > 1) {
s.add(all: h[1..h.size])
}
case _ => ()
}
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return ([], false)
}
}
while (isAlpha(parser.buffer, parser.bufferPos) || checkBufferChar(parser.buffer, parser.bufferPos)) {
if (parser.buffer[parser.bufferPos] == 0x25) {
if (!parserScanURIEscapes(parser, directive, startMark, s)) {
return ([], false)
}
} else {
s.add(all: read(parser))
}
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return ([], false)
}
}
hasTag = true
}
if (!hasTag) {
parserSetScannerTagError(
parser,
directive,
startMark,
"did not find expected tag URI"
)
return ([], false)
}
(s.toArray(), true)
}
func parserScanURIEscapes(parser: ParserT, directive: Bool, startMark: MarkT, s: ArrayList<UInt8>): Bool {
var w = 1024
while (w > 0) {
if (parser.unread < 3) {
if (!parserUpdateBuffer(parser, 3)) {
return false
}
}
if (!(parser.buffer[parser.bufferPos] == 0x25 && isHex(parser.buffer, parser.bufferPos + 1) && isHex(
parser.buffer, parser.bufferPos + 2))) {
return parserSetScannerTagError(
parser,
directive,
startMark,
"did not find URI escaped octet"
)
}
let octet = UInt8((asHex(parser.buffer, parser.bufferPos + 1) << 4) + asHex(
parser.buffer,
parser.bufferPos + 2
))
if (w == 1024) {
w = width(octet)
if (w == 0) {
return parserSetScannerTagError(
parser,
directive,
startMark,
"found an incorrect leading UTF-8 octet"
)
}
} else {
if ((octet & 0xC0) != 0x80) {
return parserSetScannerTagError(
parser,
directive,
startMark,
"found an incorrect trailing UTF-8 octet"
)
}
}
s.add(octet)
skip(parser)
skip(parser)
skip(parser)
w--
}
true
}
func parserFetchDocumentIndicator(parser: ParserT, typ: TokenTypeT): Bool {
if (!parserUnrollIndent(parser, -1)) {
return false
}
if (!parserRemoveSimpleKey(parser)) {
return false
}
parser.simpleKeyAllowed = false
let startMark = parser.mark
skip(parser)
skip(parser)
skip(parser)
let token = TokenT()
token.typ = typ
token.startMark = startMark
token.endMark = parser.mark
insertToken(parser, -1, token)
true
}
func parserFetchFlowCollectionStart(parser: ParserT, typ: TokenTypeT): Bool {
if (!parserSaveSimpleKey(parser)) {
return false
}
if (!parserIncreaseFlowLevel(parser)) {
return false
}
parser.simpleKeyAllowed = true
let startMark = parser.mark
skip(parser)
let token = TokenT()
token.typ = typ
token.startMark = startMark
token.endMark = parser.mark
insertToken(parser, -1, token)
true
}
func parserSaveSimpleKey(parser: ParserT): Bool {
let required = parser.flowLevel == 0 && parser.indent == parser.mark.column
if (parser.simpleKeyAllowed) {
let simpleKey = SimpleKeyT()
simpleKey.possible = true
simpleKey.required = required
simpleKey.tokenNumber = parser.tokensParsed + (parser.tokens.size - parser.tokensHead)
simpleKey.mark = parser.mark.clone()
if (!parserRemoveSimpleKey(parser)) {
return false
}
parser.simpleKeys[parser.simpleKeys.size - 1] = simpleKey
parser.simpleKeysByTok[simpleKey.tokenNumber] = parser.simpleKeys.size - 1
}
true
}
let max_flowLevel = 10000
func parserIncreaseFlowLevel(parser: ParserT): Bool {
let simpleKey = SimpleKeyT()
simpleKey.possible = false
simpleKey.required = false
simpleKey.tokenNumber = parser.tokensParsed + (parser.tokens.size - parser.tokensHead)
simpleKey.mark = parser.mark
parser.simpleKeys.add(simpleKey)
parser.flowLevel++
if (parser.flowLevel > max_flowLevel) {
return parserSetScannerError(
parser,
"while increasing flow level",
parser.simpleKeys[parser.simpleKeys.size - 1].mark,
"exceeded max depth of ${max_flowLevel}"
)
}
true
}
func parserFetchFlowCollectionEnd(parser: ParserT, typ: TokenTypeT): Bool {
if (!parserRemoveSimpleKey(parser)) {
return false
}
if (!parserDecreaseFlowLevel(parser)) {
return false
}
parser.simpleKeyAllowed = false
let startMark = parser.mark
skip(parser)
let token = TokenT()
token.typ = typ
token.startMark = startMark
token.endMark = parser.mark
insertToken(parser, -1, token)
true
}
func parserDecreaseFlowLevel(parser: ParserT): Bool {
if (parser.flowLevel > 0) {
parser.flowLevel--
let last = parser.simpleKeys.size - 1
parser.simpleKeysByTok.remove(parser.simpleKeys[last].tokenNumber)
parser.simpleKeys = parser.simpleKeys[0..last]
}
true
}
func parserFetchFlowEntry(parser: ParserT): Bool {
if (!parserRemoveSimpleKey(parser)) {
return false
}
parser.simpleKeyAllowed = true
let startMark = parser.mark
skip(parser)
let token = TokenT()
token.typ = TokenTypeT_FLOW_ENTRY_TOKEN
token.startMark = startMark
token.endMark = parser.mark
insertToken(parser, -1, token)
true
}
func parserFetchBlockEntry(parser: ParserT): Bool {
if (parser.flowLevel == 0) {
if (!parser.simpleKeyAllowed) {
return parserSetScannerError(
parser,
"",
parser.mark,
"block sequence entries are not allowed in this context"
)
}
if (!parserRollIndent(parser, parser.mark.column, -1, TokenTypeT_BLOCK_SEQUENCE_START_TOKEN, parser.mark)) {
return false
}
}
if (!parserRemoveSimpleKey(parser)) {
return false
}
parser.simpleKeyAllowed = true
let startMark = parser.mark
skip(parser)
let token = TokenT()
token.typ = TokenTypeT_BLOCK_ENTRY_TOKEN
token.startMark = startMark
token.endMark = parser.mark
insertToken(parser, -1, token)
true
}
let max_indents = 10000
func parserRollIndent(
parser: ParserT,
column: Int64,
number: Int64,
typ: TokenTypeT,
mark: MarkT
): Bool {
if (parser.flowLevel > 0) {
return true
}
if (parser.indent < column) {
parser.indents.add(parser.indent)
parser.indent = column
if (parser.indents.size > max_indents) {
return parserSetScannerError(
parser,
"while increasing indent level",
parser.simpleKeys[parser.simpleKeys.size - 1].mark,
"exceeded max depth of ${max_indents}"
)
}
let token = TokenT()
token.typ = typ
token.startMark = mark
token.endMark = mark
let num = if (number > -1) {
number - parser.tokensParsed
} else {
number
}
insertToken(parser, num, token)
}
true
}
func parserFetchKey(parser: ParserT): Bool {
if (parser.flowLevel == 0) {
if (!parser.simpleKeyAllowed) {
return parserSetScannerError(
parser,
"",
parser.mark,
"mapping keys are not allowed in this context"
)
}
if (!parserRollIndent(parser, parser.mark.column, -1, TokenTypeT_BLOCK_MAPPING_START_TOKEN, parser.mark)) {
return false
}
}
if (!parserRemoveSimpleKey(parser)) {
return false
}
parser.simpleKeyAllowed = parser.flowLevel == 0
let startMark = parser.mark
skip(parser)
let token = TokenT()
token.typ = TokenTypeT_KEY_TOKEN
token.startMark = startMark
token.endMark = parser.mark
insertToken(parser, -1, token)
true
}
func parserFetchValue(parser: ParserT): Bool {
let simpleKey = parser.simpleKeys[parser.simpleKeys.size - 1]
let (valid, ok) = simpleKeyIsValid(parser, simpleKey)
if (!ok) {
return false
} else if (valid) {
let token = TokenT()
token.typ = TokenTypeT_KEY_TOKEN
token.startMark = simpleKey.mark
token.endMark = simpleKey.mark
insertToken(parser, simpleKey.tokenNumber - parser.tokensParsed, token)
if (!parserRollIndent(
parser,
simpleKey.mark.column,
simpleKey.tokenNumber,
TokenTypeT_BLOCK_MAPPING_START_TOKEN,
simpleKey.mark
)) {
return false
}
simpleKey.possible = false
parser.simpleKeysByTok.remove(simpleKey.tokenNumber)
parser.simpleKeyAllowed = false
} else {
if (parser.flowLevel == 0) {
if (!parser.simpleKeyAllowed) {
return parserSetScannerError(
parser,
"",
parser.mark,
"mapping values are not allowed in this context"
)
}
if (!parserRollIndent(
parser,
parser.mark.column,
-1,
TokenTypeT_BLOCK_MAPPING_START_TOKEN,
parser.mark
)) {
return false
}
}
parser.simpleKeyAllowed = parser.flowLevel == 0
}
let startMark = parser.mark
skip(parser)
let token = TokenT()
token.typ = TokenTypeT_VALUE_TOKEN
token.startMark = startMark
token.endMark = parser.mark
insertToken(parser, -1, token)
true
}
func parserScanAnchor(parser: ParserT, typ: TokenTypeT): (TokenT, Bool) {
let startMark = parser.mark
skip(parser)
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (TokenT(), false)
}
}
let s = ArrayList<UInt8>()
while (isAlpha(parser.buffer, parser.bufferPos)) {
s.add(all: read(parser))
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (TokenT(), false)
}
}
}
let endMark = parser.mark
let bc = Rune(UInt32(parser.buffer[parser.bufferPos]))
if (s.size == 0 ||
!(isBlankz(parser.buffer, parser.bufferPos) || bc == r'?' || bc == r':' || bc == r',' || bc == r']' || bc == r'}' ||
bc == r'%' || bc == r'@' || bc == r'`')) {
let context = if (typ == TokenTypeT_ANCHOR_TOKEN) {
"while scanning an anchor"
} else {
"while scanning an alias"
}
parserSetScannerError(
parser,
context,
startMark,
"did not find expected alphabetic or numeric character"
)
return (TokenT(), false)
}
let token = TokenT()
token.typ = typ
token.startMark = startMark
token.endMark = endMark
token.value = s.toArray()
(token, true)
}
func parserFetchAnchor(parser: ParserT, typ: TokenTypeT): Bool {
if (!parserSaveSimpleKey(parser)) {
return false
}
parser.simpleKeyAllowed = false
var (token, ok) = parserScanAnchor(parser, typ)
if (!ok) {
return false
}
insertToken(parser, -1, token)
true
}
func parserScanTag(parser: ParserT): (TokenT, Bool) {
let startMark = parser.mark
if (parser.unread < 2) {
if (!parserUpdateBuffer(parser, 2)) {
return (TokenT(), false)
}
}
var han: Array<UInt8> = []
var suf: Array<UInt8> = []
if (parser.buffer[parser.bufferPos + 1] == 0x3C) {
skip(parser)
skip(parser)
let (suffix, ok) = parserScanTagURI(parser, false, None, startMark)
suf = suffix
if (!ok) {
return (TokenT(), false)
}
if (parser.buffer[parser.bufferPos] != 0x3E) {
parserSetScannerError(
parser,
"while scanning a tag",
startMark,
"did not find the expected '>'"
)
return (TokenT(), false)
}
skip(parser)
} else {
let (handle, ok) = parserScanTagHandle(parser, false, startMark)
han = handle
if (!ok) {
return (TokenT(), false)
}
if (handle[0] == 0x21 && handle.size > 1 && handle[handle.size - 1] == 0x21) {
let (suffix, sok) = parserScanTagURI(parser, false, None, startMark)
suf = suffix
if (!sok) {
return (TokenT(), false)
}
} else {
let (suffix, sok) = parserScanTagURI(parser, false, handle, startMark)
suf = suffix
if (!sok) {
return (TokenT(), false)
}
han = [0x21]
if (suf.size == 0) {
let (nhandle, nsuffix) = (suf, han)
han = nhandle
suf = nsuffix
}
}
}
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (TokenT(), false)
}
}
if (!isBlankz(parser.buffer, parser.bufferPos)) {
parserSetScannerError(
parser,
"while scanning a tag",
startMark,
"did not find expected whitespace or line break"
)
return (TokenT(), false)
}
let token = TokenT()
token.typ = TokenTypeT_TAG_TOKEN
token.startMark = startMark
token.endMark = parser.mark
token.value = han
token.suffix = suf
(token, true)
}
func parserFetchTag(parser: ParserT): Bool {
if (!parserSaveSimpleKey(parser)) {
return false
}
parser.simpleKeyAllowed = false
let (token, ok) = parserScanTag(parser)
if (!ok) {
return false
}
insertToken(parser, -1, token)
true
}
func parserScanBlockScalarResloveAddOrSub(
parser: ParserT,
startMark: MarkT,
incrementBox: Box<Int64>,
chompingBox: Box<Int64>
): (?TokenT, Bool) {
chompingBox.value = if (parser.buffer[parser.bufferPos] == 0x2B) {
1
} else {
-1
}
skip(parser)
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (TokenT(), false)
}
}
if (isDigit(parser.buffer, parser.bufferPos)) {
if (parser.buffer[parser.bufferPos] == 0x30) {
parserSetScannerError(
parser,
"while scanning a block scalar",
startMark,
"found an indentation indicator equal to 0"
)
return (TokenT(), false)
}
incrementBox.value = asDigit(parser.buffer, parser.bufferPos)
skip(parser)
}
(None, false)
}
func parserScanBlockScalarResolveDigit(
parser: ParserT,
startMark: MarkT,
incrementBox: Box<Int64>,
chompingBox: Box<Int64>
): (?TokenT, Bool) {
if (parser.buffer[parser.bufferPos] == 0x30) {
parserSetScannerError(
parser,
"while scanning a block scalar",
startMark,
"found an indentation indicator equal to 0"
)
return (TokenT(), false)
}
incrementBox.value = asDigit(parser.buffer, parser.bufferPos)
skip(parser)
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (TokenT(), false)
}
}
if (parser.buffer[parser.bufferPos] == 0x2B || parser.buffer[parser.bufferPos] == 0x2D) {
chompingBox.value = if (parser.buffer[parser.bufferPos] == 0x2B) {
1
} else {
-1
}
skip(parser)
}
(None, false)
}
func parserScanBlockScalarReslove0(parser: ParserT, startMark: MarkT): (?TokenT, Bool) {
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (TokenT(), false)
}
}
while (isBlank(parser.buffer, parser.bufferPos)) {
skip(parser)
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (TokenT(), false)
}
}
}
if (parser.buffer[parser.bufferPos] == 0x23) {
while (!isBreakz(parser.buffer, parser.bufferPos)) {
skip(parser)
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (TokenT(), false)
}
}
}
}
if (!isBreakz(parser.buffer, parser.bufferPos)) {
parserSetScannerError(
parser,
"while scanning a block scalar",
startMark,
"did not find expected comment or line break"
)
return (TokenT(), false)
}
if (isBreak(parser.buffer, parser.bufferPos)) {
if (parser.unread < 2) {
if (!parserUpdateBuffer(parser, 2)) {
return (TokenT(), false)
}
}
skipLine(parser)
}
(None, false)
}
func parserScanBlockScalarReslove1(
parser: ParserT,
literal: Bool,
chomping: Int64,
indentBox: Box<Int64>,
s: ArrayList<UInt8>,
trailingBreaksBox: Box<Array<UInt8>>,
startMark: MarkT,
endMarkBox: Box<MarkT>
): (?TokenT, Bool) {
var leadingBreak: ArrayList<UInt8> = ArrayList<UInt8>()
var leadingBlank = false
var trailingBlank = false
while (parser.mark.column == indentBox.value && !isZ(parser.buffer, parser.bufferPos)) {
trailingBlank = isBlank(parser.buffer, parser.bufferPos)
if (!literal && !leadingBlank && !trailingBlank && leadingBreak.size > 0 && leadingBreak[0] == 0xA) {
if (trailingBreaksBox.value.size == 0) {
s.add(0x20)
}
} else {
s.add(all: leadingBreak)
}
leadingBreak.clear()
s.add(all: trailingBreaksBox.value)
trailingBreaksBox.value = []
leadingBlank = isBlank(parser.buffer, parser.bufferPos)
while (!isBreakz(parser.buffer, parser.bufferPos)) {
s.add(all: read(parser))
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (TokenT(), false)
}
}
}
if (parser.unread < 2) {
if (!parserUpdateBuffer(parser, 2)) {
return (TokenT(), false)
}
}
leadingBreak.add(all: readLine(parser))
let (nTrailingBreaks, nEndMark, nTok) = parserScanBlockScalarBreaks(
parser,
indentBox,
startMark
)
trailingBreaksBox.value = nTrailingBreaks
endMarkBox.value = nEndMark
if (!nTok) {
return (TokenT(), false)
}
}
if (chomping != -1) {
s.add(all: leadingBreak)
}
if (chomping == 1) {
s.add(all: trailingBreaksBox.value)
}
(None, false)
}
func parserScanBlockScalarReslove2(
parser: ParserT,
startMark: MarkT,
increment: Box<Int64>,
chomping: Box<Int64>
): ?(TokenT, Bool) {
if (parser.buffer[parser.bufferPos] == 0x2B || parser.buffer[parser.bufferPos] == 0x2D) {
if (let (Some(t), ok) <- parserScanBlockScalarResloveAddOrSub(
parser,
startMark,
increment,
chomping
)) {
return (t, ok)
}
} else if (isDigit(parser.buffer, parser.bufferPos)) {
if (let (Some(t), ok) <- parserScanBlockScalarResolveDigit(
parser,
startMark,
increment,
chomping
)) {
return (t, ok)
}
}
if (let (Some(t), ok) <- parserScanBlockScalarReslove0(parser, startMark)) {
return (t, ok)
}
return None
}
func parserScanBlockScalarResloveIndent(parser: ParserT, increment: Box<Int64>): Int64 {
if (increment.value > 0) {
if (parser.indent >= 0) {
parser.indent + increment.value
} else {
increment.value
}
} else {
0
}
}
func parserScanBlockScalar(parser: ParserT, literal: Bool): (TokenT, Bool) {
let startMark = parser.mark
skip(parser)
// Scan the additional block scalar indicators.
if (parser.unread < 1 && !parserUpdateBuffer(parser, 1)) {
return (TokenT(), false)
}
let increment = Box<Int64>(0)
let chomping = Box<Int64>(0)
if (let Some((t, ok)) <- parserScanBlockScalarReslove2(parser, startMark, increment, chomping)) {
return (t, ok)
}
var endMark = parser.mark
var indent = Box<Int64>(parserScanBlockScalarResloveIndent(parser, increment))
let (ntrailingBreaks, nendMark, tok) = parserScanBlockScalarBreaks(
parser,
indent,
startMark
)
var trailingBreaks = ntrailingBreaks
endMark = nendMark
if (!tok || (parser.unread < 1 && !parserUpdateBuffer(parser, 1))) {
return (TokenT(), false)
}
let s = ArrayList<UInt8>()
let trailingBreaksBox = Box<Array<UInt8>>(trailingBreaks)
let endMarkBox = Box<MarkT>(endMark)
if (let (Some(t), ok) <- parserScanBlockScalarReslove1(
parser,
literal,
chomping.value,
indent,
s,
trailingBreaksBox,
startMark,
endMarkBox
)) {
return (t, ok)
}
trailingBreaks = trailingBreaksBox.value
endMark = endMarkBox.value
let token = TokenT()
token.typ = TokenTypeT_SCALAR_TOKEN
token.startMark = startMark
token.endMark = endMark
token.value = s.toArray()
token.style = ScalarStyleT_LITERAL_SCALAR_STYLE
if (!literal) {
token.style = ScalarStyleT_FOLDED_SCALAR_STYLE
}
(token, true)
}
func parserFetchBlockScalar(parser: ParserT, literal: Bool): Bool {
if (!parserRemoveSimpleKey(parser)) {
return false
}
parser.simpleKeyAllowed = true
let (token, ok) = parserScanBlockScalar(parser, literal)
if (!ok) {
return false
}
insertToken(parser, -1, token)
true
}
// 返回breaks、indent、endMark
func parserScanBlockScalarBreaks(
parser: ParserT,
indent: Box<Int64>,
startMark: MarkT
): (Array<UInt8>, MarkT, Bool) {
var breaks: ArrayList<UInt8> = ArrayList<UInt8>()
var endMark = parser.mark
var max_indent = 0
while (true) {
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (breaks.toArray(), endMark, false)
}
}
while ((indent.value == 0 || parser.mark.column < indent.value) && isSpace(parser.buffer, parser.bufferPos)) {
skip(parser)
if (parser.unread < 1) {
if (!parserUpdateBuffer(parser, 1)) {
return (breaks.toArray(), endMark, false)
}
}
}
if (parser.mark.column > max_indent) {
max_indent = parser.mark.column
}
if ((indent.value == 0 || parser.mark.column < indent.value) && isTab(parser.buffer, parser.bufferPos)) {
return (breaks.toArray(), endMark, parserSetScannerError(
parser,
"while scanning a block scalar",
startMark,
"found a tab character where an indentation space is expected"
))
}
if (!isBreak(parser.buffer, parser.bufferPos)) {
break
}
if (parser.unread < 2 && !parserUpdateBuffer(parser, 2)) {
return (breaks.toArray(), endMark, false)
}
breaks.add(all: readLine(parser))
endMark = parser.mark
}
if (indent.value == 0) {
indent.value = max_indent
if (indent.value < parser.indent + 1) {
indent.value = parser.indent + 1
}
if (indent.value < 1) {
indent.value = 1
}
}
(breaks.toArray(), endMark, true)
}
func parserFetchFlowScalar(parser: ParserT, single: Bool): Bool {
if (!parserSaveSimpleKey(parser)) {
return false
}
parser.simpleKeyAllowed = false
let (token, ok) = parserScanFlowScalar(parser, single)
if (!ok) {
return false
}
insertToken(parser, -1, token)
return true
}
func parserScanFlowScalarResolveNonBlankz(
parser: ParserT,
single: Bool,
s: ArrayList<UInt8>,
token: TokenT,
startMark: MarkT,
leadingBlanksBox: Box<Bool>
): (?TokenT, Bool) {
while (!isBlankz(parser.buffer, parser.bufferPos)) {
if (single && parser.buffer[parser.bufferPos] == 0x27 && parser.buffer[parser.bufferPos + 1] == 0x27) {
s.add(0x27)
skip(parser)
skip(parser)
} else if (single && parser.buffer[parser.bufferPos] == 0x27) {
break
} else if (!single && parser.buffer[parser.bufferPos] == 0x22) {
break
} else if (!single && parser.buffer[parser.bufferPos] == 0x5C && isBreak(
parser.buffer,
parser.bufferPos + 1
)) {
if (parser.unread < 3 && !parserUpdateBuffer(parser, 3)) {
return (token, false)
}
skip(parser)
skipLine(parser)
leadingBlanksBox.value = true
break
} else if (!single && parser.buffer[parser.bufferPos] == 0x5C) {
var codeLength = 0
match (Rune(UInt32(parser.buffer[parser.bufferPos + 1]))) {
case '0' => s.add(0)
case 'a' => s.add(0x07)
case 'b' => s.add(0x08)
case 't' | '\t' => s.add(0x09)
case 'n' => s.add(0x0A)
case 'v' => s.add(0x0B)
case 'f' => s.add(0x0C)
case 'r' => s.add(0x0D)
case 'e' => s.add(0x1B)
case ' ' => s.add(0x20)
case '"' => s.add(0x22)
case '\'' => s.add(0x27)
case '\\' => s.add(0x5C)
case 'N' =>
s.add(0xC2)
s.add(0x85)
case '_' =>
s.add(0xC2)
s.add(0xA0)
case 'L' =>
s.add(0xE2)
s.add(0x80)
s.add(0xA8)
case 'P' =>
s.add(0xE2)
s.add(0x80)
s.add(0xA9)
case 'x' => codeLength = 2
case 'u' => codeLength = 4
case 'U' => codeLength = 8
case _ =>
parserSetScannerError(
parser,
"while parsing a quoted scalar",
startMark,
"found unknown escape character"
)
return (token, false)
}
skip(parser)
skip(parser)
if (codeLength > 0) {
var value: Int32 = 0
if (parser.unread < codeLength && !parserUpdateBuffer(parser, codeLength)) {
return (token, false)
}
for (k in 0..codeLength) {
if (!isHex(parser.buffer, parser.bufferPos + k)) {
parserSetScannerError(
parser,
"while parsing a quoted scalar",
startMark,
"did not find expected hexdecimal number"
)
return (token, false)
}
value = (value << 4) + Int32(asHex(parser.buffer, parser.bufferPos + k))
}
if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF) {
parserSetScannerError(
parser,
"while parsing a quoted scalar",
startMark,
"found invalid Unicode character escape code"
)
return (token, false)
}
if (value <= 0x7F) {
s.add(UInt8(value))
} else if (value <= 0x7FF) {
s.add(UInt8(0xC0 + (value >> 6)))
s.add(UInt8(0x80 + (value & 0x3F)))
} else if (value <= 0xFFFF) {
s.add(UInt8(0xE0 + (value >> 12)))
s.add(UInt8(0x80 + ((value >> 6) & 0x3F)))
s.add(UInt8(0x80 + (value & 0x3F)))
} else {
s.add(UInt8(0xF0 + (value >> 18)))
s.add(UInt8(0x80 + ((value >> 12) & 0x3F)))
s.add(UInt8(0x80 + ((value >> 6) & 0x3F)))
s.add(UInt8(0x80 + (value & 0x3F)))
}
for (_ in 0..codeLength) {
skip(parser)
}
}
} else {
s.add(all: read(parser))
}
if (parser.unread < 2 && !parserUpdateBuffer(parser, 2)) {
return (token, false)
}
}
(None, false)
}
func parserScanFlowScalarResolveBlankOrBreak(
parser: ParserT,
leadingBreak: ArrayList<UInt8>,
trailingBreaks: ArrayList<UInt8>,
whitespaces: ArrayList<UInt8>,
token: TokenT,
leadingBlanksBox: Box<Bool>
): (?TokenT, Bool) {
while (isBlank(parser.buffer, parser.bufferPos) || isBreak(parser.buffer, parser.bufferPos)) {
if (isBlank(parser.buffer, parser.bufferPos)) {
if (!leadingBlanksBox.value) {
whitespaces.add(all: read(parser))
} else {
skip(parser)
}
} else {
if (parser.unread < 2 && !parserUpdateBuffer(parser, 2)) {
return (token, false)
}
if (!leadingBlanksBox.value) {
whitespaces.clear()
leadingBreak.add(all: readLine(parser))
leadingBlanksBox.value = true
} else {
trailingBreaks.add(all: readLine(parser))
}
}
if (parser.unread < 1 && !parserUpdateBuffer(parser, 1)) {
return (token, false)
}
}
(None, false)
}
func parserScanFlowScalarResolveLeadingBlanks(
leadingBlanks: Bool,
s: ArrayList<UInt8>,
leadingBreak: ArrayList<UInt8>,
trailingBreaks: ArrayList<UInt8>,
whitespaces: ArrayList<UInt8>
) {
if (leadingBlanks) {
if (leadingBreak.size > 0 && leadingBreak[0] == 0x0A) {
if (trailingBreaks.size == 0) {
s.add(0x20)
} else {
s.add(all: trailingBreaks)
}
} else {
s.add(all: leadingBreak)
s.add(all: trailingBreaks)
}
trailingBreaks.clear()
leadingBreak.clear()
} else {
s.add(all: whitespaces)
whitespaces.clear()
}
}
func parserScanFlowScalarResolvePreConditions(
parser: ParserT,
token: TokenT,
startMark: MarkT
): (?TokenT, Bool) {
if (parser.unread < 4 && !parserUpdateBuffer(parser, 4)) {
return (token, false)
}
if (parser.mark.column == 0 && ((parser.buffer[parser.bufferPos + 0] == 0x2D &&
parser.buffer[parser.bufferPos + 1] == 0x2D && parser.buffer[parser.bufferPos + 2] == 0x2D) || (parser.buffer[parser.
bufferPos + 0] == 0x2E && parser.buffer[parser.bufferPos + 1] == 0x2E &&
parser.buffer[parser.bufferPos + 2] == 0x2E)) && isBlankz(parser.buffer, parser.bufferPos + 3)) {
parserSetScannerError(
parser,
"while scanning a quoted scalar",
startMark,
"found unexpected document indicator"
)
return (token, false)
}
if (isZ(parser.buffer, parser.bufferPos)) {
parserSetScannerError(
parser,
"while scanning a quoted scalar",
startMark,
"found unexpected end of stream"
)
return (token, false)
}
(None, false)
}
func parserScanFlowScalarLoop(
parser: ParserT,
single: Bool,
token: TokenT,
startMark: MarkT,
s: ArrayList<UInt8>,
leadingBreak: ArrayList<UInt8>,
trailingBreaks: ArrayList<UInt8>,
whitespaces: ArrayList<UInt8>
): ?(TokenT, Bool, Bool) {
if (let (Some(t), ok) <- parserScanFlowScalarResolvePreConditions(parser, token, startMark)) {
return (t, ok, false)
}
var leadingBlanks = false
let leadingBlanksBox = Box<Bool>(leadingBlanks)
if (let (Some(t), ok) <- parserScanFlowScalarResolveNonBlankz(
parser,
single,
s,
token,
startMark,
leadingBlanksBox
)) {
return (t, ok, false)
}
leadingBlanks = leadingBlanksBox.value
if (parser.unread < 1 && !parserUpdateBuffer(parser, 1)) {
return (token, false, false)
}
if (single) {
if (parser.buffer[parser.bufferPos] == 0x27) {
return (token, false, true)
}
} else {
if (parser.buffer[parser.bufferPos] == 0x22) {
return (token, false, true)
}
}
if (let (Some(t), ok) <- parserScanFlowScalarResolveBlankOrBreak(
parser,
leadingBreak,
trailingBreaks,
whitespaces,
token,
leadingBlanksBox
)) {
return (t, ok, false)
}
leadingBlanks = leadingBlanksBox.value
parserScanFlowScalarResolveLeadingBlanks(
leadingBlanks,
s,
leadingBreak,
trailingBreaks,
whitespaces
)
return None
}
func parserScanFlowScalar(parser: ParserT, single: Bool): (TokenT, Bool) {
let startMark = parser.mark
skip(parser)
let token = TokenT()
let s = ArrayList<UInt8>()
let leadingBreak = ArrayList<UInt8>()
let trailingBreaks = ArrayList<UInt8>()
let whitespaces = ArrayList<UInt8>()
while (true) {
if (let Some((t, ok, isBreak)) <- parserScanFlowScalarLoop(
parser,
single,
token,
startMark,
s,
leadingBreak,
trailingBreaks,
whitespaces
)) {
if (isBreak) {
break
}
return (t, ok)
}
}
skip(parser)
token.typ = TokenTypeT_SCALAR_TOKEN
token.startMark = startMark
token.endMark = parser.mark
token.value = s.toArray()
token.style = ScalarStyleT_SINGLE_QUOTED_SCALAR_STYLE
(token, true)
}
func parserScanPlainScalarResolve0(
parser: ParserT,
s: ArrayList<UInt8>,
leadingBreak: ArrayList<UInt8>,
trailingBreaks: ArrayList<UInt8>,
whitespaces: ArrayList<UInt8>,
leadingBlanksBox: Box<Bool>,
token: TokenT,
endMarkBox: Box<MarkT>
): (?TokenT, Bool) {
while (!isBlankz(parser.buffer, parser.bufferPos)) {
if ((parser.buffer[parser.bufferPos] == 0x3A && isBlankz(parser.buffer, parser.bufferPos + 1)) || (parser.
flowLevel > 0 && (parser.buffer[parser.bufferPos] == 0x2C || parser.buffer[parser.bufferPos] == 0x3F ||
parser.buffer[parser.bufferPos] == 0x5B || parser.buffer[parser.bufferPos] == 0x5D ||
parser.buffer[parser.bufferPos] == 0x7B || parser.buffer[parser.bufferPos] == 0x7D))) {
break
}
if (leadingBlanksBox.value || whitespaces.size > 0) {
if (leadingBlanksBox.value) {
if (leadingBreak[0] == 0x0A) {
if (trailingBreaks.size == 0) {
s.add(0x20)
} else {
s.add(all: trailingBreaks)
}
} else {
s.add(all: leadingBreak)
s.add(all: trailingBreaks)
}
trailingBreaks.clear()
leadingBreak.clear()
leadingBlanksBox.value = false
} else {
s.add(all: whitespaces)
whitespaces.clear()
}
}
s.add(all: read(parser))
endMarkBox.value = parser.mark
if (parser.unread < 2 && !parserUpdateBuffer(parser, 2)) {
return (token, false)
}
}
(None, false)
}
func parserScanPlainScalarResolve0(
parser: ParserT,
indent: Int64,
startMark: MarkT,
token: TokenT,
leadingBlanksBox: Box<Bool>,
leadingBreak: ArrayList<UInt8>,
trailingBreaks: ArrayList<UInt8>,
whitespaces: ArrayList<UInt8>
): (?TokenT, Bool) {
while (isBlank(parser.buffer, parser.bufferPos) || isBreak(parser.buffer, parser.bufferPos)) {
if (isBlank(parser.buffer, parser.bufferPos)) {
if (leadingBlanksBox.value && parser.mark.column < indent && isTab(parser.buffer, parser.bufferPos)) {
parserSetScannerError(
parser,
"while scanning a plain scalar",
startMark,
"found a tab character that violates indentation"
)
return (token, false)
}
if (!leadingBlanksBox.value) {
whitespaces.add(all: read(parser))
} else {
skip(parser)
}
} else {
if (parser.unread < 2 && !parserUpdateBuffer(parser, 2)) {
return (token, false)
}
if (!leadingBlanksBox.value) {
whitespaces.clear()
leadingBreak.add(all: readLine(parser))
leadingBlanksBox.value = true
} else {
trailingBreaks.add(all: readLine(parser))
}
}
if (parser.unread < 1 && !parserUpdateBuffer(parser, 1)) {
return (token, false)
}
}
(None, false)
}
func parserScanPlainScalarLoop(
parser: ParserT,
token: TokenT,
indent: Int64,
startMark: MarkT,
s: ArrayList<UInt8>,
leadingBreak: ArrayList<UInt8>,
trailingBreaks: ArrayList<UInt8>,
whitespaces: ArrayList<UInt8>,
leadingBlanks: Box<Bool>,
endMark: Box<MarkT>
): ?(TokenT, Bool, Bool) {
if (parser.unread < 4 && !parserUpdateBuffer(parser, 4)) {
return (token, false, false)
}
if (parser.mark.column == 0 && ((parser.buffer[parser.bufferPos + 0] == 0x2D &&
parser.buffer[parser.bufferPos + 1] == 0x2D && parser.buffer[parser.bufferPos + 2] == 0x2D) || (parser.buffer[parser.
bufferPos + 0] == 0x2E && parser.buffer[parser.bufferPos + 1] == 0x2E &&
parser.buffer[parser.bufferPos + 2] == 0x2E)) && isBlankz(parser.buffer, parser.bufferPos + 3)) {
return (token, false, true)
}
if (parser.buffer[parser.bufferPos] == 0x23) {
return (token, false, true)
}
if (let (Some(t), ok) <- parserScanPlainScalarResolve0(
parser,
s,
leadingBreak,
trailingBreaks,
whitespaces,
leadingBlanks,
token,
endMark
)) {
return (t, ok, false)
}
if (!(isBlank(parser.buffer, parser.bufferPos) || isBreak(parser.buffer, parser.bufferPos))) {
return (token, false, true)
}
if (parser.unread < 1 && !parserUpdateBuffer(parser, 1)) {
return (token, false, false)
}
if (let (Some(t), ok) <- parserScanPlainScalarResolve0(
parser,
indent,
startMark,
token,
leadingBlanks,
leadingBreak,
trailingBreaks,
whitespaces
)) {
return (t, ok, false)
}
if (parser.flowLevel == 0 && parser.mark.column < indent) {
return (token, false, true)
}
return None
}
func parserScanPlainScalar(parser: ParserT): (TokenT, Bool) {
let token = TokenT()
let s = ArrayList<UInt8>()
let leadingBreak = ArrayList<UInt8>()
let trailingBreaks = ArrayList<UInt8>()
let whitespaces = ArrayList<UInt8>()
var leadingBlanks = Box<Bool>(false)
var indent = parser.indent + 1
let startMark = parser.mark
var endMark = Box<MarkT>(parser.mark)
while (true) {
if (let Some((t, ok, isBreak)) <- parserScanPlainScalarLoop(
parser,
token,
indent,
startMark,
s,
leadingBreak,
trailingBreaks,
whitespaces,
leadingBlanks,
endMark
)) {
if (isBreak) {
break
}
return (t, ok)
}
}
token.typ = TokenTypeT_SCALAR_TOKEN
token.startMark = startMark
token.endMark = endMark.value
token.value = s.toArray()
token.style = ScalarStyleT_PLAIN_SCALAR_STYLE
if (leadingBlanks.value) {
parser.simpleKeyAllowed = true
}
(token, true)
}