2015-12-23 11:35:07 +00:00
|
|
|
# file must be included from yaml.nim and cannot compile on its own
|
2015-12-05 11:10:17 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
YamlParserState = enum
|
2015-12-23 11:35:07 +00:00
|
|
|
ypInitial, ypSkipDirective, ypBlockLineStart, ypBlockAfterTag,
|
|
|
|
ypBlockAfterAnchor, ypBlockAfterAnchorAndTag, ypBlockAfterScalar,
|
|
|
|
ypBlockAfterAlias, ypBlockAfterColon, ypBlockMultilineScalar,
|
|
|
|
ypBlockLineEnd, ypBlockScalarHeader, ypBlockScalar, ypFlow,
|
|
|
|
ypFlowAfterObject, ypFlowAfterTag, ypFlowAfterAnchor,
|
|
|
|
ypFlowAfterAnchorAndTag, ypExpectingDocumentEnd, ypAfterDirectivesEnd
|
2015-12-05 11:10:17 +00:00
|
|
|
|
2015-12-11 21:55:21 +00:00
|
|
|
DocumentLevelMode = enum
|
|
|
|
mBlockSequenceItem, mFlowSequenceItem, mExplicitBlockMapKey,
|
2015-12-22 20:08:58 +00:00
|
|
|
mImplicitBlockMapKey, mBlockMapValue, mFlowMapKey, mFlowMapValue,
|
|
|
|
mScalar, mUnknown
|
2015-12-05 11:10:17 +00:00
|
|
|
|
|
|
|
DocumentLevel = object
|
2015-12-11 21:55:21 +00:00
|
|
|
mode: DocumentLevelMode
|
2015-12-05 11:10:17 +00:00
|
|
|
indicatorColumn: int
|
2015-12-11 21:55:21 +00:00
|
|
|
indentationColumn: int
|
2015-12-17 20:44:41 +00:00
|
|
|
|
|
|
|
LineStrippingMode = enum
|
|
|
|
lsStrip, lsClip, lsKeep
|
|
|
|
|
|
|
|
BlockScalarStyle = enum
|
|
|
|
bsLiteral, bsFolded
|
2015-12-21 20:40:27 +00:00
|
|
|
|
|
|
|
const
|
2015-12-22 15:28:35 +00:00
|
|
|
tagExclamationMark*: TagId = 0.TagId # "!" non-specific tag
|
|
|
|
tagQuestionMark* : TagId = 1.TagId # "?" non-specific tag
|
|
|
|
anchorNone*: AnchorId = (-1).AnchorId # no anchor defined
|
2015-12-21 20:40:27 +00:00
|
|
|
|
|
|
|
# interface
|
|
|
|
|
|
|
|
proc `==`*(left: YamlParserEvent, right: YamlParserEvent): bool
|
|
|
|
|
|
|
|
proc `==`*(left, right: TagId): bool {.borrow.}
|
2015-12-21 20:58:28 +00:00
|
|
|
proc `$`*(id: TagId): string {.borrow.}
|
2015-12-21 20:40:27 +00:00
|
|
|
|
2015-12-22 15:28:35 +00:00
|
|
|
proc `==`*(left, right: AnchorId): bool {.borrow.}
|
|
|
|
proc `$`*(id: AnchorId): string {.borrow.}
|
|
|
|
|
2015-12-23 11:35:07 +00:00
|
|
|
proc newParser*(): YamlSequentialParser
|
2015-12-21 20:40:27 +00:00
|
|
|
|
|
|
|
# iterators cannot be pre-declared.
|
|
|
|
#
|
|
|
|
# iterator events*(parser: YamlSequentialParser,
|
|
|
|
# input: Stream): YamlParserEvent
|
|
|
|
|
|
|
|
proc uri*(parser: YamlSequentialParser, id: TagId): string
|
|
|
|
|
|
|
|
proc registerUri*(parser: var YamlSequentialParser, uri: string): TagId
|
|
|
|
|
2015-12-22 15:28:35 +00:00
|
|
|
proc anchor*(parser: YamlSequentialParser, id: AnchorId): string
|
|
|
|
|
2015-12-21 20:40:27 +00:00
|
|
|
# implementation
|
|
|
|
|
2015-12-23 11:35:07 +00:00
|
|
|
proc newParser*(): YamlSequentialParser =
|
|
|
|
new(result)
|
2015-12-21 20:40:27 +00:00
|
|
|
result.tags = initOrderedTable[string, TagId]()
|
2015-12-22 15:28:35 +00:00
|
|
|
result.tags["!"] = tagExclamationMark
|
|
|
|
result.tags["?"] = tagQuestionMark
|
|
|
|
result.anchors = initOrderedTable[string, AnchorId]()
|
2015-12-21 20:40:27 +00:00
|
|
|
|
|
|
|
proc uri*(parser: YamlSequentialParser, id: TagId): string =
|
|
|
|
for pair in parser.tags.pairs:
|
|
|
|
if pair[1] == id:
|
|
|
|
return pair[0]
|
|
|
|
return nil
|
|
|
|
|
|
|
|
proc registerUri*(parser: var YamlSequentialParser, uri: string): TagId =
|
|
|
|
result = cast[TagId](parser.tags.len)
|
|
|
|
if parser.tags.hasKeyOrPut(uri, result):
|
|
|
|
result = parser.tags[uri]
|
2015-12-07 21:09:57 +00:00
|
|
|
|
2015-12-22 15:28:35 +00:00
|
|
|
proc anchor*(parser: YamlSequentialParser, id: AnchorId): string =
|
|
|
|
for pair in parser.anchors.pairs:
|
|
|
|
if pair[1] == id:
|
|
|
|
return pair[0]
|
|
|
|
return nil
|
|
|
|
|
2015-12-07 21:09:57 +00:00
|
|
|
proc `==`*(left: YamlParserEvent, right: YamlParserEvent): bool =
|
|
|
|
if left.kind != right.kind:
|
|
|
|
return false
|
|
|
|
case left.kind
|
|
|
|
of yamlStartDocument, yamlEndDocument, yamlEndMap, yamlEndSequence:
|
|
|
|
result = true
|
|
|
|
of yamlStartMap, yamlStartSequence:
|
|
|
|
result = left.objAnchor == right.objAnchor and
|
|
|
|
left.objTag == right.objTag
|
|
|
|
of yamlScalar:
|
|
|
|
result = left.scalarAnchor == right.scalarAnchor and
|
|
|
|
left.scalarTag == right.scalarTag and
|
|
|
|
left.scalarContent == right.scalarContent
|
|
|
|
of yamlAlias:
|
2015-12-22 15:28:35 +00:00
|
|
|
result = left.aliasTarget == right.aliasTarget
|
2015-12-07 21:09:57 +00:00
|
|
|
of yamlError, yamlWarning:
|
|
|
|
result = left.description == right.description and
|
|
|
|
left.line == right.line and left.column == right.column
|
2015-12-05 11:10:17 +00:00
|
|
|
|
|
|
|
template yieldWarning(d: string) {.dirty.} =
|
|
|
|
yield YamlParserEvent(kind: yamlWarning, description: d,
|
|
|
|
line: lex.line, column: lex.column)
|
|
|
|
|
|
|
|
template yieldError(d: string) {.dirty.} =
|
|
|
|
yield YamlParserEvent(kind: yamlError, description: d,
|
|
|
|
line: lex.line, column: lex.column)
|
2015-12-11 21:55:21 +00:00
|
|
|
break parserLoop
|
2015-12-05 11:10:17 +00:00
|
|
|
|
2015-12-22 15:28:35 +00:00
|
|
|
template yieldUnexpectedToken(expected: string = "") {.dirty.} =
|
|
|
|
var msg = "[" & $state & "] Unexpected token"
|
|
|
|
if expected.len > 0:
|
|
|
|
msg.add(" (expected " & expected & ")")
|
|
|
|
msg.add(": " & $token)
|
|
|
|
yieldError(msg)
|
|
|
|
|
2015-12-23 11:35:07 +00:00
|
|
|
proc resolveAnchor(parser: YamlSequentialParser, anchor: var string):
|
2015-12-22 15:28:35 +00:00
|
|
|
AnchorId {.inline.} =
|
|
|
|
result = anchorNone
|
|
|
|
if anchor.len > 0:
|
|
|
|
result = cast[AnchorId](parser.anchors.len)
|
|
|
|
if parser.anchors.hasKeyOrPut(anchor, result):
|
|
|
|
result = parser.anchors[anchor]
|
|
|
|
anchor = ""
|
|
|
|
|
2015-12-23 11:35:07 +00:00
|
|
|
proc resolveAlias(parser: YamlSequentialParser, name: string): AnchorId =
|
2015-12-22 15:28:35 +00:00
|
|
|
try:
|
|
|
|
result = parser.anchors[name]
|
|
|
|
except KeyError:
|
|
|
|
result = anchorNone
|
|
|
|
|
2015-12-23 11:35:07 +00:00
|
|
|
proc resolveTag(parser: YamlSequentialParser, tag: var string,
|
2015-12-22 15:28:35 +00:00
|
|
|
quotedString: bool = false): TagId {.inline.} =
|
|
|
|
if tag.len == 0:
|
|
|
|
result = if quotedString: tagExclamationMark else: tagQuestionMark
|
2015-12-21 20:58:28 +00:00
|
|
|
else:
|
|
|
|
try:
|
2015-12-22 15:28:35 +00:00
|
|
|
result = parser.tags[tag]
|
2015-12-21 20:58:28 +00:00
|
|
|
except KeyError:
|
2015-12-22 15:28:35 +00:00
|
|
|
result = cast[TagId](parser.tags.len)
|
|
|
|
parser.tags[tag] = result
|
|
|
|
tag = ""
|
|
|
|
|
|
|
|
template yieldScalar(content: string = "", quoted: bool = false) {.dirty.} =
|
2015-12-11 21:55:21 +00:00
|
|
|
yield YamlParserEvent(kind: yamlScalar,
|
2015-12-22 15:28:35 +00:00
|
|
|
scalarAnchor: resolveAnchor(parser, anchor),
|
|
|
|
scalarTag: resolveTag(parser, tag, quoted),
|
2015-12-11 21:55:21 +00:00
|
|
|
scalarContent: content)
|
2015-12-05 11:10:17 +00:00
|
|
|
|
2015-12-11 21:55:21 +00:00
|
|
|
template yieldStart(k: YamlParserEventKind) {.dirty.} =
|
2015-12-22 15:28:35 +00:00
|
|
|
yield YamlParserEvent(kind: k, objAnchor: resolveAnchor(parser, anchor),
|
|
|
|
objTag: resolveTag(parser, tag))
|
2015-12-05 11:10:17 +00:00
|
|
|
|
2015-12-21 22:10:42 +00:00
|
|
|
template yieldDocumentEnd() {.dirty.} =
|
|
|
|
yield YamlParserEvent(kind: yamlEndDocument)
|
|
|
|
tagShorthands = initTable[string, string]()
|
|
|
|
tagShorthands["!"] = "!"
|
|
|
|
tagShorthands["!!"] = "tag:yaml.org,2002:"
|
2015-12-22 15:28:35 +00:00
|
|
|
parser.anchors = initOrderedTable[string, AnchorId]()
|
2015-12-21 22:10:42 +00:00
|
|
|
|
2015-12-11 21:55:21 +00:00
|
|
|
template closeLevel(lvl: DocumentLevel) {.dirty.} =
|
|
|
|
case lvl.mode
|
|
|
|
of mExplicitBlockMapKey, mFlowMapKey:
|
2015-12-22 21:28:27 +00:00
|
|
|
yieldScalar("")
|
|
|
|
yield YamlParserEvent(kind: yamlEndMap)
|
2015-12-22 20:08:58 +00:00
|
|
|
of mImplicitBlockMapKey, mBlockMapValue, mFlowMapValue:
|
2015-12-11 21:55:21 +00:00
|
|
|
yield YamlParserEvent(kind: yamlEndMap)
|
|
|
|
of mBlockSequenceItem, mFlowSequenceItem:
|
|
|
|
yield YamlParserEvent(kind: yamlEndSequence)
|
2015-12-14 20:26:34 +00:00
|
|
|
of mScalar:
|
2015-12-22 15:28:35 +00:00
|
|
|
yield YamlParserEvent(kind: yamlScalar,
|
|
|
|
scalarAnchor: resolveAnchor(parser, anchor),
|
|
|
|
scalarTag: resolveTag(parser, tag),
|
|
|
|
scalarContent: scalarCache)
|
2015-12-21 20:40:27 +00:00
|
|
|
|
2015-12-11 21:55:21 +00:00
|
|
|
else:
|
|
|
|
yieldScalar()
|
|
|
|
|
2015-12-22 22:35:03 +00:00
|
|
|
proc mustLeaveLevel(curCol: int, ancestry: seq[DocumentLevel]): bool =
|
|
|
|
if ancestry.len == 0:
|
|
|
|
result = false
|
|
|
|
else:
|
|
|
|
let parent = ancestry[ancestry.high]
|
|
|
|
result = parent.indicatorColumn >= curCol or
|
|
|
|
(parent.indicatorColumn == -1 and
|
|
|
|
parent.indentationColumn >= curCol)
|
|
|
|
|
2015-12-11 21:55:21 +00:00
|
|
|
template leaveMoreIndentedLevels() {.dirty.} =
|
2015-12-14 20:26:34 +00:00
|
|
|
while ancestry.len > 0:
|
|
|
|
let parent = ancestry[ancestry.high]
|
|
|
|
if parent.indicatorColumn >= lex.column or
|
|
|
|
(parent.indicatorColumn == -1 and
|
|
|
|
parent.indentationColumn >= lex.column):
|
|
|
|
closeLevel(level)
|
|
|
|
level = ancestry.pop()
|
2015-12-22 20:08:58 +00:00
|
|
|
if level.mode == mBlockMapValue:
|
2015-12-14 20:26:34 +00:00
|
|
|
level.mode = mImplicitBlockMapKey
|
|
|
|
else:
|
|
|
|
break
|
2015-12-11 21:55:21 +00:00
|
|
|
|
2015-12-07 21:09:57 +00:00
|
|
|
template closeAllLevels() {.dirty.} =
|
2015-12-11 21:55:21 +00:00
|
|
|
while true:
|
|
|
|
closeLevel(level)
|
|
|
|
if ancestry.len == 0: break
|
|
|
|
level = ancestry.pop()
|
|
|
|
|
2015-12-22 21:28:27 +00:00
|
|
|
template handleBlockIndicator(expected, possible: openarray[DocumentLevelMode],
|
2015-12-22 20:08:58 +00:00
|
|
|
next: DocumentLevelMode,
|
2015-12-22 21:28:27 +00:00
|
|
|
entering: YamlParserEventKind,
|
|
|
|
emptyScalarOnOpening: bool = false) {.dirty.} =
|
2015-12-11 21:55:21 +00:00
|
|
|
leaveMoreIndentedLevels()
|
2015-12-22 20:08:58 +00:00
|
|
|
if level.indicatorColumn == lex.column or
|
|
|
|
level.indicatorColumn == -1 and level.indentationColumn == lex.column:
|
|
|
|
if level.mode in expected:
|
2015-12-11 21:55:21 +00:00
|
|
|
level.mode = next
|
|
|
|
ancestry.add(level)
|
|
|
|
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
|
|
|
indentationColumn: -1)
|
|
|
|
else:
|
2015-12-22 21:28:27 +00:00
|
|
|
# `in` does not work if possible is [], so we have to check for that
|
|
|
|
when possible.len > 0:
|
|
|
|
if level.mode in possible:
|
|
|
|
yieldScalar("")
|
|
|
|
level.mode = next
|
|
|
|
ancestry.add(level)
|
|
|
|
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
|
|
|
indentationColumn: -1)
|
|
|
|
else:
|
|
|
|
yieldError("Invalid token after " & $level.mode)
|
|
|
|
else:
|
|
|
|
yieldError("Invalid token after " & $level.mode)
|
2015-12-11 21:55:21 +00:00
|
|
|
elif level.mode != mUnknown:
|
|
|
|
yieldError("Invalid indentation")
|
|
|
|
elif entering == yamlError:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-11 21:55:21 +00:00
|
|
|
else:
|
|
|
|
level.mode = next
|
|
|
|
level.indicatorColumn = lex.column
|
2015-12-22 21:28:27 +00:00
|
|
|
if emptyScalarOnOpening:
|
2015-12-22 22:35:03 +00:00
|
|
|
# do not consume anchor and tag; they are on the scalar
|
|
|
|
var
|
|
|
|
cachedAnchor = anchor
|
|
|
|
cachedTag = tag
|
|
|
|
anchor = ""
|
|
|
|
tag = ""
|
|
|
|
yieldStart(entering)
|
|
|
|
anchor = cachedAnchor
|
|
|
|
tag = cachedTag
|
2015-12-22 21:28:27 +00:00
|
|
|
yieldScalar("")
|
2015-12-22 22:35:03 +00:00
|
|
|
else:
|
|
|
|
yieldStart(entering)
|
2015-12-11 21:55:21 +00:00
|
|
|
ancestry.add(level)
|
|
|
|
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
|
|
|
indentationColumn: -1)
|
2015-12-07 21:09:57 +00:00
|
|
|
|
2015-12-21 20:40:27 +00:00
|
|
|
template startPlainScalar() {.dirty.} =
|
|
|
|
level.mode = mScalar
|
|
|
|
scalarCache = lex.content
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockAfterScalar
|
2015-12-21 20:40:27 +00:00
|
|
|
|
|
|
|
template handleTagHandle() {.dirty.} =
|
|
|
|
let handle = lex.content
|
|
|
|
if tagShorthands.hasKey(handle):
|
|
|
|
token = nextToken(lex)
|
|
|
|
if finished(nextToken):
|
|
|
|
yieldError("Missing tag suffix")
|
|
|
|
continue
|
2015-12-23 11:35:07 +00:00
|
|
|
if token != tTagSuffix:
|
2015-12-21 20:40:27 +00:00
|
|
|
yieldError("Missing tag suffix")
|
|
|
|
continue
|
|
|
|
tag = tagShorthands[handle] & lex.content
|
2015-12-22 22:35:03 +00:00
|
|
|
if level.indentationColumn == -1 and level.indicatorColumn == -1:
|
|
|
|
level.indentationColumn = lex.column
|
2015-12-21 20:40:27 +00:00
|
|
|
else:
|
|
|
|
yieldError("Unknown tag shorthand: " & handle)
|
|
|
|
|
2015-12-23 11:35:07 +00:00
|
|
|
proc parse*(parser: YamlSequentialParser,
|
|
|
|
s: Stream): iterator(): YamlParserEvent =
|
|
|
|
result = iterator(): YamlParserEvent =
|
2015-12-05 11:10:17 +00:00
|
|
|
var
|
2015-12-14 20:26:34 +00:00
|
|
|
# parsing state
|
2015-12-11 21:55:21 +00:00
|
|
|
lex: YamlLexer
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypInitial
|
2015-12-14 20:26:34 +00:00
|
|
|
|
|
|
|
# document state
|
2015-12-05 11:10:17 +00:00
|
|
|
foundYamlDirective = false
|
|
|
|
tagShorthands = initTable[string, string]()
|
2015-12-14 20:26:34 +00:00
|
|
|
|
|
|
|
# object tree state
|
2015-12-11 21:55:21 +00:00
|
|
|
ancestry = newSeq[DocumentLevel]()
|
|
|
|
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
|
|
|
indentationColumn: -1)
|
2015-12-14 20:26:34 +00:00
|
|
|
|
2015-12-17 20:44:41 +00:00
|
|
|
# block scalar state
|
|
|
|
lineStrip: LineStrippingMode
|
|
|
|
blockScalar: BlockScalarStyle
|
|
|
|
blockScalarIndentation: int
|
|
|
|
blockScalarTrailing: string = nil
|
|
|
|
|
2015-12-14 20:26:34 +00:00
|
|
|
# cached values
|
2015-12-22 15:28:35 +00:00
|
|
|
tag: string = ""
|
|
|
|
anchor: string = ""
|
2015-12-14 20:26:34 +00:00
|
|
|
scalarCache: string = nil
|
|
|
|
scalarIndentation: int
|
2015-12-21 20:40:27 +00:00
|
|
|
scalarCacheIsQuoted: bool = false
|
2015-12-22 15:28:35 +00:00
|
|
|
aliasCache = anchorNone
|
2015-12-14 20:26:34 +00:00
|
|
|
|
2015-12-23 11:35:07 +00:00
|
|
|
lex.open(s)
|
2015-12-21 22:10:42 +00:00
|
|
|
tagShorthands["!"] = "!"
|
|
|
|
tagShorthands["!!"] = "tag:yaml.org,2002:"
|
2015-12-05 11:10:17 +00:00
|
|
|
|
2015-12-07 21:09:57 +00:00
|
|
|
var nextToken = tokens
|
2015-12-05 11:10:17 +00:00
|
|
|
var token = nextToken(lex)
|
2015-12-11 21:55:21 +00:00
|
|
|
block parserLoop:
|
|
|
|
while not finished(nextToken):
|
2015-12-05 11:10:17 +00:00
|
|
|
case state
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypInitial:
|
2015-12-11 21:55:21 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tYamlDirective:
|
2015-12-05 11:10:17 +00:00
|
|
|
if foundYamlDirective:
|
2015-12-11 21:55:21 +00:00
|
|
|
yieldError("Duplicate %YAML directive")
|
|
|
|
var
|
|
|
|
warn = false
|
|
|
|
actualVersion = ""
|
|
|
|
for version in [1, 2]:
|
|
|
|
token = nextToken(lex)
|
|
|
|
if finished(nextToken):
|
|
|
|
yieldError("Missing or badly formatted YAML version")
|
2015-12-23 11:35:07 +00:00
|
|
|
if token != tVersionPart:
|
2015-12-11 21:55:21 +00:00
|
|
|
yieldError("Missing or badly formatted YAML version")
|
|
|
|
if parseInt(lex.content) != version:
|
|
|
|
warn = true
|
|
|
|
if actualVersion.len > 0: actualVersion &= "."
|
|
|
|
actualVersion &= $version
|
|
|
|
if warn:
|
|
|
|
yieldWarning("Unsupported version: " & actualVersion &
|
|
|
|
", trying to parse anyway")
|
|
|
|
foundYamlDirective = true
|
2015-12-23 11:35:07 +00:00
|
|
|
of tTagDirective:
|
2015-12-05 11:10:17 +00:00
|
|
|
token = nextToken(lex)
|
|
|
|
if finished(nextToken):
|
|
|
|
yieldError("Incomplete %TAG directive")
|
2015-12-23 11:35:07 +00:00
|
|
|
if token != tTagHandle:
|
2015-12-05 11:10:17 +00:00
|
|
|
yieldError("Invalid token (expected tag handle)")
|
|
|
|
let tagHandle = lex.content
|
|
|
|
token = nextToken(lex)
|
|
|
|
if finished(nextToken):
|
|
|
|
yieldError("Incomplete %TAG directive")
|
2015-12-23 11:35:07 +00:00
|
|
|
if token != tTagURI:
|
2015-12-05 11:10:17 +00:00
|
|
|
yieldError("Invalid token (expected tag URI)")
|
|
|
|
tagShorthands[tagHandle] = lex.content
|
2015-12-23 11:35:07 +00:00
|
|
|
of tUnknownDirective:
|
2015-12-05 11:10:17 +00:00
|
|
|
yieldWarning("Unknown directive: " & lex.content)
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypSkipDirective
|
|
|
|
of tComment:
|
2015-12-05 11:10:17 +00:00
|
|
|
discard
|
2015-12-23 11:35:07 +00:00
|
|
|
of tDirectivesEnd:
|
2015-12-05 11:10:17 +00:00
|
|
|
yield YamlParserEvent(kind: yamlStartDocument)
|
2015-12-11 21:55:21 +00:00
|
|
|
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
|
|
|
indentationColumn: -1)
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypAfterDirectivesEnd
|
|
|
|
of tDocumentEnd, tStreamEnd:
|
2015-12-05 11:10:17 +00:00
|
|
|
yield YamlParserEvent(kind: yamlStartDocument)
|
2015-12-21 22:10:42 +00:00
|
|
|
yieldDocumentEnd()
|
2015-12-05 11:10:17 +00:00
|
|
|
else:
|
|
|
|
yield YamlParserEvent(kind: yamlStartDocument)
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineStart
|
2015-12-05 11:10:17 +00:00
|
|
|
continue
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypSkipDirective:
|
|
|
|
if token notin [tUnknownDirectiveParam, tTagHandle,
|
|
|
|
tTagURI, tVersionPart, tComment]:
|
|
|
|
state = ypInitial
|
2015-12-05 11:10:17 +00:00
|
|
|
continue
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypAfterDirectivesEnd:
|
2015-12-22 17:51:16 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tTagHandle:
|
2015-12-22 17:51:16 +00:00
|
|
|
handleTagHandle()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineEnd
|
|
|
|
of tComment:
|
|
|
|
state = ypBlockLineEnd
|
|
|
|
of tLineStart:
|
|
|
|
state = ypBlockLineStart
|
2015-12-22 17:51:16 +00:00
|
|
|
else:
|
|
|
|
yieldUnexpectedToken()
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypBlockLineStart:
|
2015-12-11 21:55:21 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tLineStart:
|
2015-12-05 11:10:17 +00:00
|
|
|
discard
|
2015-12-23 11:35:07 +00:00
|
|
|
of tDash:
|
2015-12-22 21:28:27 +00:00
|
|
|
handleBlockIndicator([mBlockSequenceItem], [],
|
|
|
|
mBlockSequenceItem, yamlStartSequence)
|
2015-12-23 11:35:07 +00:00
|
|
|
of tQuestionmark:
|
2015-12-22 20:08:58 +00:00
|
|
|
handleBlockIndicator([mImplicitBlockMapKey, mBlockMapValue],
|
2015-12-22 21:28:27 +00:00
|
|
|
[mExplicitBlockMapKey],
|
2015-12-11 21:55:21 +00:00
|
|
|
mExplicitBlockMapKey, yamlStartMap)
|
2015-12-23 11:35:07 +00:00
|
|
|
of tColon:
|
2015-12-22 20:08:58 +00:00
|
|
|
handleBlockIndicator([mExplicitBlockMapKey],
|
2015-12-22 21:28:27 +00:00
|
|
|
[mBlockMapValue, mImplicitBlockMapKey],
|
|
|
|
mBlockMapValue, yamlStartMap, true)
|
2015-12-23 11:35:07 +00:00
|
|
|
of tPipe, tGreater:
|
|
|
|
blockScalar = if token == tPipe: bsLiteral else: bsFolded
|
2015-12-17 20:44:41 +00:00
|
|
|
blockScalarIndentation = -1
|
|
|
|
lineStrip = lsClip
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockScalarHeader
|
2015-12-17 20:44:41 +00:00
|
|
|
scalarCache = ""
|
|
|
|
level.mode = mScalar
|
2015-12-23 11:35:07 +00:00
|
|
|
of tTagHandle:
|
2015-12-22 22:35:03 +00:00
|
|
|
leaveMoreIndentedLevels()
|
2015-12-21 20:40:27 +00:00
|
|
|
handleTagHandle()
|
2015-12-21 22:10:42 +00:00
|
|
|
level.indentationColumn = lex.column
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockAfterTag
|
|
|
|
of tVerbatimTag:
|
2015-12-11 21:55:21 +00:00
|
|
|
tag = lex.content
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockAfterTag
|
2015-12-21 20:40:27 +00:00
|
|
|
level.indentationColumn = lex.column
|
2015-12-23 11:35:07 +00:00
|
|
|
of tAnchor:
|
2015-12-22 22:35:03 +00:00
|
|
|
leaveMoreIndentedLevels()
|
2015-12-11 21:55:21 +00:00
|
|
|
anchor = lex.content
|
2015-12-21 20:40:27 +00:00
|
|
|
level.indentationColumn = lex.column
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockAfterAnchor
|
|
|
|
of tScalarPart:
|
2015-12-14 20:26:34 +00:00
|
|
|
leaveMoreIndentedLevels()
|
|
|
|
case level.mode
|
|
|
|
of mUnknown:
|
2015-12-21 20:40:27 +00:00
|
|
|
startPlainScalar()
|
|
|
|
level.indentationColumn = lex.column
|
2015-12-14 20:26:34 +00:00
|
|
|
of mImplicitBlockMapKey:
|
|
|
|
scalarCache = lex.content
|
2015-12-21 20:40:27 +00:00
|
|
|
scalarCacheIsQuoted = false
|
2015-12-14 20:26:34 +00:00
|
|
|
scalarIndentation = lex.column
|
2015-12-22 20:08:58 +00:00
|
|
|
of mBlockMapValue:
|
2015-12-14 20:26:34 +00:00
|
|
|
scalarCache = lex.content
|
2015-12-21 20:40:27 +00:00
|
|
|
scalarCacheIsQuoted = false
|
2015-12-14 20:26:34 +00:00
|
|
|
scalarIndentation = lex.column
|
2015-12-22 21:28:27 +00:00
|
|
|
level.mode = mImplicitBlockMapKey
|
|
|
|
of mExplicitBlockMapKey:
|
|
|
|
yieldScalar()
|
|
|
|
level.mode = mBlockMapValue
|
|
|
|
continue
|
2015-12-14 20:26:34 +00:00
|
|
|
else:
|
2015-12-22 21:28:27 +00:00
|
|
|
yieldError("Unexpected scalar in " & $level.mode)
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockAfterScalar
|
|
|
|
of tScalar:
|
2015-12-11 21:55:21 +00:00
|
|
|
leaveMoreIndentedLevels()
|
|
|
|
case level.mode
|
|
|
|
of mUnknown, mImplicitBlockMapKey:
|
2015-12-14 20:26:34 +00:00
|
|
|
scalarCache = lex.content
|
2015-12-21 20:40:27 +00:00
|
|
|
scalarCacheIsQuoted = true
|
2015-12-14 20:26:34 +00:00
|
|
|
scalarIndentation = lex.column
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockAfterScalar
|
2015-12-11 21:55:21 +00:00
|
|
|
else:
|
|
|
|
yieldError("Unexpected scalar")
|
2015-12-23 11:35:07 +00:00
|
|
|
of tAlias:
|
2015-12-22 15:28:35 +00:00
|
|
|
aliasCache = resolveAlias(parser, lex.content)
|
|
|
|
if aliasCache == anchorNone:
|
|
|
|
yieldError("[alias] Unknown anchor: " & lex.content)
|
|
|
|
if ancestry.len > 0:
|
|
|
|
if level.mode == mUnknown:
|
|
|
|
level = ancestry.pop()
|
|
|
|
else:
|
|
|
|
assert level.mode == mImplicitBlockMapKey
|
|
|
|
leaveMoreIndentedLevels()
|
|
|
|
case level.mode
|
|
|
|
of mUnknown, mImplicitBlockMapKey, mBlockSequenceItem:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockAfterAlias
|
2015-12-22 15:28:35 +00:00
|
|
|
else:
|
|
|
|
yieldError("Unexpected alias")
|
2015-12-23 11:35:07 +00:00
|
|
|
of tStreamEnd:
|
2015-12-07 21:09:57 +00:00
|
|
|
closeAllLevels()
|
|
|
|
yield YamlParserEvent(kind: yamlEndDocument)
|
|
|
|
break
|
2015-12-23 11:35:07 +00:00
|
|
|
of tDocumentEnd:
|
2015-12-07 21:09:57 +00:00
|
|
|
closeAllLevels()
|
2015-12-21 22:10:42 +00:00
|
|
|
yieldDocumentEnd()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypInitial
|
|
|
|
of tOpeningBrace:
|
|
|
|
state = ypFlow
|
2015-12-10 21:28:57 +00:00
|
|
|
continue
|
2015-12-23 11:35:07 +00:00
|
|
|
of tOpeningBracket:
|
|
|
|
state = ypFlow
|
2015-12-10 21:28:57 +00:00
|
|
|
continue
|
2015-12-07 21:09:57 +00:00
|
|
|
else:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypBlockMultilineScalar:
|
2015-12-14 20:26:34 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tScalarPart:
|
2015-12-14 20:26:34 +00:00
|
|
|
leaveMoreIndentedLevels()
|
|
|
|
if level.mode != mScalar:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineStart
|
2015-12-14 20:26:34 +00:00
|
|
|
continue
|
|
|
|
scalarCache &= " " & lex.content
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineEnd
|
|
|
|
of tLineStart:
|
2015-12-14 20:26:34 +00:00
|
|
|
discard
|
2015-12-23 11:35:07 +00:00
|
|
|
of tColon, tDash, tQuestionmark:
|
2015-12-14 20:26:34 +00:00
|
|
|
leaveMoreIndentedLevels()
|
|
|
|
if level.mode != mScalar:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineStart
|
2015-12-14 20:26:34 +00:00
|
|
|
continue
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-23 11:35:07 +00:00
|
|
|
of tDocumentEnd, tStreamEnd:
|
2015-12-14 20:26:34 +00:00
|
|
|
closeAllLevels()
|
|
|
|
scalarCache = nil
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypInitial
|
2015-12-14 20:26:34 +00:00
|
|
|
continue
|
2015-12-23 11:35:07 +00:00
|
|
|
of tDirectivesEnd:
|
2015-12-14 20:26:34 +00:00
|
|
|
closeAllLevels()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypAfterDirectivesEnd
|
2015-12-14 20:26:34 +00:00
|
|
|
continue
|
2015-12-23 11:35:07 +00:00
|
|
|
of tAlias:
|
2015-12-22 15:28:35 +00:00
|
|
|
leaveMoreIndentedLevels()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineStart
|
2015-12-22 15:28:35 +00:00
|
|
|
continue
|
2015-12-14 20:26:34 +00:00
|
|
|
else:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypBlockAfterScalar:
|
2015-12-11 21:55:21 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tColon:
|
2015-12-14 20:26:34 +00:00
|
|
|
assert level.mode in [mUnknown, mImplicitBlockMapKey, mScalar]
|
|
|
|
if level.mode in [mUnknown, mScalar]:
|
|
|
|
level.indentationColumn = scalarIndentation
|
2015-12-21 20:40:27 +00:00
|
|
|
# tags and anchors are for key scalar, not for map.
|
|
|
|
yield YamlParserEvent(kind: yamlStartMap,
|
2015-12-22 15:28:35 +00:00
|
|
|
objAnchor: anchorNone,
|
|
|
|
objTag: tagQuestionMark)
|
2015-12-22 20:08:58 +00:00
|
|
|
level.mode = mBlockMapValue
|
2015-12-11 21:55:21 +00:00
|
|
|
ancestry.add(level)
|
|
|
|
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
|
|
|
indentationColumn: -1)
|
2015-12-21 20:40:27 +00:00
|
|
|
yieldScalar(scalarCache, scalarCacheIsQuoted)
|
2015-12-14 20:26:34 +00:00
|
|
|
scalarCache = nil
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockAfterColon
|
|
|
|
of tLineStart:
|
2015-12-11 21:55:21 +00:00
|
|
|
if level.mode == mImplicitBlockMapKey:
|
|
|
|
yieldError("Missing colon after implicit map key")
|
2015-12-14 20:26:34 +00:00
|
|
|
if level.mode != mScalar:
|
2015-12-21 20:40:27 +00:00
|
|
|
yieldScalar(scalarCache, scalarCacheIsQuoted)
|
2015-12-14 20:26:34 +00:00
|
|
|
scalarCache = nil
|
|
|
|
if ancestry.len > 0:
|
|
|
|
level = ancestry.pop()
|
|
|
|
else:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypExpectingDocumentEnd
|
2015-12-11 21:55:21 +00:00
|
|
|
else:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockMultilineScalar
|
|
|
|
of tStreamEnd:
|
2015-12-21 20:40:27 +00:00
|
|
|
yieldScalar(scalarCache, scalarCacheIsQuoted)
|
2015-12-14 20:26:34 +00:00
|
|
|
scalarCache = nil
|
2015-12-11 21:55:21 +00:00
|
|
|
if ancestry.len > 0:
|
|
|
|
level = ancestry.pop()
|
|
|
|
closeAllLevels()
|
2015-12-07 21:09:57 +00:00
|
|
|
yield YamlParserEvent(kind: yamlEndDocument)
|
|
|
|
break
|
|
|
|
else:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypBlockAfterAlias:
|
2015-12-22 15:28:35 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tColon:
|
2015-12-22 15:28:35 +00:00
|
|
|
assert level.mode in [mUnknown, mImplicitBlockMapKey]
|
|
|
|
if level.mode == mUnknown:
|
|
|
|
yield YamlParserEvent(kind: yamlStartMap,
|
|
|
|
objAnchor: anchorNone,
|
|
|
|
objTag: tagQuestionMark)
|
2015-12-22 20:08:58 +00:00
|
|
|
level.mode = mBlockMapValue
|
2015-12-22 15:28:35 +00:00
|
|
|
ancestry.add(level)
|
|
|
|
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
|
|
|
indentationColumn: -1)
|
|
|
|
yield YamlParserEvent(kind: yamlAlias, aliasTarget: aliasCache)
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockAfterColon
|
|
|
|
of tLineStart:
|
2015-12-22 15:28:35 +00:00
|
|
|
if level.mode == mImplicitBlockMapKey:
|
|
|
|
yieldError("Missing colon after implicit map key")
|
|
|
|
if level.mode == mUnknown:
|
|
|
|
assert ancestry.len > 0
|
|
|
|
level = ancestry.pop()
|
|
|
|
yield YamlParserEvent(kind: yamlAlias, aliasTarget: aliasCache)
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineStart
|
|
|
|
of tStreamEnd:
|
2015-12-22 15:28:35 +00:00
|
|
|
yield YamlParserEvent(kind: yamlAlias, aliasTarget: aliasCache)
|
|
|
|
if level.mode == mUnknown:
|
|
|
|
assert ancestry.len > 0
|
|
|
|
level = ancestry.pop()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineEnd
|
2015-12-22 15:28:35 +00:00
|
|
|
continue
|
|
|
|
else:
|
|
|
|
yieldUnexpectedToken()
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypBlockAfterTag:
|
2015-12-22 22:35:03 +00:00
|
|
|
if mustLeaveLevel(lex.column, ancestry):
|
|
|
|
leaveMoreIndentedLevels()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineStart
|
2015-12-22 22:35:03 +00:00
|
|
|
continue
|
2015-12-11 21:55:21 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tAnchor:
|
2015-12-11 21:55:21 +00:00
|
|
|
anchor = lex.content
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockAfterAnchorAndTag
|
|
|
|
of tScalar, tColon, tStreamEnd:
|
|
|
|
state = ypBlockLineStart
|
2015-12-11 21:55:21 +00:00
|
|
|
continue
|
2015-12-23 11:35:07 +00:00
|
|
|
of tScalarPart:
|
2015-12-21 20:40:27 +00:00
|
|
|
startPlainScalar()
|
2015-12-23 11:35:07 +00:00
|
|
|
of tLineStart:
|
|
|
|
state = ypBlockLineStart
|
|
|
|
of tOpeningBracket, tOpeningBrace:
|
|
|
|
state = ypFlow
|
2015-12-11 21:55:21 +00:00
|
|
|
continue
|
|
|
|
else:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypBlockAfterAnchor:
|
2015-12-22 22:35:03 +00:00
|
|
|
if mustLeaveLevel(lex.column, ancestry):
|
|
|
|
leaveMoreIndentedLevels()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineStart
|
2015-12-22 22:35:03 +00:00
|
|
|
continue
|
2015-12-11 21:55:21 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tScalar, tColon, tStreamEnd:
|
|
|
|
state = ypBlockLineStart
|
2015-12-11 21:55:21 +00:00
|
|
|
continue
|
2015-12-23 11:35:07 +00:00
|
|
|
of tScalarPart:
|
2015-12-21 20:40:27 +00:00
|
|
|
startPlainScalar()
|
2015-12-23 11:35:07 +00:00
|
|
|
of tLineStart:
|
2015-12-21 20:40:27 +00:00
|
|
|
discard
|
2015-12-23 11:35:07 +00:00
|
|
|
of tOpeningBracket, tOpeningBrace:
|
|
|
|
state = ypFlow
|
2015-12-21 20:40:27 +00:00
|
|
|
continue
|
2015-12-23 11:35:07 +00:00
|
|
|
of tTagHandle:
|
2015-12-21 20:40:27 +00:00
|
|
|
handleTagHandle()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockAfterAnchorAndTag
|
|
|
|
of tVerbatimTag:
|
2015-12-21 20:40:27 +00:00
|
|
|
tag = lex.content
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockAfterAnchorAndTag
|
2015-12-21 20:40:27 +00:00
|
|
|
level.indentationColumn = lex.column
|
|
|
|
else:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypBlockAfterAnchorAndTag:
|
2015-12-22 22:35:03 +00:00
|
|
|
if mustLeaveLevel(lex.column, ancestry):
|
|
|
|
leaveMoreIndentedLevels()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineStart
|
2015-12-22 22:35:03 +00:00
|
|
|
continue
|
2015-12-21 20:40:27 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tScalar, tColon, tStreamEnd:
|
|
|
|
state = ypBlockLineStart
|
2015-12-21 20:40:27 +00:00
|
|
|
continue
|
2015-12-23 11:35:07 +00:00
|
|
|
of tScalarPart:
|
2015-12-21 20:40:27 +00:00
|
|
|
startPlainScalar()
|
2015-12-23 11:35:07 +00:00
|
|
|
of tLineStart:
|
2015-12-21 20:40:27 +00:00
|
|
|
discard
|
2015-12-23 11:35:07 +00:00
|
|
|
of tOpeningBracket, tOpeningBrace:
|
|
|
|
state = ypFlow
|
2015-12-11 21:55:21 +00:00
|
|
|
continue
|
|
|
|
else:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypBlockAfterColon:
|
2015-12-11 21:55:21 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tScalar:
|
2015-12-21 20:40:27 +00:00
|
|
|
yieldScalar(lex.content, true)
|
2015-12-11 21:55:21 +00:00
|
|
|
level = ancestry.pop()
|
2015-12-22 20:08:58 +00:00
|
|
|
assert level.mode == mBlockMapValue
|
2015-12-11 21:55:21 +00:00
|
|
|
level.mode = mImplicitBlockMapKey
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineEnd
|
|
|
|
of tScalarPart:
|
2015-12-21 20:40:27 +00:00
|
|
|
startPlainScalar()
|
2015-12-23 11:35:07 +00:00
|
|
|
of tLineStart:
|
|
|
|
state = ypBlockLineStart
|
|
|
|
of tStreamEnd:
|
2015-12-07 21:09:57 +00:00
|
|
|
closeAllLevels()
|
|
|
|
yield YamlParserEvent(kind: yamlEndDocument)
|
|
|
|
break
|
2015-12-23 11:35:07 +00:00
|
|
|
of tOpeningBracket, tOpeningBrace:
|
|
|
|
state = ypFlow
|
2015-12-10 21:28:57 +00:00
|
|
|
continue
|
2015-12-23 11:35:07 +00:00
|
|
|
of tPipe, tGreater:
|
|
|
|
blockScalar = if token == tPipe: bsLiteral else: bsFolded
|
2015-12-17 20:44:41 +00:00
|
|
|
blockScalarIndentation = -1
|
|
|
|
lineStrip = lsClip
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockScalarHeader
|
2015-12-17 20:44:41 +00:00
|
|
|
scalarCache = ""
|
|
|
|
level.mode = mScalar
|
2015-12-23 11:35:07 +00:00
|
|
|
of tTagHandle:
|
2015-12-21 22:10:42 +00:00
|
|
|
handleTagHandle()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockAfterTag
|
|
|
|
of tAnchor:
|
2015-12-22 22:35:03 +00:00
|
|
|
level.indentationColumn = lex.column
|
2015-12-21 22:10:42 +00:00
|
|
|
anchor = lex.content
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockAfterAnchor
|
|
|
|
of tAlias:
|
2015-12-22 15:28:35 +00:00
|
|
|
var noAnchor = false
|
|
|
|
try:
|
|
|
|
aliasCache = parser.anchors[lex.content]
|
|
|
|
except KeyError:
|
|
|
|
noAnchor = true
|
|
|
|
if noAnchor:
|
|
|
|
# cannot use yield within try/except, so do it here
|
|
|
|
yieldError("[alias] Unknown anchor: " & lex.content)
|
|
|
|
yield YamlParserEvent(kind: yamlAlias, aliasTarget: aliasCache)
|
|
|
|
level = ancestry.pop()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineEnd
|
2015-12-07 21:09:57 +00:00
|
|
|
else:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken("scalar or line end")
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypBlockLineEnd:
|
2015-12-11 21:55:21 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tLineStart:
|
|
|
|
state = if level.mode == mScalar: ypBlockMultilineScalar else:
|
|
|
|
ypBlockLineStart
|
|
|
|
of tStreamEnd:
|
2015-12-07 21:09:57 +00:00
|
|
|
closeAllLevels()
|
|
|
|
yield YamlParserEvent(kind: yamlEndDocument)
|
|
|
|
break
|
|
|
|
else:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken("line end")
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypBlockScalarHeader:
|
2015-12-17 20:44:41 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tPlus:
|
2015-12-17 20:44:41 +00:00
|
|
|
if lineStrip != lsClip:
|
|
|
|
yieldError("Multiple chomping indicators!")
|
|
|
|
else:
|
|
|
|
lineStrip = lsKeep
|
2015-12-23 11:35:07 +00:00
|
|
|
of tDash:
|
2015-12-17 20:44:41 +00:00
|
|
|
if lineStrip != lsClip:
|
|
|
|
yieldError("Multiple chomping indicators!")
|
|
|
|
else:
|
|
|
|
lineStrip = lsStrip
|
2015-12-23 11:35:07 +00:00
|
|
|
of tBlockIndentationIndicator:
|
2015-12-17 20:44:41 +00:00
|
|
|
if blockScalarIndentation != -1:
|
|
|
|
yieldError("Multiple indentation indicators!")
|
|
|
|
else:
|
|
|
|
blockScalarIndentation = parseInt(lex.content)
|
2015-12-23 11:35:07 +00:00
|
|
|
of tLineStart:
|
2015-12-17 20:44:41 +00:00
|
|
|
blockScalarTrailing = ""
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockScalar
|
2015-12-17 20:44:41 +00:00
|
|
|
else:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypBlockScalar:
|
2015-12-17 20:44:41 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tLineStart:
|
2015-12-17 20:44:41 +00:00
|
|
|
if level.indentationColumn == -1:
|
|
|
|
discard
|
|
|
|
else:
|
|
|
|
case blockScalar
|
|
|
|
of bsLiteral:
|
|
|
|
blockScalarTrailing &= "\x0A"
|
|
|
|
of bsFolded:
|
|
|
|
case blockScalarTrailing.len
|
|
|
|
of 0:
|
|
|
|
blockScalarTrailing = " "
|
|
|
|
of 1:
|
|
|
|
blockScalarTrailing = "\x0A"
|
|
|
|
else:
|
|
|
|
discard
|
|
|
|
|
|
|
|
if lex.content.len > level.indentationColumn:
|
|
|
|
if blockScalar == bsFolded:
|
|
|
|
if blockScalarTrailing == " ":
|
|
|
|
blockScalarTrailing = "\x0A"
|
|
|
|
scalarCache &= blockScalarTrailing &
|
|
|
|
lex.content[level.indentationColumn..^1]
|
|
|
|
blockScalarTrailing = ""
|
|
|
|
|
2015-12-23 11:35:07 +00:00
|
|
|
of tScalarPart:
|
2015-12-17 20:44:41 +00:00
|
|
|
if ancestry.high > 0:
|
|
|
|
if ancestry[ancestry.high].indicatorColumn >= lex.column or
|
|
|
|
ancestry[ancestry.high].indicatorColumn == -1 and
|
|
|
|
ancestry[ancestry.high].indentationColumn >= lex.column:
|
|
|
|
# todo: trailing chomping?
|
|
|
|
closeLevel(level)
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineStart
|
2015-12-17 20:44:41 +00:00
|
|
|
continue
|
|
|
|
if level.indentationColumn == -1:
|
|
|
|
level.indentationColumn = lex.column
|
|
|
|
else:
|
|
|
|
scalarCache &= blockScalarTrailing
|
|
|
|
blockScalarTrailing = ""
|
|
|
|
scalarCache &= lex.content
|
|
|
|
else:
|
|
|
|
case lineStrip
|
|
|
|
of lsStrip:
|
|
|
|
discard
|
|
|
|
of lsClip:
|
|
|
|
scalarCache &= "\x0A"
|
|
|
|
of lsKeep:
|
|
|
|
scalarCache &= blockScalarTrailing
|
|
|
|
closeLevel(level)
|
|
|
|
if ancestry.len == 0:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypExpectingDocumentEnd
|
2015-12-17 20:44:41 +00:00
|
|
|
else:
|
|
|
|
level = ancestry.pop()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineStart
|
2015-12-17 20:44:41 +00:00
|
|
|
continue
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypFlow:
|
2015-12-11 21:55:21 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tLineStart:
|
2015-12-10 21:28:57 +00:00
|
|
|
discard
|
2015-12-23 11:35:07 +00:00
|
|
|
of tScalar, tScalarPart:
|
|
|
|
yieldScalar(lex.content, token == tScalar)
|
2015-12-11 21:55:21 +00:00
|
|
|
level = ancestry.pop()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypFlowAfterObject
|
|
|
|
of tColon:
|
2015-12-11 21:55:21 +00:00
|
|
|
yieldScalar()
|
|
|
|
level = ancestry.pop()
|
|
|
|
if level.mode == mFlowMapKey:
|
|
|
|
level.mode = mFlowMapValue
|
|
|
|
ancestry.add(level)
|
|
|
|
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
|
|
|
indentationColumn: -1)
|
|
|
|
else:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken("scalar, comma or map end")
|
2015-12-23 11:35:07 +00:00
|
|
|
of tComma:
|
2015-12-11 21:55:21 +00:00
|
|
|
yieldScalar()
|
|
|
|
level = ancestry.pop()
|
|
|
|
case level.mode
|
|
|
|
of mFlowMapValue:
|
|
|
|
level.mode = mFlowMapKey
|
|
|
|
ancestry.add(level)
|
|
|
|
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
|
|
|
indentationColumn: -1)
|
|
|
|
of mFlowSequenceItem:
|
|
|
|
yieldScalar()
|
|
|
|
else:
|
2015-12-10 21:28:57 +00:00
|
|
|
yieldError("Internal error! Please report this bug.")
|
2015-12-23 11:35:07 +00:00
|
|
|
of tOpeningBrace:
|
2015-12-11 21:55:21 +00:00
|
|
|
if level.mode != mUnknown:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-11 21:55:21 +00:00
|
|
|
level.mode = mFlowMapKey
|
|
|
|
yieldStart(yamlStartMap)
|
|
|
|
ancestry.add(level)
|
|
|
|
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
|
|
|
indentationColumn: -1)
|
2015-12-23 11:35:07 +00:00
|
|
|
of tOpeningBracket:
|
2015-12-11 21:55:21 +00:00
|
|
|
if level.mode != mUnknown:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-11 21:55:21 +00:00
|
|
|
level.mode = mFlowSequenceItem
|
|
|
|
yieldStart(yamlStartSequence)
|
|
|
|
ancestry.add(level)
|
|
|
|
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
|
|
|
indentationColumn: -1)
|
2015-12-23 11:35:07 +00:00
|
|
|
of tClosingBrace:
|
2015-12-11 21:55:21 +00:00
|
|
|
if level.mode == mUnknown:
|
|
|
|
yieldScalar()
|
|
|
|
level = ancestry.pop()
|
|
|
|
if level.mode != mFlowMapValue:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-11 21:55:21 +00:00
|
|
|
yield YamlParserEvent(kind: yamlEndMap)
|
|
|
|
if ancestry.len > 0:
|
|
|
|
level = ancestry.pop()
|
|
|
|
case level.mode
|
|
|
|
of mFlowMapKey, mFlowMapValue, mFlowSequenceItem:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypFlowAfterObject
|
2015-12-11 21:55:21 +00:00
|
|
|
else:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineEnd
|
2015-12-11 21:55:21 +00:00
|
|
|
else:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypExpectingDocumentEnd
|
|
|
|
of tClosingBracket:
|
2015-12-11 21:55:21 +00:00
|
|
|
if level.mode == mUnknown:
|
|
|
|
yieldScalar()
|
|
|
|
level = ancestry.pop()
|
|
|
|
if level.mode != mFlowSequenceItem:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-10 21:28:57 +00:00
|
|
|
else:
|
|
|
|
yield YamlParserEvent(kind: yamlEndSequence)
|
2015-12-11 21:55:21 +00:00
|
|
|
if ancestry.len > 0:
|
|
|
|
level = ancestry.pop()
|
|
|
|
case level.mode
|
|
|
|
of mFlowMapKey, mFlowMapValue, mFlowSequenceItem:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypFlowAfterObject
|
2015-12-11 21:55:21 +00:00
|
|
|
else:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineEnd
|
2015-12-10 21:28:57 +00:00
|
|
|
else:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypExpectingDocumentEnd
|
|
|
|
of tTagHandle:
|
2015-12-21 22:10:42 +00:00
|
|
|
handleTagHandle()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypFlowAfterTag
|
|
|
|
of tAnchor:
|
2015-12-21 22:10:42 +00:00
|
|
|
anchor = lex.content
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypFlowAfterAnchor
|
|
|
|
of tAlias:
|
2015-12-22 15:28:35 +00:00
|
|
|
yield YamlParserEvent(kind: yamlAlias,
|
|
|
|
aliasTarget: resolveAlias(parser, lex.content))
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypFlowAfterObject
|
2015-12-22 15:28:35 +00:00
|
|
|
level = ancestry.pop()
|
2015-12-10 21:28:57 +00:00
|
|
|
else:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypFlowAfterTag:
|
2015-12-21 22:10:42 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tTagHandle:
|
2015-12-21 22:10:42 +00:00
|
|
|
yieldError("Multiple tags on same node!")
|
2015-12-23 11:35:07 +00:00
|
|
|
of tAnchor:
|
2015-12-21 22:10:42 +00:00
|
|
|
anchor = lex.content
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypFlowAfterAnchorAndTag
|
2015-12-21 22:10:42 +00:00
|
|
|
else:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypFlow
|
2015-12-21 22:10:42 +00:00
|
|
|
continue
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypFlowAfterAnchor:
|
2015-12-21 22:10:42 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tAnchor:
|
2015-12-21 22:10:42 +00:00
|
|
|
yieldError("Multiple anchors on same node!")
|
2015-12-23 11:35:07 +00:00
|
|
|
of tTagHandle:
|
2015-12-21 22:10:42 +00:00
|
|
|
handleTagHandle()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypFlowAfterAnchorAndTag
|
2015-12-21 22:10:42 +00:00
|
|
|
else:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypFlow
|
2015-12-21 22:10:42 +00:00
|
|
|
continue
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypFlowAfterAnchorAndTag:
|
2015-12-21 22:10:42 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tAnchor:
|
2015-12-21 22:10:42 +00:00
|
|
|
yieldError("Multiple anchors on same node!")
|
2015-12-23 11:35:07 +00:00
|
|
|
of tTagHandle:
|
2015-12-21 22:10:42 +00:00
|
|
|
yieldError("Multiple tags on same node!")
|
|
|
|
else:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypFlow
|
2015-12-21 22:10:42 +00:00
|
|
|
continue
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypFlowAfterObject:
|
2015-12-11 21:55:21 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tLineStart:
|
2015-12-10 21:28:57 +00:00
|
|
|
discard
|
2015-12-23 11:35:07 +00:00
|
|
|
of tColon:
|
2015-12-11 21:55:21 +00:00
|
|
|
if level.mode != mFlowMapKey:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-10 21:28:57 +00:00
|
|
|
else:
|
2015-12-11 21:55:21 +00:00
|
|
|
level.mode = mFlowMapValue
|
|
|
|
ancestry.add(level)
|
|
|
|
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
|
|
|
indentationColumn: -1)
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypFlow
|
|
|
|
of tComma:
|
2015-12-11 21:55:21 +00:00
|
|
|
case level.mode
|
|
|
|
of mFlowSequenceItem:
|
|
|
|
ancestry.add(level)
|
|
|
|
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
|
|
|
indentationColumn: -1)
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypFlow
|
2015-12-11 21:55:21 +00:00
|
|
|
of mFlowMapValue:
|
|
|
|
level.mode = mFlowMapKey
|
|
|
|
ancestry.add(level)
|
|
|
|
level = DocumentLevel(mode: mUnknown, indicatorColumn: -1,
|
|
|
|
indentationColumn: -1)
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypFlow
|
2015-12-10 21:28:57 +00:00
|
|
|
else:
|
2015-12-22 15:28:35 +00:00
|
|
|
echo "level.mode = ", level.mode
|
|
|
|
yieldUnexpectedToken()
|
2015-12-23 11:35:07 +00:00
|
|
|
of tClosingBrace:
|
2015-12-11 21:55:21 +00:00
|
|
|
if level.mode != mFlowMapValue:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-10 21:28:57 +00:00
|
|
|
else:
|
|
|
|
yield YamlParserEvent(kind: yamlEndMap)
|
2015-12-11 21:55:21 +00:00
|
|
|
if ancestry.len > 0:
|
|
|
|
level = ancestry.pop()
|
|
|
|
case level.mode
|
|
|
|
of mFlowMapKey, mFlowMapValue, mFlowSequenceItem:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypFlowAfterObject
|
2015-12-11 21:55:21 +00:00
|
|
|
else:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineEnd
|
2015-12-11 21:55:21 +00:00
|
|
|
else:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypExpectingDocumentEnd
|
|
|
|
of tClosingBracket:
|
2015-12-11 21:55:21 +00:00
|
|
|
if level.mode != mFlowSequenceItem:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-10 21:28:57 +00:00
|
|
|
else:
|
|
|
|
yield YamlParserEvent(kind: yamlEndSequence)
|
2015-12-11 21:55:21 +00:00
|
|
|
if ancestry.len > 0:
|
|
|
|
level = ancestry.pop()
|
|
|
|
case level.mode
|
|
|
|
of mFlowMapKey, mFlowMapValue, mFlowSequenceItem:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypFlowAfterObject
|
2015-12-11 21:55:21 +00:00
|
|
|
else:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypBlockLineEnd
|
2015-12-11 21:55:21 +00:00
|
|
|
else:
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypExpectingDocumentEnd
|
2015-12-11 21:55:21 +00:00
|
|
|
else:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken()
|
2015-12-23 11:35:07 +00:00
|
|
|
of ypExpectingDocumentEnd:
|
2015-12-11 21:55:21 +00:00
|
|
|
case token
|
2015-12-23 11:35:07 +00:00
|
|
|
of tComment, tLineStart:
|
2015-12-11 21:55:21 +00:00
|
|
|
discard
|
2015-12-23 11:35:07 +00:00
|
|
|
of tStreamEnd, tDocumentEnd:
|
2015-12-21 22:10:42 +00:00
|
|
|
yieldDocumentEnd()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypInitial
|
|
|
|
of tDirectivesEnd:
|
2015-12-21 22:10:42 +00:00
|
|
|
yieldDocumentEnd()
|
2015-12-23 11:35:07 +00:00
|
|
|
state = ypAfterDirectivesEnd
|
2015-12-11 21:55:21 +00:00
|
|
|
continue
|
2015-12-10 21:28:57 +00:00
|
|
|
else:
|
2015-12-22 15:28:35 +00:00
|
|
|
yieldUnexpectedToken("document end")
|
2015-12-05 11:10:17 +00:00
|
|
|
token = nextToken(lex)
|