section 3bD, JSON and XML =========================

++moon

Mime type to `++cord` ++ moon :: mime type to text |= myn=mite %+ rap 3 |- ^- tape ?~ myn ~ ?: =(~ t.myn) (trip i.myn) (weld (trip i.myn) `tape`['/' $(myn t.myn)]) :: Renders a [mime](http://en.wikipedia.org/wiki/MIME) type path with infix `/` to a [cord](). `myn` is a ++[mite](), a list of [@ta](). ~zod/try=> `@t`(moon /image/png) 'image/png' ~zod/try=> `@t`(moon /text/x-hoon) 'text/x-hoon' ~zod/try=> `@t`(moon /application/x-pnacl) 'application/x-pnacl'

++perk

Parse cube with fork ++ perk :: parse cube with fork |* a=(pole ,@tas) ?~ a fail ;~ pose (cold -.a (jest -.a)) $(a +.a) == :: Parser generator. Produces a parser that succeeds upon encountering one of the [`++term`]()s in a faceless list `a`. A- perk is an arm used to parse one of a finite set of options, formally a choice between terms: if you want to match "true" or "false", and nothing else, (perk \~[%true %false]) produces the relevant parser, whose result type is `?(%true %false)`. For more complicated transformations, a combintation of ++sear and map ++get is recommended, e.g. `(sear ~(get by (mo ~[[%true &] [%false |]]))) sym)` will have a similar effect but produce `?(& |)` ,a loobean. However, constructions such as `(sear (flit ~(has in (sa %true %false %other ~))) sym)` are needlessly unwieldy. `a` is a [`++pole`](), which is a [`++list`]() without [`%face`]()s ~zod/try=> (scan "ham" (perk %sam %ham %lam ~)) %ham ~zod/try=> (scan "ram" (perk %sam %ham %lam ~)) ! {1 1} ! exit

++poja

JSON parser core ++ poja :: JSON parser core =< |=(a=cord (rush a apex)) |% JSON parser core: parses a `++cord` `a` to the hoon structure for JSON, a [`++json`](). `a` is [`++cord`](). ~zod/try=> (poja '[1,2,3]') [~ [%a p=~[[%n p=~.1] [%n p=~.2] [%n p=~.3]]]] ~zod/try=> (poja 'null') [~ ~] ~zod/try=> (poja 'invalid{json') ~

++apex

Parse object ++ apex ;~(pose abox obox) :: JSON object Top level parsing rule. Parses either a single JSON object, or an array of JSON objects to a [`++json`](). See also: [`++abox`](), [`++obox`](). A- this is now called ++tops, and ++apex is the old ++valu, which apparently didn't make its way into the docs. Apologies for the confusion, many things have been restructured in ++shell inconsistently with current test:urbit.git ~zod/try=> (rash '[1,2]' apex:poja) [%a p=~[[%n p=~.1] [%n p=~.2]]] ~zod/try=> (rash '{"sam": "kot"}' apex:poja) [%o p={[p=~.sam q=[%s p=~.kot]]}] ~zod/try=> (rash 'null' apex:poja) ! {1 1} ! exit

++valu

Parse value ++ valu :: JSON value %+ knee *json |. ~+ ;~ pfix spac ;~ pose (cold ~ (jest 'null')) (jify %b bool) (jify %s stri) (cook |=(s=tape [%n p=(rap 3 s)]) numb) abox obox == == Parsing rule. Parses JSON values to [`++json`](). ~zod/try=> (rash '[1,2]' valu:poja) [%a p=~[[%n p=~.1] [%n p=~.2]]] ~zod/try=> (rash '{"sam": "kot"}' valu:poja) [%o p={[p='sam' q=[%s p=~.kot]]}] ~zod/try=> (rash 'null' valu:poja) ~ ~zod/try=> (rash '20' valu:poja) [%n p=~.20] ~zod/try=> (rash '"str"' valu:poja) [%s p=~.str] ~zod/try=> (rash 'true' valu:poja) [%b p=%.y]

++abox

Parse array ++ abox (stag %a (ifix [sel (ws ser)] (more (ws com) valu))) Parsing rule. Parses a JSON array with values enclosed within `[]` and delimited by a `,`. ~zod/try=> (rash '[1, 2,4]' abox:poja) [[%n p=~.1] ~[[%n p=~.2] [%n p=~.4]]] JSON Objects ------------

++pair

Parse key value pair ++ pair ;~(plug ;~(sfix (ws stri) (ws col)) valu) Parsing rule. Parses a [`++json`]() from a JSON key-value pair of a string and value delimited by `:`. ~zod/try=> (rash '"ham": 2' pair:poja) ['ham' [%n p=~.2]]

++obje

Parse array of objects ++ obje (ifix [(ws kel) (ws ker)] (more (ws com) pair)) Parsing rule. Parses a [`++json`]() from an array of JSON object key-value pairs that are enclosed within `{}` and separated by `,`. ~zod/try=> (rash '{"ham": 2, "lam":true}' obje:poja) [['ham' [%n p=~.2]] ~[['lam' [%b p=%.y]]]]

++obox

Parse boxed object ++ obox (stag %o (cook mo obje)) Parsing rule. Parses an array of JSON objects to a [`++json`]() map with a tag of `%o`. See also: [`++json`](). ~zod/try=> (rash '{"ham": 2, "lam":true}' obox:poja) [%o {[p='lam' q=[%b p=%.y]] [p='ham' q=[%n p=~.2]]}] JSON Booleans -------------

++bool

Parse boolean ++ bool ;~(pose (cold & (jest 'true')) (cold | (jest 'false'))) Parsing rule. Parses a string of either `true` or `false` to a [`++json`]() boolean. ~zod/try=> (rash 'true' bool:poja) %.y ~zod/try=> (rash 'false' bool:poja) %.n ~zod/try=> (rash 'null' bool:poja) ! {1 1} ! exit JSON strings ------------

++stri

Parse string ++ stri (cook crip (ifix [doq doq] (star jcha))) Parsing rule. Parse a string to a [`++cord`](). A JSON string is a list of characters enclosed in double quotes along with escaping `\`s, to a [`++cord`](). See also [`++jcha`](). ~zod/try=> (rash '"ham"' stri:poja) 'ham' ~zod/try=> (rash '"h\\nam"' stri:poja) 'h am' ~zod/try=> (rash '"This be \\"quoted\\""' stri:poja) 'This be "quoted"'

++jcha

Parse char from string ++ jcha ;~(pose ;~(less doq bas prn) esca) :: character in string Parsing rule. Parses either a literal or escaped character from a JSON string to a [`++cord`](). ~zod/try=> (rash 'a' jcha:poja) 'a'. ~zod/try=> (rash '!' jcha:poja) '!' ~zod/try=> (rash '\\"' jcha:poja) '"' ~zod/try=> (rash '\\u00a4' jcha:poja) '¤' ~zod/try=> (rash '\\n' jcha:poja) ' '

++esca

Parse escaped char ++ esca :: Escaped character ;~ pfix bas ;~ pose doq fas soq bas (sear ~(get by `(map ,@t ,@)`(mo b/8 t/9 n/10 f/12 r/13 ~)) low) ;~(pfix (just 'u') (cook tuft qix:ab)) :: 4-digit hex to UTF-8 == Parsing rule. Parses a backslash-escaped special character, low ASCII, or UTF16 codepoint, to a [`++cord`](). ~zod/try=> (rash 'b' esca:poja) ! {1 1} ! exit ~zod/try=> (rash '\n' esca:poja) ~ ~zod/try=> (rash '\\n' esca:poja) ' ' ~zod/try=> `@`(rash '\\r' esca:poja) 13 ~zod/try=> (rash '\\u00c4' esca:poja) 'Ä' ~zod/try=> (rash '\\u00df' esca:poja) 'ß' JSON numbers ------------ A- JSON numbers are stored as cords internally in lieu of full float support, so ++numb and subarms are really more *validators* than parsers per se.

++numb

Parse number ++ numb ;~ (comp twel) (mayb (piec hep)) ;~ pose (piec (just '0')) ;~(plug (shim '1' '9') digs) == (mayb frac) (mayb expo) == Parsing rule. Parses decimal numbers with an optional `-`, fractional part, or exponent part, to a [`++cord`](). ~zod/try=> (rash '0' numb:poja) ~[~~0] ~zod/try=> (rash '1' numb:poja) ~[~~1] ~zod/try=> `tape`(rash '1' numb:poja) "1" ~zod/try=> `tape`(rash '12.6' numb:poja) "12.6" ~zod/try=> `tape`(rash '-2e20' numb:poja) "-2e20" ~zod/try=> `tape`(rash '00e20' numb:poja) ! {1 2} ! exit

++digs

Parse 1-9 ++ digs (star (shim '0' '9')) Parsing rule. Parses digits `0` through `9` to a [`++tape`](). ~zod/try=> (rash '' digs:poja) "" ~zod/try=> (rash '25' digs:poja) "25" ~zod/try=> (rash '016' digs:poja) "016" ~zod/try=> (rash '7' digs:poja) "7"

++expo

Parse exponent part ++ expo :: Exponent part ;~ (comp twel) (piec (mask "eE")) (mayb (piec (mask "+-"))) digs == Parsing rule. Parses an exponent to a [`++cord`](). An exponent is an `e`, followed by an optional `+` or `-`, followed by digits. ~zod/try=> `tape`(rash 'e7' expo:poja) "e7" ~zod/try=> `tape`(rash 'E17' expo:poja) "E17" ~zod/try=> `tape`(rash 'E-4' expo:poja) "E-4"

++frac

Fractional part ++ frac ;~(plug dot digs) :: Fractional part Parsing rule. Parses a dot followed by digits to a [`++cord`](). ~zod/try=> (rash '.25' frac:poja) [~~~. "25"] ~zod/try=> (rash '.016' frac:poja) [~~~. "016"] ~zod/try=> (rash '.7' frac:poja) [~~~. "7"] whitespace ----------

++spac

Parse whitespace ++ spac (star (mask [`@`9 `@`10 `@`13 ' ' ~])) Parsing rule. Parses a whitespace to a [`++tape`](). ~zod/try=> (scan "" spac:poja) "" ~zod/try=> (scan " " spac:poja) " " ~zod/try=> `*`(scan `tape`~[' ' ' ' ' ' `@`9 ' ' ' ' `@`13] spac:poja) [32 32 32 9 32 32 13 0] ~zod/try=> (scan " m " spac:poja) ! {1 4} ! exit

++ws

Allow prefix whitespace ++ ws |*(sef=_rule ;~(pfix spac sef)) Parser modifier. Produces a rule that allows for a whitespace before applying `sef`. `sef` is a [`++rule`](). ~zod/try=> (rash ' 4' digs:poja) ! {1 1} ! exit ~zod/try=> (rash ' 4' (ws digs):poja) "4" ~zod/try=> (rash ''' 4 ''' (ws digs):poja) "4" Plumbing --------

++mayb

Maybe parse ++ mayb |*(bus=_rule ;~(pose bus (easy ""))) Parser modifier. Need to document, an example showing failure. ~zod/try=> (abox:poja 1^1 "not-an-array") [p=[p=1 q=1] q=~] ~zod/try=> ((mayb abox):poja 1^1 "not-an-array") [p=[p=1 q=1] q=[~ [p="" q=[p=[p=1 q=1] q="not-an-array"]]]]

++twel

Weld two tapes ++ twel |=([a=tape b=tape] (weld a b)) Concatenates two tapes, `a` and `b`, producing a `++tape`. `a` is a [`++tape`](). `b` is a [`++tape`](). ~zod/try=> (twel "sam" "hok"):poja ~[~~s ~~a ~~m ~~h ~~o ~~k] ~zod/try=> (twel "kre" ""):poja ~[~~k ~~r ~~e]

++piec

Parse char to list ++ piec |* bus=_rule (cook |=(a=@ [a ~]) bus) :: Parser modifer. Parses an atom with `bus` and then wraps it in a [`++list`](). `bus` is a [`++rule`](). ~zod/try=> (scan "4" (piec:poja dem:ag)) [4 ~]

++pojo

Print JSON ++ pojo :: print json |= val=json ^- tape ?~ val "null" ?- -.val %a ;: weld "[" =| rez=tape |- ^+ rez ?~ p.val rez $(p.val t.p.val, rez :(weld rez ^$(val i.p.val) ?~(t.p.val ~ ","))) "]" == :: %b ?:(p.val "true" "false") %n (trip p.val) %s ;: welp "\"" %+ reel (turn (trip p.val) jesc) |=([p=tape q=tape] (welp +<)) "\"" == %o ;: welp "\{" =+ viz=(~(tap by p.val) ~) =| rez=tape |- ^+ rez ?~ viz rez %= $ viz t.viz rez :(welp rez "\"" (trip p.i.viz) "\":" ^$(val q.i.viz) ?~(t.viz ~ ",")) == "}" == == :: Renders a `++json` `val` as a [`++tape`](). `val` is a [`json`](). ~zod/try=> (pojo [%n '12.6']) "12.6" ~zod/try=> (crip (pojo %n '12.6')) '12.6' ~zod/try=> (crip (pojo %s 'samtel')) '"samtel"' ~zod/try=> (crip (pojo %a ~[(jone 12) (jape "ha")])) '[12,"ha"]' ~zod/try=> (crip (pojo %a ~[(jone 12) ~ (jape "ha")])) '[12,null,"ha"]' ~zod/try=> (crip (pojo %o (mo sale/(jone 12) same/b/| ~))) '{"same":false,"sale":12}'

++poxo

Print XML ++ poxo :: node to tape =< |=(a=manx `tape`(apex a ~)) |_ unq=? :: unq Renders a `++manx` `a` as a [`++tape`](). `a` is a [`++manx`](). ~zod/try=> (poxo ;div;) "
" ~zod/try=> (poxo ;div:(p a)) "

" ~zod/try=> (poxo ;div:(p:"tree > text" a)) "

tree > text

"

++apex

Inner XML printer ++ apex :: top level |= [mex=manx rez=tape] ^- tape ?: ?=([%$ [[%$ *] ~]] g.mex) (escp v.i.a.g.mex rez) =+ man=`mane`n.g.mex =. unq |(unq =(%script man) =(%style man)) =+ tam=(name man) =. rez :(weld "" rez) =+ att=`mart`a.g.mex :- '<' %+ welp tam =. rez ['>' (many c.mex rez)] ?~(att rez [' ' (attr att rez)]) :: Renders a `++manx` as a [`++tape`](), appending a suffix `rez\`. `rez` is a [`++tape`](). ~zod/try=> (apex:poxo ;div; "") "
" ~zod/try=> (apex:poxo ;div:(p a) ""). "

" ~zod/try=> (apex:poxo ;div:(p a) "--sfix") "

--sfix" ~zod/try=> (apex:poxo ;div:(p:"tree > text" a) "") "

tree > text

" ~zod/try=> (~(apex poxo &) ;div:(p:"tree > text" a) "") "

tree > text

"

++attr

Print attributes ++ attr :: attributes to tape |= [tat=mart rez=tape] ^- tape ?~ tat rez =. rez $(tat t.tat) ;: weld (name n.i.tat) "=\"" (escp(unq |) v.i.tat '"' ?~(t.tat rez [' ' rez])) == Render XML attributes as a [`++tape`](). `tat` is a [`++mart`](). `rez` is a [`++tape`](). ~zod/try=> (attr:poxo ~ "") "" ~zod/try=> (crip (attr:poxo ~[sam/"hem" [%tok %ns]^"reptor"] "")) 'sam="hem" tok:ns="reptor"' ~zod/try=> (crip (attr:poxo ~[sam/"hem" [%tok %ns]^"reptor"] "|appen")) 'sam="hem" tok:ns="reptor"|appen'

++escp

Escape XML ++ escp :: escape for xml |= [tex=tape rez=tape] ?: unq (weld tex rez) =+ xet=`tape`(flop tex) |- ^- tape ?~ xet rez %= $ xet t.xet rez ?- i.xet 34 ['&' 'q' 'u' 'o' 't' ';' rez] 38 ['&' 'a' 'm' 'p' ';' rez] 39 ['&' '#' '3' '9' ';' rez] 60 ['&' 'l' 't' ';' rez] 62 ['&' 'g' 't' ';' rez] * [i.xet rez] == == :: Escapes the XML special characters `"`, `&`, `'`, `<`, `>`. `tex`is a [`++tape`](). `rez` is a [`++tape`](). ~zod/try=> (escp:poxo "astra" ~) ~[~~a ~~s ~~t ~~r ~~a] ~zod/try=> `tape`(escp:poxo "astra" ~) "astra" ~zod/try=> `tape`(escp:poxo "x > y" ~) "x > y" ~zod/try=> `tape`(~(escp poxo &) "x > y" ~) "x > y"

++name

Print name ++ name :: name to tape |= man=mane ^- tape ?@ man (trip man) (weld (trip -.man) `tape`[':' (trip +.man)]) :: Renders a `++mane` as a `++tape`. `man` is a [`++mane`](). ~zod/try=> (name:poxo %$) "" ~zod/try=> (name:poxo %ham) "ham" ~zod/try=> (name:poxo %ham^%tor) "ham:tor"

++many

Print node list ++ many :: nodelist to tape |= [lix=(list manx) rez=tape] |- ^- tape ?~ lix rez (apex i.lix $(lix t.lix)) :: Renders multiple XML nodes as a [`++tape`]() `lix` is a [`++list`]() of [`++manx`](). `rez` is a [`++tape`](). ~zod/try=> (many:poxo ~ "") "" ~zod/try=> (many:poxo ;"hare" "") "hare" ~zod/try=> (many:poxo ;"hare;{lep}ton" "") "hareton" ~zod/try=> ;"hare;{lep}ton" [[[%~. [%~. "hare"] ~] ~] [[%lep ~] ~] [[%~. [%~. "ton"] ~] ~] ~] ------------------------------------------------------------------------

++poxa

Parse XML ++ poxa :: xml parser =< |=(a=cord (rush a apex)) |% Parses an XML node from a [`++cord`](), producing a unit [`++manx`](). `a` is a [`++cord`](). ~zod/try=> (poxa '
') [~ [g=[n=%div a=~] c=~]] ~zod/try=> (poxa ' ') [~ [g=[n=%html a=~] c=~[[g=[n=%head a=~] c=~] [g=[n=%body a=~] c=~]]]] ~zod/try=> (poxa '