(.require
 [library
  [lux (.except)
   ["$" documentation]
   [data
    [collection
     ["[0]" list (.use "[1]#[0]" monoid)]]]
   [meta
    [macro
     ["[0]" template]]]]]
 ["[0]" /
  ["[1][0]" buffer]
  ["[1][0]" encoding]
  ["[1][0]" escape]
  ["[1][0]" regex]
  ["[1][0]" unicode]]
 ["[0]" \\format (.only format)]
 ["[0]" \\parser]
 [\\library
  ["[0]" / (.only \n)]])

(def \\format
  (List $.Documentation)
  (let [specific (list ($.definition \\format.bit)
                       ($.definition \\format.nat)
                       ($.definition \\format.int)
                       ($.definition \\format.rev)
                       ($.definition \\format.frac)
                       ($.definition \\format.text)
                       
                       ($.definition \\format.ratio)
                       ($.definition \\format.symbol)
                       ($.definition \\format.location)
                       ($.definition \\format.code)
                       ($.definition \\format.type)
                       
                       ($.definition \\format.instant)
                       ($.definition \\format.duration)
                       ($.definition \\format.date)
                       ($.definition \\format.time)
                       ($.definition \\format.day)
                       ($.definition \\format.month)
                       
                       ($.definition \\format.xml)
                       ($.definition \\format.json))
        number (list ($.definition \\format.nat_2)
                     ($.definition \\format.nat_8)
                     ($.definition \\format.nat_10)
                     ($.definition \\format.nat_16)
                     ($.definition \\format.int_2)
                     ($.definition \\format.int_8)
                     ($.definition \\format.int_10)
                     ($.definition \\format.int_16)
                     ($.definition \\format.rev_2)
                     ($.definition \\format.rev_8)
                     ($.definition \\format.rev_10)
                     ($.definition \\format.rev_16)
                     ($.definition \\format.frac_2)
                     ($.definition \\format.frac_8)
                     ($.definition \\format.frac_10)
                     ($.definition \\format.frac_16))]
    (list.partial ($.module \\format._
                            "")

                  ($.definition \\format.functor)

                  ($.definition \\format.mod)
                  ($.definition \\format.list)
                  ($.definition \\format.maybe)

                  ($.definition (\\format.Format it)
                    "A way to produce readable text from values.")

                  ($.definition \\format.format
                    "Text interpolation."
                    [(format "Static part " (text static) " does not match URI: " uri)])

                  (all list#composite
                       specific
                       number
                       )
                  )))

(`` (def \\parser
      (List $.Documentation)
      (let [exception (list ($.definition \\parser.unconsumed_input)
                            ($.definition \\parser.expected_to_fail)
                            ($.definition \\parser.cannot_parse)
                            ($.definition \\parser.cannot_slice)
                            ($.definition \\parser.cannot_match)
                            ($.definition \\parser.character_should_be)
                            ($.definition \\parser.character_should_not_be)
                            ($.definition \\parser.character_does_not_satisfy_predicate))
            specific (list ($.definition \\parser.range
                             "Only yields characters within a range."
                             [(range bottom top)])

                           (,, (with_template [<name> <desc>]
                                 [($.definition <name>
                                    (format "Only yields " <desc> " characters."))]

                                 [\\parser.upper "uppercase"]
                                 [\\parser.lower "lowercase"]
                                 [\\parser.decimal "decimal"]
                                 [\\parser.octal "octal"]
                                 ))

                           ($.definition \\parser.alpha
                             "Yields alphabetic characters.")

                           ($.definition \\parser.alpha_num
                             "Yields alphanumeric characters.")

                           ($.definition \\parser.hexadecimal
                             "Yields hexadecimal digits.")

                           ($.definition \\parser.space
                             "Yields white-space."))]
        (list.partial ($.module \\parser._
                                "")

                      ($.definition \\parser.Offset
                        "An offset into a block of text.")

                      ($.definition (\\parser.Parser it)
                        "A parser for text.")

                      ($.definition \\parser.Slice
                        "A slice of a block of text.")

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

                      ($.definition \\parser.offset
                        "Yields the current offset into the input.")

                      ($.definition \\parser.any
                        "Yields the next character without applying any logic.")

                      ($.definition \\parser.any!
                        "Yields the next character (as a slice) without applying any logic.")

                      (,, (with_template [<name> <caveat>]
                            [(`` ($.definition <name>
                                   (format "Produce a character" (,, (template.text [<caveat>])) " if the parser fails.")))]

                            [\\parser.not  ""]
                            [\\parser.not! " (as a slice)"]
                            ))

                      ($.definition \\parser.this
                        "Checks that a specific text shows up in the input."
                        [(this reference)])

                      ($.definition \\parser.end
                        "Ensure the parser's input is empty.")

                      ($.definition \\parser.next
                        "Yields the next character (without consuming it from the input).")

                      ($.definition \\parser.remaining
                        "Get all of the remaining input (without consuming it).")

                      (,, (with_template [<name> <description_modifier>]
                            [($.definition <name>
                               (format "Yields characters that are" <description_modifier> " part of a piece of text."))]

                            [\\parser.one_of ""]
                            [\\parser.none_of " not"]
                            ))

                      (,, (with_template [<name> <description_modifier>]
                            [($.definition <name>
                               (format "Yields characters (as a slice) that are" <description_modifier> " part of a piece of text."))]

                            [\\parser.one_of! ""]
                            [\\parser.none_of! " not"]
                            ))

                      ($.definition \\parser.satisfies
                        "Yields characters that satisfy a predicate."
                        [(satisfies parser)])

                      ($.definition \\parser.and
                        "Yields the outputs of both parsers composed together."
                        [(and left right)])

                      ($.definition \\parser.and!
                        "Yields the outputs of both parsers composed together (as a slice)."
                        [(and! left right)])

                      (,, (with_template [<text> <slice>]
                            [(`` ($.definition <text>
                                   (format "Yields " (,, (template.text [<name>])) " characters as a single continuous text.")))
                             (`` ($.definition <slice>
                                   (format "Yields " (,, (template.text [<name>])) " characters as a single continuous text (as a slice).")))]

                            [\\parser.some \\parser.some!]
                            [\\parser.many \\parser.many!]
                            ))

                      (,, (with_template [<text> <slice> <doc_modifier>]
                            [(`` ($.definition <text>
                                   (format "Yields " <doc_modifier> " N characters.")))
                             (`` ($.definition <slice>
                                   (format "Yields " <doc_modifier> " N characters (as a slice).")))]

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

                      ($.definition \\parser.between
                        ""
                        [(between minimum additional parser)])

                      ($.definition \\parser.between!
                        ""
                        [(between! minimum additional parser)])

                      ($.definition \\parser.enclosed
                        ""
                        [(enclosed [start end] parser)])

                      ($.definition \\parser.local
                        "Applies a parser against the given input."
                        [(local local_input parser)])

                      ($.definition \\parser.slice
                        "Converts a slice to a block of text."
                        [(slice parser)])

                      ($.definition \\parser.then
                        "Embeds a text parser into an arbitrary parser that yields text."
                        [(then structured text)])

                      (all list#composite
                           exception
                           specific
                           )
                      ))))

(def .public documentation
  (List $.Documentation)
  (let [character (list ($.definition /.Char
                          "A character code number.")

                        ($.definition /.char
                          "Yields the character at the specified index."
                          [(char index input)])

                        ($.definition /.of_char)

                        ($.definition /.\0)
                        ($.definition /.null)
                        ($.definition /.\a)
                        ($.definition /.alarm)
                        ($.definition /.\b)
                        ($.definition /.back_space)
                        ($.definition /.\t)
                        ($.definition /.tab)
                        ($.definition /.\n)
                        ($.definition /.new_line)
                        ($.definition /.\v)
                        ($.definition /.vertical_tab)
                        ($.definition /.\f)
                        ($.definition /.form_feed)
                        ($.definition /.\r)
                        ($.definition /.carriage_return)
                        ($.definition /.\'')
                        ($.definition /.double_quote)

                        ($.definition /.space)
                        
                        ($.definition /.line_feed
                          "Same as 'new_line'."))
        query (list ($.definition /.empty?)

                    ($.definition /.starts_with?
                      ""
                      [(starts_with? prefix x)])

                    ($.definition /.ends_with?
                      ""
                      [(ends_with? postfix x)])

                    ($.definition /.enclosed_by?
                      ""
                      [(enclosed_by? boundary value)])

                    ($.definition /.contains?
                      ""
                      [(contains? sub text)])

                    ($.definition /.space?
                      "Checks whether the character is white-space."
                      [(space? char)]))]
    (list.partial ($.module /._
                            "")

                  ($.definition /.size)
                  ($.definition /.format)
                  ($.definition /.equivalence)
                  ($.definition /.order)
                  ($.definition /.monoid)
                  ($.definition /.hash)
                  ($.definition /.together)
                  
                  ($.definition /.lower_cased)
                  ($.definition /.upper_cased)

                  ($.definition /.index_since
                    ""
                    [(index_since from pattern input)])

                  ($.definition /.index
                    ""
                    [(index pattern input)])

                  ($.definition /.last_index
                    ""
                    [(last_index part text)])

                  ($.definition /.prefix
                    ""
                    [(prefix param subject)])

                  ($.definition /.suffix
                    ""
                    [(suffix param subject)])

                  ($.definition /.enclosed
                    "Surrounds the given content text with left and right side additions."
                    [(enclosed [left right] content)])

                  ($.definition /.enclosed'
                    "Surrounds the given content text with the same boundary text."
                    [(enclosed' boundary content)])

                  ($.definition /.clip
                    "Clips a chunk of text from the input at the specified offset and of the specified size."
                    [(clip offset size input)])

                  ($.definition /.clip_since
                    "Clips the remaining text from the input at the specified offset."
                    [(clip_since offset input)])

                  ($.definition /.split_at
                    ""
                    [(split_at at x)])

                  ($.definition /.split_by
                    ""
                    [(split_by token sample)])

                  ($.definition /.all_split_by
                    ""
                    [(all_split_by token sample)])

                  ($.definition /.replaced_once
                    ""
                    [(replaced_once pattern replacement template)])

                  ($.definition /.replaced
                    ""
                    [(replaced pattern replacement template)])

                  ($.definition /.interposed
                    ""
                    [(interposed separator texts)])

                  (all list#composite
                       character
                       query
                       
                       ..\\format
                       ..\\parser
                       
                       /buffer.documentation
                       /encoding.documentation
                       /escape.documentation
                       /regex.documentation
                       /unicode.documentation
                       )
                  )))
