NimYAML/private/hints.nim

165 lines
5.0 KiB
Nim
Raw Normal View History

# NimYAML - YAML implementation in Nim
# (c) Copyright 2015 Felix Krause
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
type
2016-04-02 15:48:22 +00:00
YamlTypeHintState = enum
ythInitial,
ythF, ythFA, ythFAL, ythFALS, ythFALSE,
ythN, ythNU, ythNUL, ythNULL,
ythNO,
ythO, ythON,
ythOF, ythOFF,
ythT, ythTR, ythTRU, ythTRUE,
ythY, ythYE, ythYES,
2016-07-07 15:14:18 +00:00
2016-04-02 15:48:22 +00:00
ythPoint, ythPointI, ythPointIN, ythPointINF,
ythPointN, ythPointNA, ythPointNAN,
2016-07-07 15:14:18 +00:00
2016-04-02 15:48:22 +00:00
ythLowerFA, ythLowerFAL, ythLowerFALS,
ythLowerNU, ythLowerNUL,
ythLowerOF,
ythLowerTR, ythLowerTRU,
ythLowerYE,
2016-07-07 15:14:18 +00:00
2016-04-02 15:48:22 +00:00
ythPointLowerIN, ythPointLowerN, ythPointLowerNA,
2016-07-07 15:14:18 +00:00
2016-04-02 15:48:22 +00:00
ythMinus, yth0, ythInt, ythDecimal, ythNumE, ythNumEPlusMinus, ythExponent
2016-08-17 20:50:37 +00:00
macro typeHintStateMachine(c: untyped, content: untyped): typed =
yAssert content.kind == nnkStmtList
2016-04-02 15:48:22 +00:00
result = newNimNode(nnkCaseStmt, content).add(copyNimNode(c))
for branch in content.children:
yAssert branch.kind == nnkOfBranch
2016-07-07 15:14:18 +00:00
var
2016-04-02 15:48:22 +00:00
charBranch = newNimNode(nnkOfBranch, branch)
i = 0
stateBranches = newNimNode(nnkCaseStmt, branch).add(
newIdentNode("typeHintState"))
while branch[i].kind != nnkStmtList:
charBranch.add(copyNimTree(branch[i]))
inc(i)
for rule in branch[i].children:
yAssert rule.kind == nnkInfix
2016-08-17 20:50:37 +00:00
yAssert $rule[0].ident == "=>"
2016-04-02 15:48:22 +00:00
var stateBranch = newNimNode(nnkOfBranch, rule)
case rule[1].kind
of nnkBracket:
for item in rule[1].children: stateBranch.add(item)
of nnkIdent: stateBranch.add(rule[1])
else: internalError("Invalid rule kind: " & $rule[1].kind)
2016-04-02 15:48:22 +00:00
if rule[2].kind == nnkNilLit:
stateBranch.add(newStmtList(newNimNode(nnkDiscardStmt).add(
newEmptyNode())))
2016-04-02 15:48:22 +00:00
else:
stateBranch.add(newStmtList(newAssignment(
newIdentNode("typeHintState"), copyNimTree(rule[2]))))
2016-04-02 15:48:22 +00:00
stateBranches.add(stateBranch)
stateBranches.add(newNimNode(nnkElse).add(newStmtList(
newNimNode(nnkReturnStmt).add(newIdentNode("yTypeUnknown")))))
charBranch.add(newStmtList(stateBranches))
result.add(charBranch)
result.add(newNimNode(nnkElse).add(newStmtList(
newNimNode(nnkReturnStmt).add(newIdentNode("yTypeUnknown")))))
template advanceTypeHint(ch: char) {.dirty.} =
2016-04-02 15:48:22 +00:00
typeHintStateMachine ch:
of '~': ythInitial => ythNULL
of '.':
[yth0, ythInt] => ythDecimal
[ythInitial, ythMinus] => ythPoint
of '+': ythNumE => ythNumEPlusMinus
of '-':
ythInitial => ythMinus
ythNumE => ythNumEPlusMinus
of '0':
[ythInitial, ythMinus] => yth0
[ythNumE, ythNumEPlusMinus] => ythExponent
2016-07-07 15:14:18 +00:00
[ythInt, ythDecimal, ythExponent] => nil
2016-04-02 15:48:22 +00:00
of '1'..'9':
[ythInitial, ythMinus] => ythInt
[ythNumE, ythNumEPlusMinus] => ythExponent
[ythInt, ythDecimal, ythExponent] => nil
of 'a':
ythF => ythLowerFA
ythPointN => ythPointNA
ythPointLowerN => ythPointLowerNA
of 'A':
ythF => ythFA
ythPointN => ythPointNA
of 'e':
[yth0, ythInt, ythDecimal] => ythNumE
ythLowerFALS => ythFALSE
ythLowerTRU => ythTRUE
ythY => ythLowerYE
of 'E':
[yth0, ythInt, ythDecimal] => ythNumE
ythFALS => ythFALSE
ythTRU => ythTRUE
ythY => ythYE
of 'f':
ythInitial => ythF
ythO => ythLowerOF
ythLowerOF => ythOFF
ythPointLowerIN => ythPointINF
of 'F':
ythInitial => ythF
ythO => ythOF
ythOF => ythOFF
ythPointIN => ythPointINF
of 'i', 'I': ythPoint => ythPointI
of 'l':
ythLowerNU => ythLowerNUL
ythLowerNUL => ythNULL
ythLowerFA => ythLowerFAL
of 'L':
ythNU => ythNUL
ythNUL => ythNULL
ythFA => ythFAL
of 'n':
ythInitial => ythN
ythO => ythON
ythPoint => ythPointLowerN
ythPointI => ythPointLowerIN
ythPointLowerNA => ythPointNAN
of 'N':
ythInitial => ythN
ythO => ythON
ythPoint => ythPointN
ythPointI => ythPointIN
ythPointNA => ythPointNAN
of 'o', 'O':
ythInitial => ythO
ythN => ythNO
of 'r': ythT => ythLowerTR
of 'R': ythT => ythTR
of 's':
ythLowerFAL => ythLowerFALS
ythLowerYE => ythYES
of 'S':
ythFAL => ythFALS
ythYE => ythYES
of 't', 'T': ythInitial => ythT
of 'u':
ythN => ythLowerNU
ythLowerTR => ythLowerTRU
of 'U':
ythN => ythNU
ythTR => ythTRU
of 'y', 'Y': ythInitial => ythY
proc guessType*(scalar: string): TypeHint =
2016-04-02 15:48:22 +00:00
var typeHintState: YamlTypeHintState = ythInitial
for c in scalar: advanceTypeHint(c)
case typeHintState
of ythNULL: result = yTypeNull
of ythTRUE, ythON, ythYES, ythY: result = yTypeBoolTrue
of ythFALSE, ythOFF, ythNO, ythN: result = yTypeBoolFalse
of ythInt, yth0: result = yTypeInteger
of ythDecimal, ythExponent: result = yTypeFloat
of ythPointINF: result = yTypeFloatInf
of ythPointNAN: result = yTypeFloatNaN
else: result = yTypeUnknown