aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/control/parser/json.lux
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--stdlib/source/lux/control/parser/json.lux82
1 files changed, 43 insertions, 39 deletions
diff --git a/stdlib/source/lux/control/parser/json.lux b/stdlib/source/lux/control/parser/json.lux
index ed1620627..48006855b 100644
--- a/stdlib/source/lux/control/parser/json.lux
+++ b/stdlib/source/lux/control/parser/json.lux
@@ -30,8 +30,8 @@
(exception: #export empty-input)
-(def: #export (run json parser)
- (All [a] (-> JSON (Parser a) (Try a)))
+(def: #export (run parser json)
+ (All [a] (-> (Parser a) JSON (Try a)))
(case (//.run parser (list json))
(#try.Success [remainder output])
(case remainder
@@ -39,93 +39,97 @@
(#try.Success output)
_
- (exception.throw unconsumed-input remainder))
+ (exception.throw ..unconsumed-input remainder))
(#try.Failure error)
(#try.Failure error)))
-(def: #export (fail error)
- (All [a] (-> Text (Parser a)))
- (function (_ inputs)
- (#try.Failure error)))
-
(def: #export any
{#.doc "Just returns the JSON input without applying any logic."}
(Parser JSON)
(<| (function (_ inputs))
(case inputs
#.Nil
- (exception.throw empty-input [])
+ (exception.throw ..empty-input [])
(#.Cons head tail)
(#try.Success [tail head]))))
+(exception: #export (unexpected-value {value JSON})
+ (exception.report
+ ["Value" (/.format value)]))
+
(template [<name> <type> <tag> <desc>]
[(def: #export <name>
{#.doc (code.text ($_ text@compose "Reads a JSON value as " <desc> "."))}
(Parser <type>)
(do //.monad
- [head any]
+ [head ..any]
(case head
(<tag> value)
(wrap value)
_
- (fail ($_ text@compose "JSON value is not " <desc> ".")))))]
+ (//.fail (exception.construct ..unexpected-value [head])))))]
- [null Any #/.Null "null"]
- [boolean Bit #/.Boolean "boolean"]
- [number Frac #/.Number "number"]
- [string Text #/.String "string"]
+ [null /.Null #/.Null "null"]
+ [boolean /.Boolean #/.Boolean "boolean"]
+ [number /.Number #/.Number "number"]
+ [string /.String #/.String "string"]
)
-(template [<test> <check> <type> <eq> <encoder> <tag> <desc>]
+(exception: #export [a] (value-mismatch {reference JSON} {sample JSON})
+ (exception.report
+ ["Reference" (/.format reference)]
+ ["Sample" (/.format sample)]))
+
+(template [<test> <check> <type> <equivalence> <tag> <desc>]
[(def: #export (<test> test)
{#.doc (code.text ($_ text@compose "Asks whether a JSON value is a " <desc> "."))}
(-> <type> (Parser Bit))
(do //.monad
- [head any]
+ [head ..any]
(case head
(<tag> value)
- (wrap (:: <eq> = test value))
+ (wrap (:: <equivalence> = test value))
_
- (fail ($_ text@compose "JSON value is not " <desc> ".")))))
+ (//.fail (exception.construct ..unexpected-value [head])))))
(def: #export (<check> test)
{#.doc (code.text ($_ text@compose "Ensures a JSON value is a " <desc> "."))}
(-> <type> (Parser Any))
(do //.monad
- [head any]
+ [head ..any]
(case head
(<tag> value)
- (if (:: <eq> = test value)
+ (if (:: <equivalence> = test value)
(wrap [])
- (fail ($_ text@compose "Value mismatch: " (|> test <encoder>) " =/= " (|> value <encoder>))))
+ (//.fail (exception.construct ..value-mismatch [(<tag> test) (<tag> value)])))
_
- (fail ($_ text@compose "JSON value is not a " <desc> ".")))))]
+ (//.fail (exception.construct ..unexpected-value [head])))))]
- [boolean? boolean! Bit bit.equivalence (<| /.format #/.Boolean) #/.Boolean "boolean"]
- [number? number! Frac frac.equivalence (:: frac.decimal encode) #/.Number "number"]
- [string? string! Text text.equivalence text.encode #/.String "string"]
+ [boolean? boolean! /.Boolean bit.equivalence #/.Boolean "boolean"]
+ [number? number! /.Number frac.equivalence #/.Number "number"]
+ [string? string! /.String text.equivalence #/.String "string"]
)
(def: #export (nullable parser)
(All [a] (-> (Parser a) (Parser (Maybe a))))
- (//.or null
+ (//.or ..null
parser))
(def: #export (array parser)
{#.doc "Parses a JSON array."}
(All [a] (-> (Parser a) (Parser a)))
(do //.monad
- [head any]
+ [head ..any]
(case head
(#/.Array values)
(case (//.run parser (row.to-list values))
(#try.Failure error)
- (fail error)
+ (//.fail error)
(#try.Success [remainder output])
(case remainder
@@ -133,16 +137,16 @@
(wrap output)
_
- (fail (exception.construct unconsumed-input remainder))))
+ (//.fail (exception.construct ..unconsumed-input remainder))))
_
- (fail (text@compose "JSON value is not an array: " (/.format head))))))
+ (//.fail (exception.construct ..unexpected-value [head])))))
(def: #export (object parser)
{#.doc "Parses a JSON object. Use this with the 'field' combinator."}
(All [a] (-> (Parser a) (Parser a)))
(do //.monad
- [head any]
+ [head ..any]
(case head
(#/.Object kvs)
(case (|> kvs
@@ -152,7 +156,7 @@
list.concat
(//.run parser))
(#try.Failure error)
- (fail error)
+ (//.fail error)
(#try.Success [remainder output])
(case remainder
@@ -160,10 +164,10 @@
(wrap output)
_
- (fail (exception.construct unconsumed-input remainder))))
+ (//.fail (exception.construct ..unconsumed-input remainder))))
_
- (fail (text@compose "JSON value is not an object: " (/.format head))))))
+ (//.fail (exception.construct ..unexpected-value [head])))))
(def: #export (field field-name parser)
{#.doc "Parses a field inside a JSON object. Use this inside the 'object' combinator."}
@@ -177,7 +181,7 @@
(#try.Success [inputs' output])
(#try.Success [inputs'' _])
- (exception.throw unconsumed-input inputs'')
+ (exception.throw ..unconsumed-input inputs'')
(#try.Failure error)
(#try.Failure error))
@@ -187,15 +191,15 @@
output])))
#.Nil
- (exception.throw empty-input [])
+ (exception.throw ..empty-input [])
_
- (exception.throw unconsumed-input inputs))))
+ (exception.throw ..unconsumed-input inputs))))
(def: #export dictionary
{#.doc "Parses a dictionary-like JSON object."}
(All [a] (-> (Parser a) (Parser (Dictionary Text a))))
(|>> (//.and ..string)
//.some
- object
+ ..object
(//@map (dictionary.from-list text.hash))))