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

(documentation: /.Offset
  "An offset into a block of text.")

(documentation: (/.Parser it)
  "A parser for text.")

(documentation: /.Slice
  "A slice of a block of text.")

(documentation: /.result
  (format "Executes a parser against a block of text."
          \n "Verifies that the entire input has been processed.")
  [(result parser input)])

(documentation: /.offset
  "Yields the current offset into the input.")

(documentation: /.any
  "Yields the next character without applying any logic.")

(documentation: /.any!
  "Yields the next character (as a slice) without applying any logic.")

(template [<name> <caveat>]
  [(`` (documentation: <name>
         (format "Produce a character" (~~ (template.text [<caveat>])) " if the parser fails.")))]

  [/.not  ""]
  [/.not! " (as a slice)"]
  )

(documentation: /.this
  "Checks that a specific text shows up in the input."
  [(this reference)])

(documentation: /.end!
  "Ensure the parser's input is empty.")

(documentation: /.next
  "Yields the next character (without consuming it from the input).")

(documentation: /.remaining
  "Get all of the remaining input (without consuming it).")

(documentation: /.range
  "Only yields characters within a range."
  [(range bottom top)])

(template [<name> <desc>]
  [(documentation: <name>
     (format "Only yields " <desc> " characters."))]

  [/.upper "uppercase"]
  [/.lower "lowercase"]
  [/.decimal "decimal"]
  [/.octal "octal"]
  )

(documentation: /.alpha
  "Yields alphabetic characters.")

(documentation: /.alpha_num
  "Yields alphanumeric characters.")

(documentation: /.hexadecimal
  "Yields hexadecimal digits.")

(template [<name> <description_modifier>]
  [(documentation: <name>
     (format "Yields characters that are" <description_modifier> " part of a piece of text."))]

  [/.one_of ""]
  [/.none_of " not"]
  )

(template [<name> <description_modifier>]
  [(documentation: <name>
     (format "Yields characters (as a slice) that are" <description_modifier> " part of a piece of text."))]

  [/.one_of! ""]
  [/.none_of! " not"]
  )

(documentation: /.satisfies
  "Yields characters that satisfy a predicate."
  [(satisfies parser)])

(documentation: /.space
  "Yields white-space.")

(documentation: /.and
  "Yields the outputs of both parsers composed together."
  [(and left right)])

(documentation: /.and!
  "Yields the outputs of both parsers composed together (as a slice)."
  [(and! left right)])

(template [<text> <slice>]
  [(`` (documentation: <text>
         (format "Yields " (~~ (template.text [<name>])) " characters as a single continuous text.")))
   (`` (documentation: <slice>
         (format "Yields " (~~ (template.text [<name>])) " characters as a single continuous text (as a slice).")))]

  [/.some /.some!]
  [/.many /.many!]
  )

(template [<text> <slice> <doc_modifier>]
  [(`` (documentation: <text>
         (format "Yields " <doc_modifier> " N characters.")))
   (`` (documentation: <slice>
         (format "Yields " <doc_modifier> " N characters (as a slice).")))]

  [/.exactly  /.exactly!  "exactly"]
  [/.at_most  /.at_most!  "at most"]
  [/.at_least /.at_least! "at least"]
  )

(documentation: /.between
  ""
  [(between minimum additional parser)])

(documentation: /.between!
  ""
  [(between! minimum additional parser)])

(documentation: /.enclosed
  ""
  [(enclosed [start end] parser)])

(documentation: /.local
  "Applies a parser against the given input."
  [(local local_input parser)])

(documentation: /.slice
  "Converts a slice to a block of text."
  [(slice parser)])

(documentation: /.then
  "Embeds a text parser into an arbitrary parser that yields text."
  [(then structured text)])

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

             ..any ..any!
             ..not ..not!
             
             ..this
             ..end!
             ..next
             ..remaining
             ..range

             ..upper
             ..lower
             ..decimal
             ..octal
             
             ..alpha
             ..alpha_num
             ..hexadecimal

             ..one_of ..one_of!
             ..none_of ..none_of!
             
             ..satisfies
             ..space
             ..and ..and!

             ..some ..some!
             ..many ..many!
             

             ..exactly ..exactly!
             ..at_most ..at_most!
             ..at_least ..at_least!
             
             ..between
             ..between!
             ..enclosed
             ..local
             ..slice
             ..then

             ($.default /.unconsumed_input)
             ($.default /.expected_to_fail)
             ($.default /.cannot_parse)
             ($.default /.cannot_slice)
             ($.default /.cannot_match)
             ($.default /.character_should_be)
             ($.default /.character_should_not_be)
             ($.default /.character_does_not_satisfy_predicate)]
            []))
