4e: Parsing (Combinators)

    ++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

        ++  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

        ++  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

        ++  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

        ++  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

        ++  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 ++rules, ignoring the result of the first and producing the result of the second.

    Accepts

    vex is an edge.

    Produces

    Source

        ++  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

        ++  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

        ++  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 ++edges vex with two subsequent ++rules 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

        ++  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

        ++  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