(.using
  [library
   [lux "*"
    ["$" documentation {"+" documentation:}]
    [data
     [text {"+" \n}
      ["%" format {"+" format}]]]
    [macro
     ["[0]" template]]]]
  [\\library
   ["[0]" /]])

(documentation: (/.Parser it)
  "A JSON parser.")

(documentation: /.result
  (format "Executes the parser against a JSON object."
          \n "Verifies that all of the JSON was consumed by the parser.")
  [(result parser json)])

(documentation: /.any
  "Just returns the JSON input without applying any logic.")

(template [<name>]
  [(`` (documentation: <name>
         (format "Reads a JSON value as " (~~ (template.text [<name>])) ".")))]

  [/.null]
  [/.boolean]
  [/.number]
  [/.string]
  )

(template [<test> <check> <read>]
  [(`` (documentation: <test>
         (format "Asks whether a JSON value is a " (~~ (template.text [<read>])) ".")))
   (`` (documentation: <check>
         (format "Ensures a JSON value is a " (~~ (template.text [<read>])) ".")))]

  [/.boolean? /.boolean! ..boolean]
  [/.number?  /.number!  ..number]
  [/.string?  /.string!  ..string]
  )

(documentation: /.nullable
  "Enhances parser by adding NULL-handling."
  [(nullable parser)])

(documentation: /.array
  "Parses the contents of a JSON array."
  [(array parser)])

(documentation: /.object
  (format "Parses the contents of a JSON object."
          \n "Use this with the 'field' combinator.")
  [(object parser)])

(documentation: /.field
  (format "Parses a field inside a JSON object."
          \n "Use this inside the 'object' combinator.")
  [(field field_name parser)])

(documentation: /.dictionary
  "Parses a dictionary-like JSON object.")

(.def: .public documentation
  (.List $.Module)
  ($.module /._
            ""
            [..Parser
             ..result
             ..any

             ..null
             ..boolean
             ..number
             ..string
             
             ..boolean? ..boolean!
             ..number? ..number!
             ..string? ..string!
             
             ..nullable
             ..array
             ..object
             ..field
             ..dictionary
             ($.default /.unconsumed_input)
             ($.default /.empty_input)
             ($.default /.unexpected_value)
             ($.default /.value_mismatch)]
            []))
