diff --git a/private/lex.nim b/private/lex.nim index eea2a65..79dcea6 100644 --- a/private/lex.nim +++ b/private/lex.nim @@ -181,6 +181,8 @@ proc plainScalarPart[T](lex: YamlLexer): bool proc blockScalarHeader[T](lex: YamlLexer): bool proc blockScalar[T](lex: YamlLexer): bool proc tagHandle[T](lex: YamlLexer): bool +proc anchor[T](lex: YamlLexer): bool +proc alias[T](lex: YamlLexer): bool proc streamEnd(lex: YamlLexer): bool # implementation @@ -589,6 +591,15 @@ proc insideLine[T](lex: YamlLexer): bool = of '!': lex.nextState = tagHandle[T] result = false + of '&': + lex.nextState = anchor[T] + result = false + of '*': + lex.nextState = alias[T] + result = false + of '@', '`': + raise generateError[T](lex, + "Reserved characters cannot start a plain scalar") else: lex.nextState = plainScalarPart[T] result = false @@ -758,6 +769,29 @@ proc tagHandle[T](lex: YamlLexer): bool = else: lex.nextState = insideLine[T] result = true +proc anchorName[T](lex: YamlLexer) = + debug("lex: anchorName") + while true: + lex.advance(T) + case lex.c + of spaceOrLineEnd, '[', ']', '{', '}', ',': break + else: lex.buf.add(lex.c) + while lex.c in space: lex.advance(T) + if lex.c in lineEnd: lex.nextState = expectLineEnd[T] + else: lex.nextState = insideLine[T] + +proc anchor[T](lex: YamlLexer): bool = + debug("lex: anchor") + anchorName[T](lex) + lex.cur = ltAnchor + result = true + +proc alias[T](lex: YamlLexer): bool = + debug("lex: alias") + anchorName[T](lex) + lex.cur = ltAlias + result = true + proc streamEnd(lex: YamlLexer): bool = debug("lex: streamEnd") lex.cur = ltStreamEnd diff --git a/test/tlex.nim b/test/tlex.nim index cc5492b..3c98819 100644 --- a/test/tlex.nim +++ b/test/tlex.nim @@ -4,7 +4,8 @@ import unittest, strutils const tokensWithValue = {ltScalarPart, ltQuotedScalar, ltYamlVersion, ltTagShorthand, ltTagUri, - ltUnknownDirective, ltUnknownDirectiveParams, ltLiteralTag} + ltUnknownDirective, ltUnknownDirectiveParams, ltLiteralTag, ltAnchor, + ltAlias} type TokenWithValue = object @@ -125,6 +126,8 @@ proc th(handle, suffix: string): TokenWithValue = TokenWithValue(kind: ltTagHandle, handle: handle, suffix: suffix) proc lt(v: string): TokenWithValue = TokenWithValue(kind: ltLiteralTag, value: v) +proc an(v: string): TokenWithValue = TokenWithValue(kind: ltAnchor, value: v) +proc al(v: string): TokenWithValue = TokenWithValue(kind: ltAlias, value: v) suite "Lexer": test "Empty document": @@ -202,4 +205,9 @@ suite "Lexer": test "Literal tag handle": assertEquals("! string", i(0), - lt("tag:yaml.org,2002:str"), sp("string"), se()) \ No newline at end of file + lt("tag:yaml.org,2002:str"), sp("string"), se()) + + test "Anchors and aliases": + assertEquals("&a foo: {&b b: *a, *b : c}", i(0), an("a"), sp("foo"), mv(), + oo(), an("b"), sp("b"), mv(), al("a"), c(), al("b"), mv(), sp("c"), + oc(), se()) \ No newline at end of file