tparsecombnum.nim 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. import parsecomb
  2. discard """
  3. output: "-289096"
  4. """
  5. type Num = int
  6. # forward stuff
  7. var exp3: Parser[string, Num]
  8. var exp = lazy(proc(): Parser[string, Num] = exp3)
  9. var digit = (proc(): Parser[string, Num] =
  10. result = tok("0").then(unit[string, Num](Num(0)))
  11. for n in 1..9:
  12. result = result + tok($n).then(unit[string, Num](Num(n)))
  13. )()
  14. var num = repeat1(digit).map(proc(ds: seq[Num]): Num =
  15. result = 0
  16. for d in ds:
  17. result = result*10 + d)
  18. type Op = proc(a, b: Num): Num
  19. var plusOp = tok("+").then(unit[string, Op](proc(a, b: Num): Num = a + b))
  20. var minusOp = tok("-").then(unit[string, Op](proc(a, b: Num): Num = a - b))
  21. var timesOp = tok("*").then(unit[string, Op](proc(a, b: Num): Num = a*b))
  22. var divideOp = tok("/").then(unit[string, Op](proc(a, b: Num): Num = a div b))
  23. var paren = (tok("(") * exp * tok(")")).map(proc(ler: ((string, Num), string)): Num =
  24. var (le, r) = ler
  25. var (l, e) = le
  26. e)
  27. proc foldOp(a: Num, ob: (Op, Num)): Num =
  28. var (o, b) = ob
  29. o(a, b)
  30. var exp0 = paren + num
  31. var exp1 = exp0.leftRec((timesOp + divideOp)*exp0, foldOp)
  32. var exp2 = exp1.leftRec((plusOp + minusOp)*exp1, foldOp)
  33. exp3 = exp2
  34. proc strsplit(s: string): seq[string] =
  35. result = @[]
  36. for i in 0 .. s.len - 1:
  37. result.add($s[i])
  38. var r = exp.run("523-(1243+411/744*1642/1323)*233".strsplit)
  39. case r.kind:
  40. of rkSuccess:
  41. echo r.output
  42. of rkFailure:
  43. echo "failed"