diff options
author | Araq <rumpf_a@web.de> | 2011-09-20 12:13:24 -0700 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-09-20 12:13:24 -0700 |
commit | 57f184cf48a0b522001ab20e2c742d4d6436e14d (patch) | |
tree | 6799fff3c4f1676548b93b537c8d814acec8eded /lib/pure | |
parent | bf386374020663452bfdbe3169845970d948cba6 (diff) | |
parent | 9acfc43119d42d7265497fd6ae60eda3903d9938 (diff) | |
download | Nim-57f184cf48a0b522001ab20e2c742d4d6436e14d.tar.gz |
Merge pull request #54 from zah/pretty-print-ast
String interpolation implemented in terms of macros
Diffstat (limited to 'lib/pure')
-rwxr-xr-x | lib/pure/parseutils.nim | 102 | ||||
-rw-r--r-- | lib/pure/uuid.nim | 30 |
2 files changed, 132 insertions, 0 deletions
diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim index d3346ecde..1f4e54b96 100755 --- a/lib/pure/parseutils.nim +++ b/lib/pure/parseutils.nim @@ -76,6 +76,18 @@ proc parseIdent*(s: string, ident: var string, start = 0): int = ident = substr(s, start, i-1) result = i-start +proc parseIdent*(s: string, start = 0): string = + ## parses an identifier and stores it in ``ident``. + ## Returns the parsed identifier or an empty string in case of an error. + result = "" + var i = start + + if s[i] in IdentStartChars: + inc(i) + while s[i] in IdentChars: inc(i) + + result = substr(s, start, i-1) + proc parseToken*(s: string, token: var string, validChars: set[char], start = 0): int {.inline, deprecated.} = ## parses a token and stores it in ``token``. Returns @@ -254,4 +266,94 @@ proc parseFloat*(s: string, number: var float, start = 0): int {. result = parseBiggestFloat(s, bf, start) number = bf +proc isEscaped*(s: string, pos: int) : bool = + assert pos >= 0 and pos < s.len + + var + backslashes = 0 + j = pos - 1 + + while j >= 0: + if s[j] == '\\': + inc backslashes + dec j + else: + break + + return backslashes mod 2 != 0 + +type + TInterpolatedKind* = enum + ikString, ikExpr + + TInterpStrFragment* = tuple[kind: TInterpolatedKind, value: string] + +iterator interpolatedFragments*(s: string): TInterpStrFragment = + var + i = 0 + tokenStart = 0 + + proc token(kind: TInterpolatedKind, value: string): TInterpStrFragment = + result.kind = kind + result.value = value + + while i < s.len: + # The $ sign marks the start of an interpolation. + # + # It's followed either by a varialbe name or an opening bracket + # (so it should be before the end of the string) + # if the dollar sign is escaped, don't trigger interpolation + if s[i] == '$' and i < (s.len - 1) and not isEscaped(s, i): + # Interpolation starts here. + # Return any string that we've ran over so far. + if i != tokenStart: + yield token(ikString, s[tokenStart..i-1]) + + var next = s[i+1] + if next == '{': + # Complex expression: ${foo(bar) in {1..100}} + # Find closing braket, while respecting any nested brackets + inc i + tokenStart = i + 1 + + var + brackets = {'{', '}'} + nestingCount = 1 + + while i < s.len: + inc i, skipUntil(s, brackets, i+1) + 1 + + if not isEscaped(s, i): + if s[i] == '}': + dec nestingCount + if nestingCount == 0: break + else: + inc nestingCount + + yield token(ikExpr, s[tokenStart..(i-1)]) + + tokenStart = i + 1 + + else: + tokenStart = i + 1 + var identifier = parseIdent(s, i+1) + + if identifier.len > 0: + inc i, identifier.len + + yield token(ikExpr, s[tokenStart..i]) + + tokenStart = i + 1 + + else: + raise newException(EInvalidValue, "Unable to parse a varible name at " & s[i..s.len]) + + inc i + #end while + + # We've reached the end of the string without finding a new interpolation. + # Return the last fragment at string. + if i != tokenStart: + yield token(ikString, s[tokenStart..i]) + {.pop.} diff --git a/lib/pure/uuid.nim b/lib/pure/uuid.nim new file mode 100644 index 000000000..36fa9e445 --- /dev/null +++ b/lib/pure/uuid.nim @@ -0,0 +1,30 @@ +# This module implements the RFC 4122 specification for generating universally unique identifiers +# http://en.wikipedia.org/wiki/Universally_unique_identifier + +# This module is a work-in-progress +# If you want to help with the implementation, take a loot at: +# http://dsource.org/projects/tango/docs/current/tango.util.uuid.Uuid.html + +type TUuid* = array[0..15, char] + +when defined(windows): + # This is actually available only on Windows 2000+ + type PUuid* {.importc: "UUID __RPC_FAR *", header: "<Rpc.h>".} = ptr TUuid + proc uuid1Sys*(uuid: PUuid) {.importc: "UuidCreateSequential", header: "<Rpc.h>".} + +else: + type PUuid {.importc: "uuid_t", header: "<uuid/uuid.h>".} = ptr TUuid + proc uuid1Sys*(uuid: PUuid) {.importc: "uuid_generate_time", header: "<uuid/uuid.h>".} + +# v1 UUIDs include the MAC address of the machine generating the ID and a timestamp +# This scheme has the strongest guaranty of uniqueness, but discloses when the ID was generated +proc uuidMacTime* : TUuid = uuid1Sys(addr(result)) + +# v4 UUID are created entirely using a random number generator. +# Some bits have fixed value in order to indicate the UUID type +proc uuidRandom*[RandomGenerator](rand: RandomGenerator) : TUuid = nil + +# v3 and v5 UUIDs are derived from given namespace and name using a secure hashing algorithm. +# v3 uses MD5, v5 uses SHA1. +proc uuidByName*[Hash](namespace: TUuid, name: string, hasher: Hash, v: int) : TUuid = nil + |