parseutils

This module contains helpers for parsing tokens, numbers, integers, floats, identifiers, etc.

To unpack raw bytes look at the streams module.

import parseutils

let logs = @["2019-01-10: OK_", "2019-01-11: FAIL_", "2019-01: aaaa"]

for log in logs:
  var res: string
  if parseUntil(log, res, ':') == 10: # YYYY-MM-DD == 10
    echo res & " - " & captureBetween(log, ' ', '_')
    # => 2019-01-10 - OK
import parseutils
from strutils import Digits, parseInt

let userInput1 = "2019 school start"
let userInput2 = "3 years back"

let startYear = input1[0..skipWhile(input1, Digits)-1] # 2019
let yearsBack = input2[0..skipWhile(input2, Digits)-1] # 3

echo "Examination is in " & $(parseInt(startYear) + parseInt(yearsBack))

See also:

Types

InterpolatedKind = enum
  ikStr,                      ## ``str`` part of the interpolated string
  ikDollar,                   ## escaped ``$`` part of the interpolated string
  ikVar,                      ## ``var`` part of the interpolated string
  ikExpr                      ## ``expr`` part of the interpolated string
Describes for interpolatedFragments which part of the interpolated string is yielded; for example in "str$$$var${expr}"   Source Edit

Procs

proc parseHex(s: string; number: var int; start = 0; maxLen = 0): int {...}{.gcsafe,
    extern: "npuParseHex", noSideEffect, raises: [], tags: [].}

Parses a hexadecimal number and stores its value in number.

Returns the number of the parsed characters or 0 in case of an error. This proc is sensitive to the already existing value of number and will likely not do what you want unless you make sure number is zero. You can use this feature to chain calls, though the result int will quickly overflow.

If maxLen == 0 the length of the hexadecimal number has no upper bound. Else no more than start + maxLen characters are parsed, up to the length of the string.

Examples:

var value = 0
discard parseHex("0x38", value)
assert value == 56
discard parseHex("0x34", value)
assert value == 56 * 256 + 52
value = -1
discard parseHex("0x38", value)
assert value == -200
  Source Edit
proc parseOct(s: string; number: var int; start = 0; maxLen = 0): int {...}{.gcsafe,
    extern: "npuParseOct", noSideEffect, raises: [], tags: [].}

Parses an octal number and stores its value in number. Returns the number of the parsed characters or 0 in case of an error.

If maxLen == 0 the length of the octal number has no upper bound. Else no more than start + maxLen characters are parsed, up to the length of the string.

Examples:

var res: int
doAssert parseOct("12", res) == 2
doAssert res == 10
doAssert parseOct("9", res) == 0
  Source Edit
proc parseBin(s: string; number: var int; start = 0; maxLen = 0): int {...}{.gcsafe,
    extern: "npuParseBin", noSideEffect, raises: [], tags: [].}

Parses an binary number and stores its value in number. Returns the number of the parsed characters or 0 in case of an error.

If maxLen == 0 the length of the binary number has no upper bound. Else no more than start + maxLen characters are parsed, up to the length of the string.

Examples:

var res: int
doAssert parseBin("010011100110100101101101", res) == 24
doAssert parseBin("3", res) == 0
  Source Edit
proc parseIdent(s: string; ident: var string; start = 0): int {...}{.raises: [], tags: [].}
Parses an identifier and stores it in ident. Returns the number of the parsed characters or 0 in case of an error.

Examples:

var res: string
doAssert parseIdent("Hello World", res, 0) == 5
doAssert res == "Hello"
doAssert parseIdent("Hello World", res, 1) == 4
doAssert res == "ello"
doAssert parseIdent("Hello World", res, 6) == 5
doAssert res == "World"
  Source Edit
proc parseIdent(s: string; start = 0): string {...}{.raises: [], tags: [].}
Parses an identifier and returns it or an empty string in case of an error.

Examples:

doAssert parseIdent("Hello World", 0) == "Hello"
doAssert parseIdent("Hello World", 1) == "ello"
doAssert parseIdent("Hello World", 5) == ""
doAssert parseIdent("Hello World", 6) == "World"
  Source Edit
proc skipWhitespace(s: string; start = 0): int {...}{.inline, raises: [], tags: [].}
Skips the whitespace starting at s[start]. Returns the number of skipped characters.

Examples:

doAssert skipWhitespace("Hello World", 0) == 0
doAssert skipWhitespace(" Hello World", 0) == 1
doAssert skipWhitespace("Hello World", 5) == 1
doAssert skipWhitespace("Hello  World", 5) == 2
  Source Edit
proc skip(s, token: string; start = 0): int {...}{.inline, raises: [], tags: [].}
Skips the token starting at s[start]. Returns the length of token or 0 if there was no token at s[start].

Examples:

doAssert skip("2019-01-22", "2019", 0) == 4
doAssert skip("2019-01-22", "19", 0) == 0
doAssert skip("2019-01-22", "19", 2) == 2
doAssert skip("CAPlow", "CAP", 0) == 3
doAssert skip("CAPlow", "cap", 0) == 0
  Source Edit
proc skipIgnoreCase(s, token: string; start = 0): int {...}{.raises: [], tags: [].}
Same as skip but case is ignored for token matching.

Examples:

doAssert skipIgnoreCase("CAPlow", "CAP", 0) == 3
doAssert skipIgnoreCase("CAPlow", "cap", 0) == 3
  Source Edit
proc skipUntil(s: string; until: set[char]; start = 0): int {...}{.inline, raises: [], tags: [].}
Skips all characters until one char from the set until is found or the end is reached. Returns number of characters skipped.

Examples:

doAssert skipUntil("Hello World", {'W', 'e'}, 0) == 1
doAssert skipUntil("Hello World", {'W'}, 0) == 6
doAssert skipUntil("Hello World", {'W', 'd'}, 0) == 6
  Source Edit
proc skipUntil(s: string; until: char; start = 0): int {...}{.inline, raises: [], tags: [].}
Skips all characters until the char until is found or the end is reached. Returns number of characters skipped.

Examples:

doAssert skipUntil("Hello World", 'o', 0) == 4
doAssert skipUntil("Hello World", 'o', 4) == 0
doAssert skipUntil("Hello World", 'W', 0) == 6
doAssert skipUntil("Hello World", 'w', 0) == 11
  Source Edit
proc skipWhile(s: string; toSkip: set[char]; start = 0): int {...}{.inline, raises: [], tags: [].}
Skips all characters while one char from the set token is found. Returns number of characters skipped.

Examples:

doAssert skipWhile("Hello World", {'H', 'e'}) == 2
doAssert skipWhile("Hello World", {'e'}) == 0
doAssert skipWhile("Hello World", {'W', 'o', 'r'}, 6) == 3
  Source Edit
proc parseUntil(s: string; token: var string; until: set[char]; start = 0): int {...}{.inline,
    raises: [], tags: [].}
Parses a token and stores it in token. Returns the number of the parsed characters or 0 in case of an error. A token consists of the characters notin until.

Examples:

var myToken: string
doAssert parseUntil("Hello World", myToken, {'W', 'o', 'r'}) == 4
doAssert myToken == "Hell"
doAssert parseUntil("Hello World", myToken, {'W', 'r'}) == 6
doAssert myToken == "Hello "
doAssert parseUntil("Hello World", myToken, {'W', 'r'}, 3) == 3
doAssert myToken == "lo "
  Source Edit
proc parseUntil(s: string; token: var string; until: char; start = 0): int {...}{.inline,
    raises: [], tags: [].}
Parses a token and stores it in token. Returns the number of the parsed characters or 0 in case of an error. A token consists of any character that is not the until character.

Examples:

var myToken: string
doAssert parseUntil("Hello World", myToken, 'W') == 6
doAssert myToken == "Hello "
doAssert parseUntil("Hello World", myToken, 'o') == 4
doAssert myToken == "Hell"
doAssert parseUntil("Hello World", myToken, 'o', 2) == 2
doAssert myToken == "ll"
  Source Edit
proc parseUntil(s: string; token: var string; until: string; start = 0): int {...}{.inline,
    raises: [], tags: [].}
Parses a token and stores it in token. Returns the number of the parsed characters or 0 in case of an error. A token consists of any character that comes before the until token.

Examples:

var myToken: string
doAssert parseUntil("Hello World", myToken, "Wor") == 6
doAssert myToken == "Hello "
doAssert parseUntil("Hello World", myToken, "Wor", 2) == 4
doAssert myToken == "llo "
  Source Edit
proc parseWhile(s: string; token: var string; validChars: set[char]; start = 0): int {...}{.
    inline, raises: [], tags: [].}
Parses a token and stores it in token. Returns the number of the parsed characters or 0 in case of an error. A token consists of the characters in validChars.

Examples:

var myToken: string
doAssert parseWhile("Hello World", myToken, {'W', 'o', 'r'}, 0) == 0
doAssert myToken.len() == 0
doAssert parseWhile("Hello World", myToken, {'W', 'o', 'r'}, 6) == 3
doAssert myToken == "Wor"
  Source Edit
proc captureBetween(s: string; first: char; second = '\x00'; start = 0): string {...}{.
    raises: [], tags: [].}
Finds the first occurrence of first, then returns everything from there up to second (if second is '0', then first is used).

Examples:

doAssert captureBetween("Hello World", 'e') == "llo World"
doAssert captureBetween("Hello World", 'e', 'r') == "llo Wo"
doAssert captureBetween("Hello World", 'l', start = 6) == "d"
  Source Edit
proc parseBiggestInt(s: string; number: var BiggestInt; start = 0): int {...}{.gcsafe,
    extern: "npuParseBiggestInt", noSideEffect, raises: [ValueError], tags: [].}
Parses an integer starting at start and stores the value into number. Result is the number of processed chars or 0 if there is no integer. ValueError is raised if the parsed integer is out of the valid range.

Examples:

var res: BiggestInt
doAssert parseBiggestInt("9223372036854775807", res, 0) == 19
doAssert res == 9223372036854775807'i64
  Source Edit
proc parseInt(s: string; number: var int; start = 0): int {...}{.gcsafe, extern: "npuParseInt",
    noSideEffect, raises: [ValueError], tags: [].}
Parses an integer starting at start and stores the value into number. Result is the number of processed chars or 0 if there is no integer. ValueError is raised if the parsed integer is out of the valid range.

Examples:

var res: int
doAssert parseInt("2019", res, 0) == 4
doAssert res == 2019
doAssert parseInt("2019", res, 2) == 2
doAssert res == 19
  Source Edit
proc parseSaturatedNatural(s: string; b: var int; start = 0): int {...}{.raises: [], tags: [].}
Parses a natural number into b. This cannot raise an overflow error. high(int) is returned for an overflow. The number of processed character is returned. This is usually what you really want to use instead of parseInt.

Examples:

var res = 0
discard parseSaturatedNatural("848", res)
doAssert res == 848
  Source Edit
proc parseBiggestUInt(s: string; number: var BiggestUInt; start = 0): int {...}{.gcsafe,
    extern: "npuParseBiggestUInt", noSideEffect, raises: [ValueError], tags: [].}
Parses an unsigned integer starting at start and stores the value into number. ValueError is raised if the parsed integer is out of the valid range.

Examples:

var res: BiggestUInt
doAssert parseBiggestUInt("12", res, 0) == 2
doAssert res == 12
doAssert parseBiggestUInt("1111111111111111111", res, 0) == 19
doAssert res == 1111111111111111111'u64
  Source Edit
proc parseUInt(s: string; number: var uint; start = 0): int {...}{.gcsafe,
    extern: "npuParseUInt", noSideEffect, raises: [ValueError], tags: [].}
Parses an unsigned integer starting at start and stores the value into number. ValueError is raised if the parsed integer is out of the valid range.

Examples:

var res: uint
doAssert parseUInt("3450", res) == 4
doAssert res == 3450
doAssert parseUInt("3450", res, 2) == 2
doAssert res == 50
  Source Edit
proc parseBiggestFloat(s: string; number: var BiggestFloat; start = 0): int {...}{.
    magic: "ParseBiggestFloat", importc: "nimParseBiggestFloat", noSideEffect.}
Parses a float starting at start and stores the value into number. Result is the number of processed chars or 0 if a parsing error occurred.   Source Edit
proc parseFloat(s: string; number: var float; start = 0): int {...}{.gcsafe,
    extern: "npuParseFloat", noSideEffect, raises: [], tags: [].}
Parses a float starting at start and stores the value into number. Result is the number of processed chars or 0 if there occurred a parsing error.

Examples:

var res: float
doAssert parseFloat("32", res, 0) == 2
doAssert res == 32.0
doAssert parseFloat("32.57", res, 0) == 5
doAssert res == 32.57
doAssert parseFloat("32.57", res, 3) == 2
doAssert res == 57.0
  Source Edit

Iterators

iterator interpolatedFragments(s: string): tuple[kind: InterpolatedKind,
    value: string] {...}{.raises: [ValueError], tags: [].}

Tokenizes the string s into substrings for interpolation purposes.

Example:

for k, v in interpolatedFragments("  $this is ${an  example}  $$"):
  echo "(", k, ", \"", v, "\")"

Results in:

(ikString, "  ")
(ikExpr, "this")
(ikString, " is ")
(ikExpr, "an  example")
(ikString, "  ")
(ikDollar, "$")
  Source Edit