(.require [library [lux (.except char symbol) ["_" test (.only Test)] [abstract [monad (.only do)] [\\specification ["$[0]" equivalence] ["$[0]" codec]]] [control ["<>" parser (.use "[1]#[0]" monad)] ["[0]" maybe] ["[0]" try (.use "[1]#[0]" functor)] ["[0]" exception]] [data ["[0]" text (.use "[1]#[0]" equivalence) ["%" \\format (.only format)]] [collection ["[0]" dictionary] ["[0]" list (.use "[1]#[0]" functor)]]] [macro ["^" pattern] ["[0]" template]] [math ["[0]" random (.only Random) (.use "[1]#[0]" monad)] [number ["n" nat]]] [meta ["[0]" symbol (.use "[1]#[0]" equivalence)] ["[0]" type (.use "[1]#[0]" equivalence)]]]] ["[0]" \\parser] [\\library ["[0]" / (.use "[1]#[0]" equivalence)]]) (def !expect (template (_ ) [(case true _ false)])) (def !failure (template (_ ) [(with_expansions [<> (template.spliced )] (do [! random.monad] [expected (random.alphabetic 1)] (_.coverage [] (`` (and (,, (with_template [ ] [(|> (\\parser.result (list )) (!expect (^.multi {try.#Failure error} (exception.match? error))))] <>)))))))])) (def random_label (Random Symbol) (random.and (random.alphabetic 1) (random.alphabetic 1))) (def random_tag ..random_label) (def random_attribute ..random_label) (def \\parser Test (<| (_.covering \\parser._) (_.for [\\parser.Parser]) (all _.and (do [! random.monad] [expected (random.alphabetic 1)] (_.coverage [\\parser.result \\parser.text] (|> (\\parser.result \\parser.text (list {/.#Text expected})) (!expect (^.multi {try.#Success actual} (text#= expected actual)))))) (!failure \\parser.unconsumed_inputs [[(<>#in expected) {/.#Text expected}]]) (do [! random.monad] [expected (at ! each (|>> {/.#Text}) (random.alphabetic 1))] (_.coverage [\\parser.any] (|> (\\parser.result \\parser.any (list expected)) (try#each (/#= expected)) (try.else false)))) (do [! random.monad] [expected ..random_tag] (_.coverage [\\parser.tag] (|> (\\parser.result (do <>.monad [actual \\parser.tag _ \\parser.any] (in (symbol#= expected actual))) (list {/.#Node expected (dictionary.empty symbol.hash) (list)})) (!expect {try.#Success #1})))) (do [! random.monad] [expected ..random_tag] (_.coverage [\\parser.node] (|> (\\parser.result (\\parser.node expected (<>#in [])) (list {/.#Node expected (dictionary.empty symbol.hash) (list)})) (!expect {try.#Success []})))) (!failure \\parser.wrong_tag [[(\\parser.node ["" expected] (<>#in [])) {/.#Node [expected ""] (dictionary.empty symbol.hash) (list)}]]) (do [! random.monad] [expected_tag ..random_tag expected_attribute ..random_attribute expected_value (random.alphabetic 1)] (_.coverage [\\parser.attribute] (|> (\\parser.result (<| (\\parser.node expected_tag) (<>.after (\\parser.attribute expected_attribute)) (<>#in [])) (list {/.#Node expected_tag (|> (dictionary.empty symbol.hash) (dictionary.has expected_attribute expected_value)) (list)})) (!expect {try.#Success []})))) (!failure \\parser.unknown_attribute [[(\\parser.attribute ["" expected]) {/.#Node [expected expected] (|> (dictionary.empty symbol.hash) (dictionary.has [expected ""] expected)) (list)}]]) (!failure \\parser.empty_input [[(do <>.monad [_ \\parser.any] \\parser.any) {/.#Text expected}] [(do <>.monad [_ \\parser.any] \\parser.text) {/.#Text expected}] [(do <>.monad [_ \\parser.any] (\\parser.node [expected expected] (<>#in []))) {/.#Node [expected expected] (dictionary.empty symbol.hash) (list)}] [(do <>.monad [_ \\parser.any] (\\parser.node [expected expected] (\\parser.attribute [expected expected]))) {/.#Node [expected expected] (|> (dictionary.empty symbol.hash) (dictionary.has [expected expected] expected)) (list)}]]) (!failure \\parser.unexpected_input [[\\parser.text {/.#Node [expected expected] (dictionary.empty symbol.hash) (list)}] [(\\parser.node [expected expected] (<>#in [])) {/.#Text expected}] [(\\parser.node [expected expected] (\\parser.attribute [expected expected])) {/.#Text expected}]]) (do [! random.monad] [.let [node (is (-> /.Tag (List /.XML) /.XML) (function (_ tag children) {/.#Node tag (dictionary.empty symbol.hash) children}))] parent ..random_tag right ..random_tag wrong (random.only (|>> (symbol#= right) not) ..random_tag) .let [parser (<| (\\parser.node parent) (do <>.monad [_ (<| \\parser.somewhere (\\parser.node right) (<>#in [])) _ (<>.some \\parser.any)] (in [])))] repetitions (at ! each (n.% 10) random.nat)] (all _.and (_.coverage [\\parser.somewhere] (|> (\\parser.result parser (list (node parent (list.together (list (list.repeated repetitions (node wrong (list))) (list (node right (list))) (list.repeated repetitions (node wrong (list)))))))) (!expect {try.#Success []}))) (_.coverage [\\parser.nowhere] (|> (\\parser.result parser (list (node parent (list.repeated repetitions (node wrong (list)))))) (!expect (^.multi {try.#Failure error} (exception.match? \\parser.nowhere error))))) )) ))) (def char_range Text (format "_" "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) (def char (Random Nat) (do [! random.monad] [idx (|> random.nat (at ! each (n.% (text.size char_range))))] (in (maybe.trusted (text.char idx char_range))))) (def (size bottom top) (-> Nat Nat (Random Nat)) (let [constraint (|>> (n.% top) (n.max bottom))] (random#each constraint random.nat))) (def (text bottom top) (-> Nat Nat (Random Text)) (do random.monad [size (..size bottom top)] (random.text ..char size))) (def symbol (Random Symbol) (random.and (..text 0 10) (..text 1 10))) (def .public random (Random /.XML) (random.rec (function (_ random) (random.or (..text 1 10) (do random.monad [size (..size 0 2)] (all random.and ..symbol (random.dictionary symbol.hash size ..symbol (..text 0 10)) (random.list size random))))))) (def .public test Test (<| (_.covering /._) (_.for [/.XML]) (all _.and (_.for [/.equivalence] ($equivalence.spec /.equivalence ..random)) (_.for [/.codec] ($codec.spec /.equivalence /.codec ..random)) (do [! random.monad] [(^.let symbol [namespace name]) ..symbol] (`` (all _.and (,, (with_template [ ] [(_.coverage [ ] (and (text#= name ( ["" name])) (let [symbol ( symbol)] (and (text.starts_with? namespace symbol) (text.ends_with? name symbol)))))] [/.Tag /.tag] [/.Attribute /.attribute] )) (_.coverage [/.Attrs /.attributes] (dictionary.empty? /.attributes)) ))) ..\\parser )))