mirror of https://github.com/status-im/NimYAML.git
Fixes for block scalars and doc end markers
* Properly (now really) handle block scalars at doc root * Properly handle multiple document end markers
This commit is contained in:
parent
22b8de876d
commit
0fc30241b9
|
@ -8,7 +8,7 @@ type
|
||||||
FastParseState = enum
|
FastParseState = enum
|
||||||
fpInitial, fpBlockLineStart, fpBlockAfterObject, fpBlockAfterPlainScalar,
|
fpInitial, fpBlockLineStart, fpBlockAfterObject, fpBlockAfterPlainScalar,
|
||||||
fpBlockObjectStart, fpBlockContinueScalar, fpExpectDocEnd, fpFlow,
|
fpBlockObjectStart, fpBlockContinueScalar, fpExpectDocEnd, fpFlow,
|
||||||
fpFlowAfterObject
|
fpFlowAfterObject, fpAfterDocument
|
||||||
|
|
||||||
FastParseLevelKind = enum
|
FastParseLevelKind = enum
|
||||||
fplUnknown, fplSequence, fplMapKey, fplMapValue, fplSinglePairKey,
|
fplUnknown, fplSequence, fplMapKey, fplMapValue, fplSinglePairKey,
|
||||||
|
@ -872,7 +872,7 @@ template blockScalar(lexer: BaseLexer, content: var string,
|
||||||
block outer:
|
block outer:
|
||||||
while true:
|
while true:
|
||||||
block inner:
|
block inner:
|
||||||
for i in countup(1, parentIndent):
|
for i in countup(1, parentIndent + 1):
|
||||||
case lexer.buf[lexer.bufpos]
|
case lexer.buf[lexer.bufpos]
|
||||||
of ' ': discard
|
of ' ': discard
|
||||||
of '\l':
|
of '\l':
|
||||||
|
@ -887,8 +887,15 @@ template blockScalar(lexer: BaseLexer, content: var string,
|
||||||
stateAfter = if i == 1: fpBlockLineStart else: fpBlockObjectStart
|
stateAfter = if i == 1: fpBlockLineStart else: fpBlockObjectStart
|
||||||
break outer
|
break outer
|
||||||
lexer.bufpos.inc()
|
lexer.bufpos.inc()
|
||||||
|
if parentIndent == -1 and lexer.buf[lexer.bufpos] == '.':
|
||||||
|
var isDocumentEnd: bool
|
||||||
|
startToken()
|
||||||
|
lexer.documentEnd(isDocumentEnd)
|
||||||
|
if isDocumentEnd:
|
||||||
|
stateAfter = fpExpectDocEnd
|
||||||
|
break outer
|
||||||
if detectedIndent:
|
if detectedIndent:
|
||||||
for i in countup(1, blockIndent):
|
for i in countup(1, blockIndent - 1 + max(0, -parentIndent)):
|
||||||
case lexer.buf[lexer.bufpos]
|
case lexer.buf[lexer.bufpos]
|
||||||
of ' ': discard
|
of ' ': discard
|
||||||
of '\l':
|
of '\l':
|
||||||
|
@ -910,11 +917,6 @@ template blockScalar(lexer: BaseLexer, content: var string,
|
||||||
else: discard
|
else: discard
|
||||||
stateAfter = fpBlockLineStart
|
stateAfter = fpBlockLineStart
|
||||||
break outer
|
break outer
|
||||||
else:
|
|
||||||
if i == 1:
|
|
||||||
stateAfter = if parentIndent <= 0: fpBlockLineStart else:
|
|
||||||
fpBlockObjectStart
|
|
||||||
break outer
|
|
||||||
else:
|
else:
|
||||||
startToken()
|
startToken()
|
||||||
parserError("The text is less indented than expected ")
|
parserError("The text is less indented than expected ")
|
||||||
|
@ -937,8 +939,8 @@ template blockScalar(lexer: BaseLexer, content: var string,
|
||||||
else:
|
else:
|
||||||
blockIndent =
|
blockIndent =
|
||||||
lexer.getColNumber(lexer.bufpos) - max(0, parentIndent)
|
lexer.getColNumber(lexer.bufpos) - max(0, parentIndent)
|
||||||
if blockIndent == 0:
|
if blockIndent == 0 and parentIndent >= 0:
|
||||||
stateAfter = if blockIndent + max(0, parentIndent) > 0:
|
stateAfter = if blockIndent + parentIndent > 0:
|
||||||
fpBlockObjectStart else: fpBlockLineStart
|
fpBlockObjectStart else: fpBlockLineStart
|
||||||
break outer
|
break outer
|
||||||
detectedIndent = true
|
detectedIndent = true
|
||||||
|
@ -1000,6 +1002,27 @@ template blockScalar(lexer: BaseLexer, content: var string,
|
||||||
of ctStrip: discard
|
of ctStrip: discard
|
||||||
debug("lex: \"" & content & '\"')
|
debug("lex: \"" & content & '\"')
|
||||||
|
|
||||||
|
template consumeLineIfEmpty(lex: BaseLexer): bool =
|
||||||
|
var result = true
|
||||||
|
while true:
|
||||||
|
lex.bufpos.inc()
|
||||||
|
case lex.buf[lex.bufpos]
|
||||||
|
of ' ', '\t': discard
|
||||||
|
of '\l':
|
||||||
|
lex.bufpos = lex.handleLF(lex.bufpos)
|
||||||
|
break
|
||||||
|
of '\c':
|
||||||
|
lex.bufpos = lex.handleCR(lex.bufpos)
|
||||||
|
break
|
||||||
|
of '#', EndOfFile:
|
||||||
|
lex.lineEnding()
|
||||||
|
handleLineEnd(false)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
result = false
|
||||||
|
break
|
||||||
|
result
|
||||||
|
|
||||||
proc parse*(p: YamlParser, s: Stream): YamlStream =
|
proc parse*(p: YamlParser, s: Stream): YamlStream =
|
||||||
var backend = iterator(): YamlStreamEvent =
|
var backend = iterator(): YamlStreamEvent =
|
||||||
var
|
var
|
||||||
|
@ -1057,25 +1080,10 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
|
||||||
p.lexer.finishLine()
|
p.lexer.finishLine()
|
||||||
handleLineEnd(false)
|
handleLineEnd(false)
|
||||||
of ' ', '\t':
|
of ' ', '\t':
|
||||||
while true:
|
if not p.lexer.consumeLineIfEmpty():
|
||||||
p.lexer.bufpos.inc()
|
|
||||||
case p.lexer.buf[p.lexer.bufpos]
|
|
||||||
of ' ', '\t': discard
|
|
||||||
of '\l':
|
|
||||||
p.lexer.bufpos = p.lexer.handleLF(p.lexer.bufpos)
|
|
||||||
break
|
|
||||||
of '\c':
|
|
||||||
p.lexer.bufpos = p.lexer.handleCR(p.lexer.bufpos)
|
|
||||||
break
|
|
||||||
of '#', EndOfFile:
|
|
||||||
p.lexer.lineEnding()
|
|
||||||
handleLineEnd(false)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
indentation = p.lexer.getColNumber(p.lexer.bufpos)
|
indentation = p.lexer.getColNumber(p.lexer.bufpos)
|
||||||
yield startDocEvent()
|
yield startDocEvent()
|
||||||
state = fpBlockObjectStart
|
state = fpBlockObjectStart
|
||||||
break
|
|
||||||
of '\l': p.lexer.bufpos = p.lexer.handleLF(p.lexer.bufpos)
|
of '\l': p.lexer.bufpos = p.lexer.handleLF(p.lexer.bufpos)
|
||||||
of '\c': p.lexer.bufpos = p.lexer.handleCR(p.lexer.bufpos)
|
of '\c': p.lexer.bufpos = p.lexer.handleCR(p.lexer.bufpos)
|
||||||
of EndOfFile: return
|
of EndOfFile: return
|
||||||
|
@ -1139,12 +1147,11 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
|
||||||
startToken()
|
startToken()
|
||||||
p.lexer.documentEnd(isDocumentEnd)
|
p.lexer.documentEnd(isDocumentEnd)
|
||||||
if isDocumentEnd:
|
if isDocumentEnd:
|
||||||
|
closeEverything()
|
||||||
p.lexer.bufpos.inc(3)
|
p.lexer.bufpos.inc(3)
|
||||||
p.lexer.lineEnding()
|
p.lexer.lineEnding()
|
||||||
handleLineEnd(true)
|
handleLineEnd(false)
|
||||||
closeEverything()
|
state = fpAfterDocument
|
||||||
initDocValues()
|
|
||||||
state = fpInitial
|
|
||||||
else:
|
else:
|
||||||
indentation = 0
|
indentation = 0
|
||||||
closeMoreIndentedLevels()
|
closeMoreIndentedLevels()
|
||||||
|
@ -1407,6 +1414,7 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
|
||||||
p.lexer.plainScalar(content, cBlock)
|
p.lexer.plainScalar(content, cBlock)
|
||||||
state = fpBlockAfterPlainScalar
|
state = fpBlockAfterPlainScalar
|
||||||
of fpExpectDocEnd:
|
of fpExpectDocEnd:
|
||||||
|
debug("state: expectDocEnd")
|
||||||
case p.lexer.buf[p.lexer.bufpos]
|
case p.lexer.buf[p.lexer.bufpos]
|
||||||
of '-':
|
of '-':
|
||||||
var token: LexedPossibleDirectivesEnd
|
var token: LexedPossibleDirectivesEnd
|
||||||
|
@ -1425,12 +1433,12 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
|
||||||
startToken()
|
startToken()
|
||||||
p.lexer.documentEnd(isDocumentEnd)
|
p.lexer.documentEnd(isDocumentEnd)
|
||||||
if isDocumentEnd:
|
if isDocumentEnd:
|
||||||
|
closeEverything()
|
||||||
p.lexer.bufpos.inc(3)
|
p.lexer.bufpos.inc(3)
|
||||||
yield endDocEvent()
|
p.lexer.lineEnding()
|
||||||
initDocValues()
|
handleLineEnd(false)
|
||||||
state = fpInitial
|
state = fpAfterDocument
|
||||||
else:
|
else: parserError("Unexpected content (expected document end)")
|
||||||
parserError("Unexpected content (expected document end)")
|
|
||||||
of ' ', '\t', '#':
|
of ' ', '\t', '#':
|
||||||
p.lexer.lineEnding()
|
p.lexer.lineEnding()
|
||||||
handleLineEnd(true)
|
handleLineEnd(true)
|
||||||
|
@ -1442,6 +1450,34 @@ proc parse*(p: YamlParser, s: Stream): YamlStream =
|
||||||
else:
|
else:
|
||||||
startToken()
|
startToken()
|
||||||
parserError("Unexpected content (expected document end)")
|
parserError("Unexpected content (expected document end)")
|
||||||
|
of fpAfterDocument:
|
||||||
|
debug("state: afterDocument")
|
||||||
|
case p.lexer.buf[p.lexer.bufpos]
|
||||||
|
of '.':
|
||||||
|
var isDocumentEnd: bool
|
||||||
|
startToken()
|
||||||
|
p.lexer.documentEnd(isDocumentEnd)
|
||||||
|
if isDocumentEnd:
|
||||||
|
p.lexer.bufpos.inc(3)
|
||||||
|
p.lexer.lineEnding()
|
||||||
|
handleLineEnd(false)
|
||||||
|
else:
|
||||||
|
initDocValues()
|
||||||
|
yield startDocEvent()
|
||||||
|
state = fpBlockLineStart
|
||||||
|
of '#':
|
||||||
|
p.lexer.lineEnding()
|
||||||
|
handleLineEnd(false)
|
||||||
|
of '\t', ' ':
|
||||||
|
if not p.lexer.consumeLineIfEmpty():
|
||||||
|
indentation = p.lexer.getColNumber(p.lexer.bufpos)
|
||||||
|
initDocValues()
|
||||||
|
yield startDocEvent()
|
||||||
|
state = fpBlockObjectStart
|
||||||
|
of EndOfFile: break
|
||||||
|
else:
|
||||||
|
initDocValues()
|
||||||
|
state = fpInitial
|
||||||
of fpFlow:
|
of fpFlow:
|
||||||
debug("state: flow")
|
debug("state: flow")
|
||||||
p.lexer.skipWhitespaceCommentsAndNewlines()
|
p.lexer.skipWhitespaceCommentsAndNewlines()
|
||||||
|
|
Loading…
Reference in New Issue