summary refs log tree commit diff stats
path: root/lib/pure
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-09-20 12:13:24 -0700
committerAraq <rumpf_a@web.de>2011-09-20 12:13:24 -0700
commit57f184cf48a0b522001ab20e2c742d4d6436e14d (patch)
tree6799fff3c4f1676548b93b537c8d814acec8eded /lib/pure
parentbf386374020663452bfdbe3169845970d948cba6 (diff)
parent9acfc43119d42d7265497fd6ae60eda3903d9938 (diff)
downloadNim-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-xlib/pure/parseutils.nim102
-rw-r--r--lib/pure/uuid.nim30
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
+