+++ title = "4e: Parsing (Combinators)" weight = 32 template = "doc.html" +++ ## `++bend` Conditional composer Parsing composer: connects the `++edge` `vex` with the subsequent `++rule` `sab` as an optional suffix, using gate `raq` to compose or reject its result. If there is no suffix, or if the suffix fails to be composed with the current result, the current result is produced. Used to map a group of rules to a specified output. #### Accepts `raq` is a gate. `sab` is a rule. `vex` is an edge. #### Produces A `++rule`. #### Source ```hoon ++ bend :: conditional comp ~/ %bend |* raq/_|*({a/* b/*} [~ u=[a b]]) ~/ %fun |* {vex/edge sab/rule} ?~ q.vex vex =+ yit=(sab q.u.q.vex) =+ yur=(last p.vex p.yit) ?~ q.yit [p=yur q=q.vex] =+ vux=(raq p.u.q.vex p.u.q.yit) ?~ vux [p=yur q=q.vex] [p=yur q=[~ u=[p=u.vux q=q.u.q.yit]]] :: ``` #### Examples ``` > (;~((bend |=([a/char b/char] ?.(=(a b) ~ (some +(a))))) prn prn) [1 1] "qs") [p=[p=1 q=3] q=[~ u=[p=~~q q=[p=[p=1 q=2] q="s"]]]] > (;~((bend |=([a/char b/char] ?.(=(a b) ~ (some +(a))))) prn prn) [1 1] "qqq") [p=[p=1 q=3] q=[~ u=[p=~~r q=[p=[p=1 q=3] q="q"]]]] > (scan "aa" ;~((bend |=([a/char b/char] ?.(=(a b) ~ (some +(a))))) prn prn)) ~~b > (scan "ba" ;~((bend |=([a/char b/char] ?.(=(a b) ~ (some +(a))))) prn prn)) ! {1 3} ! exit > `(unit @tas)`(scan "" ;~((bend) (easy ~) sym)) ~ > `(unit @tas)`(scan "sep" ;~((bend) (easy ~) sym)) [~ %sep] ``` --- ## `++comp` Arbitrary compose Parsing composer: connects the `++edge` `vex` with a following `++rule` `sab`, combining the contents of `vex` with the result of `sab` using a binary gate `raq`. Used to fold over the results of several `++rules`. #### Accepts `raq` is a gate that accepts a cell of two nouns, `a` and `b`, and produces a cell of two nouns. `sab` is a rule. `vex` is an edge. #### Produces A `++rule`. #### Source ```hoon ++ comp ~/ %comp |* raq/_|*({a/* b/*} [a b]) :: arbitrary compose ~/ %fun |* {vex/edge sab/rule} ~! +< ?~ q.vex vex =+ yit=(sab q.u.q.vex) =+ yur=(last p.vex p.yit) ?~ q.yit [p=yur q=q.yit] [p=yur q=[~ u=[p=(raq p.u.q.vex p.u.q.yit) q=q.u.q.yit]]] :: ``` #### Examples ``` > (scan "123" ;~((comp |=([a/@u b/@u] (add a b))) dit dit dit)) 6 > (scan "12" ;~((comp |=([a/@u b/@u] (add a b))) dit dit dit)) ! {1 3} ! exit ``` --- ## `++fail` Never parse Produces an `++edge` at the same text position (`++hair`) with a failing result (`q=~`). #### Accepts `tub` is a `++nail`. #### Produces An `++edge`. #### Source ```hoon ++ fail |=(tub/nail [p=p.tub q=~]) :: never parse ``` #### Examples ``` > (fail [[1 1] "abc"]) [p=[p=1 q=1] q=~] > (fail [[p=1.337 q=70] "Parse me, please?"]) [p=[p=1.337 q=70] q=~] ``` --- ## `++glue` Skip delimiter Parsing composer: connects an `++edge` `vex` with a following `++rule` `sab` by parsing the `++rule` `bus` (the delimiting symbol) and throwing out the result. #### Accepts `bus` is a `++rule`. `sab` is a `++rule`. `vex` is an `++edge`. #### Produces #### Source ```hoon ++ glue :: add rule ~/ %glue |* bus/rule ~/ %fun |* {vex/edge sab/rule} (plug vex ;~(pfix bus sab)) :: ``` #### Examples ``` > (scan "200|mal|bon" ;~((glue bar) dem sym sym)) [q=200 7.102.829 7.237.474] > `[@u @tas @tas]`(scan "200|mal|bon" ;~((glue bar) dem sym sym)) [200 %mal %bon] > (scan "200|;|bon" ;~((glue bar) dem sem sym)) [q=200 ~~~3b. 7.237.474] > (scan "200.;.bon" ;~((glue dot) dem sem sym)) [q=200 ~~~3b. 7.237.474] ``` --- ## `++less` Parse unless Parsing composer: if an `++edge` `vex` reflects a success, fail. Otherwise, connect `vex` with the following `++rule`. #### Accepts `sab` is a `++rule`. `vex` is an `++edge`. #### Produces #### Source ```hoon ++ less :: no first and second |* {vex/edge sab/rule} ?~ q.vex =+ roq=(sab) [p=(last p.vex p.roq) q=q.roq] (fail +<.sab) :: ``` #### Examples ``` > (scan "sas-/lo" (star ;~(less lus bar prn))) "sas-/lo" > (scan "sas-/l+o" (star ;~(less lus bar prn))) ! {1 8} ! exit > (scan "sas|-/lo" (star ;~(less lus bar prn))) ! {1 5} ! exit ``` --- ## `++pfix` Discard first rule Parsing composer: connects an `++edge` `vex` with two subsequent `++rule`s, ignoring the result of the first and producing the result of the second. #### Accepts `vex` is an edge. #### Produces #### Source ```hoon ++ pfix :: discard first rule ~/ %pfix (comp |*({a/* b/*} b)) ``` #### Examples ``` > `@t`(scan "%him" ;~(pfix cen sym)) 'him' > (scan "+++10" ;~(pfix (star lus) dem)) q=10 ``` --- ## `++plug` Parse to tuple Parsing composer: connects an `++edge` `vex` with a following `++rule` `sab`, producing a cell of both the results. See also: the monad applicator ;\~ for a more detailed explanation. #### Accepts `sab` is a `++rule`. `vex` is an `++edge`. #### Produces #### Source ```hoon ++ plug :: first then second ~/ %plug |* {vex/edge sab/rule} ?~ q.vex vex =+ yit=(sab q.u.q.vex) =+ yur=(last p.vex p.yit) ?~ q.yit [p=yur q=q.yit] [p=yur q=[~ u=[p=[p.u.q.vex p.u.q.yit] q=q.u.q.yit]]] :: ``` #### Examples ``` > (scan "1..20" ;~(plug dem dot dot dem)) [q=1 ~~~. ~~~. q=20] > (scan "moke/~2014.1.1" ;~(plug sym fas nuck:so)) [1.701.539.693 ~~~2f. [% p=[p=~.da q=170.141.184.500.766.106.671.844.917.172.921.958.400]]] > ;;(,[@tas @t ~ %da @da] (scan "moke/~2014.1.1" ;~(plug sym fas nuck:so))) [%moke '/' ~ %da ~2014.1.1] ``` --- ## `++pose` Parse options Parsing composer: if `vex` reflects a failure, connect it with the following rule `sab`. See also: the monad applicator ;\~ #### Accepts `sab` is a `++rule`. `vex` is an `++edge`. #### Produces #### Source ```hoon ++ pose :: first or second ~/ %pose |* {vex/edge sab/rule} ?~ q.vex =+ roq=(sab) [p=(last p.vex p.roq) q=q.roq] vex :: ``` #### Examples ``` > `@t`(scan "+" ;~(pose lus tar cen)) '+' > `@t`(scan "*" ;~(pose lus tar cen)) '*' > `@t`(scan "%" ;~(pose lus tar cen)) '%' > `@t`(scan "-" ;~(pose lus tar cen)) ! {1 1} ! exit ``` --- ## `++sfix` Discard second rule Parsing composer: connects `++edge`s `vex` with two subsequent `++rule`s returning the result of the first and discarding the result of the second. #### Accepts `a` is the result of parsing the first `++rule`. `b` is the result of of parsing the second `++rule`. #### Produces #### Source ```hoon ++ sfix :: discard second rule ~/ %sfix (comp |*({a/* b/*} a)) ``` #### Examples ``` > `@t`(scan "him%" ;~(sfix sym cen)) 'him' > (scan "10+++" ;~(sfix dem (star lus))) q=10 ``` --- ## `++simu` First and second Parsing composer: if an `++edge` `vex` reflects a failure, fail. Otherwise, connect `vex` with the following `++rule`. #### Accepts `sab` is a `++rule`. `vex` is an `++edge`. #### Produces #### Source ```hoon ++ simu :: first and second |* {vex/edge sab/rule} ?~ q.vex vex =+ roq=(sab) roq :: ``` #### Examples ``` > (scan "~zod" scat:vast) [%dtzy p=%p q=0] > (scan "%zod" scat:vast) [%dtzz p=%tas q=6.582.138] > (scan "%zod" ;~(simu cen scat:vast)) [%dtzz p=%tas q=6.582.138] > (scan "~zod" ;~(simu cen scat:vast)) ! {1 1} ! exit ``` ---