4f: Parsing (Rule-Builders)

+bass

Parser modifier: LSB ordered +list as atom of a $base.

Accepts

wuc is an atom.

tyd is a +rule.

Produces

A +rule.

Source

++  bass
  |*  [wuc=@ tyd=rule]
  %+  cook
    |=  waq=(list @)
    %+  roll
      waq
    =|([p=@ q=@] |.((add p (mul wuc q))))
  tyd

Examples

> (scan "123" (bass 10 (star dit)))
q=123
> (scan "123" (bass 8 (star dit)))
q=83
> `@ub`(scan "123" (bass 8 (star dit)))
0b101.0011

+boss

Parser modifier: LSB

Ordered +list as atom of a $base.

Accepts

wuc is an atom.

tyd is a +rule.

Produces

A +rule.

Source

++  boss
  |*  [wuc=@ tyd=rule]
  %+  cook
    |=  waq=(list @)
    %+  reel
      waq
    =|([p=@ q=@] |.((add p (mul wuc q))))
  tyd

Examples

> (scan "123" (boss 10 (star dit)))
321

> `@t`(scan "bam" (boss 256 (star alp)))
'bam'

> `@ux`(scan "bam" (boss 256 (star alp)))
0x6d.6162

+cold

Replace with constant

Parser modifier. Accepts a +rule sef and produces a parser that produces a constant cus, assuming sef is successful.

Accepts

cus is a constant noun.

sef is a +rule.

Produces

An +edge.

Source

++  cold
  ~/  %cold
  |*  [cus=* sef=rule]
  ~/  %fun
  |=  tub=nail
  =+  vex=(sef tub)
  ?~  q.vex
    vex
  [p=p.vex q=[~ u=[p=cus q=q.u.q.vex]]]

Examples

> ((cold %foo (just 'a')) [[1 1] "abc"])
[p=[p=1 q=2] q=[~ u=[p=%foo q=[p=[p=1 q=2] q="bc"]]]]

> ((cold %foo (just 'a')) [[1 1] "bc"])
[p=[p=1 q=1] q=~]

+cook

Apply gate

Parser modifier. Produces a parser that takes a (successful) result of a +rule sef and slams it through poq.

Accepts

poq is a gate.

sef is a +rule.

Produces

A +rule.

Source

++  cook
  ~/  %cook
  |*  [poq=gate sef=rule]
  ~/  %fun
  |=  tub=nail
  =+  vex=(sef tub)
  ?~  q.vex
    vex
  [p=p.vex q=[~ u=[p=(poq p.u.q.vex) q=q.u.q.vex]]]

Examples

> ((cook ,@ud (just 'a')) [[1 1] "abc"])
[p=[p=1 q=2] q=[~ u=[p=97 q=[p=[p=1 q=2] q="bc"]]]]

> ((cook ,@tas (just 'a')) [[1 1] "abc"])
[p=[p=1 q=2] q=[~ u=[p=%a q=[p=[p=1 q=2] q="bc"]]]]

> ((cook |=(a=@ +(a)) (just 'a')) [[1 1] "abc"])
[p=[p=1 q=2] q=[~ u=[p=98 q=[p=[p=1 q=2] q="bc"]]]]

> ((cook |=(a=@ `@t`+(a)) (just 'a')) [[1 1] "abc"])
[p=[p=1 q=2] q=[~ u=[p='b' q=[p=[p=1 q=2] q="bc"]]]]

+easy

Always parse

Parser generator. Produces a parser that succeeds with given noun +huf without consuming any text.

Accepts

+huf is a noun.

Produces

A +rule.

Source

++  easy
  ~/  %easy
  |*  huf=*
  ~/  %fun
  |=  tub=nail
  ^-  (like _huf)
  [p=p.tub q=[~ u=[p=huf q=tub]]]

Examples

> ((easy %foo) [[1 1] "abc"])
[p=[p=1 q=1] q=[~ [p=%foo q=[p=[p=1 q=1] q="abc"]]]]

> ((easy %foo) [[1 1] "bc"])
[p=[p=1 q=1] q=[~ [p=%foo q=[p=[p=1 q=1] q="bc"]]]]

> ((easy 'a') [[1 1] "bc"])
[p=[p=1 q=1] q=[~ [p='a' q=[p=[p=1 q=1] q="bc"]]]]

+fuss

Has A or B?

If string sic is parsed: %.y. If string non is parsed: %.n. Otherwise, fail.

Accepts

sic is a @t.

non is a @t.

Produces

A +rule.

Source

++  fuss
  |=  [sic=@t non=@t]
  ;~(pose (cold %& (jest sic)) (cold %| (jest non)))

Examples

> (rash 'foo' (fuss 'foo' 'bar'))
%.y

> (rash 'bar' (fuss 'foo' 'bar'))
%.n

> (rash 'baz' (fuss 'foo' 'bar'))
{1 3}
syntax error

+full

Parse to end

Parser modifier. Accepts a +rule sef, and produces a parser that succeeds only when the $tape of tub is fully consumed using sef.

Accepts

sef is a +rule.

Produces

A +rule.

Source

++  full
  |*  sef=rule
  |=  tub=nail
  =+  vex=(sef tub)
  ?~(q.vex vex ?:(=(~ q.q.u.q.vex) vex [p=p.vex q=~]))

Examples

> ((full (just 'a')) [[1 1] "ab"])
[p=[p=1 q=2] q=~]

> ((full (jest 'ab')) [[1 1] "ab"])
[p=[p=1 q=3] q=[~ u=[p='ab' q=[p=[p=1 q=3] q=""]]]]

> ((full ;~(plug (just 'a') (just 'b'))) [[1 1] "ab"])
[p=[p=1 q=3] q=[~ u=[p=['a' 'b'] q=[p=[p=1 q=3] q=""]]]]

+funk

Add to tape

Parser modifier: prepend text to $tape before applying parser.

Accepts

pre is a $tape

sef is a +rule

Produces

A +rule.

Source

++  funk
  |*  [pre=tape sef=rule]
  |=  tub=nail
  (sef p.tub (weld pre q.tub))

Examples

> ((funk "abc prefix-" (jest 'abc')) [[1 1] "to be parsed"])
[p=[p=1 q=4] q=[~ [p='abc' q=[p=[p=1 q=4] q=" prefix-to be parsed"]]]]

> ((funk "parse" (just 'a')) [[1 4] " me"])
[p=[p=1 q=4] q=~]

+here

Place-based apply

Parser modifier. Similar to +cook in that it produces a parser that takes a (successful) result of sef and slams it through hez. hez accepts a $pint .a and a noun .b, which is what the parser parsed.

Accepts

hez is a gate.

sef is a +rule

Produces

A +rule.

Source

++  here
  ~/  %here
  =+  [hez=|=([a=pint b=*] [a b]) sef=*rule]
  |@
  ++  $
    ~/  %fun
    |=  tub=nail
    =+  vex=(sef tub)
    ?~  q.vex
      vex
    [p=p.vex q=[~ u=[p=(hez [p.tub p.q.u.q.vex] p.u.q.vex) q=q.u.q.vex]]]
  --

Examples

> (scan "abc" (star alf))
"abc"

> (scan "abc" (here |*(^ +<) (star alf)))
[[[p=1 q=1] p=1 q=4] "abc"]

> (scan "abc" (star (here |*(^ +<) alf)))
~[[[[p=1 q=1] p=1 q=2] ~~a] [[[p=1 q=2] p=1 q=3] ~~b] [[[p=1 q=3] p=1 q=4] ~~c]]

+inde

Indentation block

Apply +rule to indented block starting at current column number, omitting the leading whitespace.

Accepts

sef is a +rule.

Produces

A +rule.

Source

++  inde  |*  sef=rule
  |=  nail  ^+  (sef)
  =+  [har tap]=[p q]:+<
  =+  lev=(fil 3 (dec q.har) ' ')
  =+  eol=(just `@t`10)
  =+  =-  roq=((star ;~(pose prn ;~(sfix eol (jest lev)) -)) har tap)
      ;~(simu ;~(plug eol eol) eol)
  ?~  q.roq  roq
  =+  vex=(sef har(q 1) p.u.q.roq)
  =+  fur=p.vex(q (add (dec q.har) q.p.vex))
  ?~  q.vex  vex(p fur)
  =-  vex(p fur, u.q -)
  :+  &3.vex
    &4.vex(q.p (add (dec q.har) q.p.&4.vex))
  =+  res=|4.vex
  |-  ?~  res  |4.roq
  ?.  =(10 -.res)  [-.res $(res +.res)]
  (welp [`@t`10 (trip lev)] $(res +.res))

Examples

> `tape`(scan "   foo\0a   bar" ;~(pfix ace ace ace (inde (star ;~(pose prn (just '\0a'))))))
"foo\0abar"

Discussion

Note the amount of indentation whitespace to be stripped from the beginning of each line is determined by the value of .q (the column) in the +hair when +inde is first called. This means something like the +pfix expression in the example above is necessary to set the level of indentation. Additionally, the +rule given to +inde must consume the whole line including the line ending.


+ifix

Infix

Parser modifier: surround with pair of +rules, the output of which is discarded.

Accepts

fel is a pair of +rules.

+hof is a +rule.

Produces

A +rule.

Source

++  ifix
  |*  [fel=[rule rule] hof=rule]
  ~!  +<
  ~!  +<:-.fel
  ~!  +<:+.fel
  ;~(pfix -.fel ;~(sfix hof +.fel))

Examples

> (scan "-40-" (ifix [hep hep] dem))
40

> (scan "4my4" (ifix [dit dit] (star alf)))
"my"

+jest

Match a cord

Match and consume a cord.

Accepts

daf is a @t.

Produces

A +rule.

Source

++  jest
  |=  daf=@t
  |=  tub=nail
  =+  fad=daf
  |-  ^-  (like @t)
  ?:  =(`@`0 daf)
    [p=p.tub q=[~ u=[p=fad q=tub]]]
  ?:  |(?=(~ q.tub) !=((end 3 daf) i.q.tub))
    (fail tub)
  $(p.tub (lust i.q.tub p.tub), q.tub t.q.tub, daf (rsh 3 daf))

Examples

> ((jest 'abc') [[1 1] "abc"])
[p=[p=1 q=4] q=[~ [p='abc' q=[p=[p=1 q=4] q=""]]]]

> (scan "abc" (jest 'abc'))
'abc'

> (scan "abc" (jest 'acb'))
! {1 2}
! 'syntax-error'
! exit

> ((jest 'john doe') [[1 1] "john smith"])
[p=[p=1 q=6] q=~]

> ((jest 'john doe') [[1 1] "john doe"])
[p=[p=1 q=9] q=[~ [p='john doe' q=[p=[p=1 q=9] q=""]]]]

+just

Match a char

Match and consume a single character.

Accepts

daf is a +char

Produces

A +rule.

Source

++  just
  ~/  %just
  |=  daf=char
  ~/  %fun
  |=  tub=nail
  ^-  (like char)
  ?~  q.tub
    (fail tub)
  ?.  =(daf i.q.tub)
    (fail tub)
  (next tub)

Examples

> ((just 'a') [[1 1] "abc"])
[p=[p=1 q=2] q=[~ [p='a' q=[p=[p=1 q=2] q="bc"]]]]

> (scan "abc" (just 'a'))
! {1 2}
! 'syntax-error'
! exit

> (scan "a" (just 'a'))
'a'

> (scan "%" (just '%'))
'%'

+knee

Recursive parsers

Used for recursive parsers, which would otherwise be infinite when compiled.

Accepts

+gar is a noun.

sef is a gate that accepts a +rule

Produces

A +rule.

Source

++  knee
  =|  [gar=* sef=_|.(*rule)]
  |@  ++  $
        |=  tub=nail
        ^-  (like _gar)
        ((sef) tub)
  --

Examples

> |-(;~(plug prn ;~(pose $ (easy ~))))
! rest-loop
! exit

> |-(;~(plug prn ;~(pose (knee *tape |.(^$)) (easy ~))))
< 1.obo
  [ c=c=tub=[p=[p=@ud q=@ud] q=""]
      b
    < 1.bes
      [ c=tub=[p=[p=@ud q=@ud] q=""]
        b=<1.tnv [tub=[p=[p=@ud q=@ud] q=""] <1.ktu [daf=@tD <414.fvk 101.jzo 1.ypj %164>]>]>
        a=<1.fvg [tub=[p=[p=@ud q=@ud] q=""] <1.khu [[les=@ mos=@] <414.fvk 101.jzo 1.ypj %164>]>]>
        v=<414.fvk 101.jzo 1.ypj %164>
      ]
    >
      a
    ... 450 lines omitted ...
  ]
>

> (scan "abcd" |-(;~(plug prn ;~(pose (knee *tape |.(^$)) (easy ~)))))
['a' "bcd"]

+mask

Match char

Parser generator. Matches the next character if it is in a list of characters.

Accepts

bud is a list of +char

Produces

A +rule.

Source

++  mask
  ~/  %mask
  |=  bud=(list char)
  ~/  %fun
  |=  tub=nail
  ^-  (like char)
  ?~  q.tub
    (fail tub)
  ?.  (lien bud |=(a=char =(i.q.tub a)))
    (fail tub)
  (next tub)

Examples

> (scan "a" (mask "cba"))
'a'

> ((mask "abc") [[1 1] "abc"])
[p=[p=1 q=2] q=[~ [p='a' q=[p=[p=1 q=2] q="bc"]]]]

> ((mask "abc") [[1 1] "bbc"])
[p=[p=1 q=2] q=[~ [p='b' q=[p=[p=1 q=2] q="bc"]]]]

> ((mask "abc") [[1 1] "dbc"])
[p=[p=1 q=1] q=~]

+more

Parse list with delimiter

Parser modifier: Parse a list of matches using a delimiter +rule.

Accepts

bus is a +rule.

fel is a +rule.

Produces

A +rule.

Source

++  more
  |*  [bus=rule fel=rule]
  ;~(pose (most bus fel) (easy ~))

Examples

> (scan "" (more ace dem))
~

> (scan "40 20" (more ace dem))
[40 [i=20 t=~]]

> (scan "40 20 60 1 5" (more ace dem))
[40 [i=20 t=~[60 1 5]]]

+most

Parse list of at least one match

Parser modifier: parse a +list of at least one match using a delimiter +rule.

Accepts

bus is a +rule.

fel is a +rule.

Produces

A +rule.

Source

++  most
  |*  [bus=rule fel=rule]
  ;~(plug fel (star ;~(pfix bus fel)))

Examples

> (scan "40 20" (most ace dem))
[40 [i=20 t=~]]

> (scan "40 20 60 1 5" (most ace dem))
[40 [i=20 t=~[60 1 5]]]

> (scan "" (most ace dem))
! {1 1}
! exit

+next

Consume char

Consume any character, producing it as a result.

Accepts

tub is a +nail

Produces

An +edge.

Source

++  next
  |=  tub=nail
  ^-  (like char)
  ?~  q.tub
    (fail tub)
  =+  zac=(lust i.q.tub p.tub)
  [zac [~ i.q.tub [zac t.q.tub]]]

Examples

> (next [[1 1] "ebc"])
[p=[p=1 q=2] q=[~ [p='e' q=[p=[p=1 q=2] q="bc"]]]]

> (next [[1 1] "john jumps jones"])
[p=[p=1 q=2] q=[~ [p='j' q=[p=[p=1 q=2] q="ohn jumps jones"]]]]

+perk

Parse cube fork

Given .a, a list of @tas, match any one in the list and produce it. Note the list should not be a +list type, but just a null-terminated cell like ~[%foo %bar %baz]. The type produced will be a union of the items in the given list, so you can use a ?- expression on the output.

Accepts

.a is a (pole @tas).

Produces

A +rule.

Source

++  perk
  |*  a=(pole @tas)
  ?~  a  fail
  ;~  pose
    (cold -.a (jest -.a))
    $(a +.a)
  ==

Examples

> (scan "foo" (perk ~[%foo %bar]))
%foo

> (scan "bar" (perk ~[%foo %bar]))
%bar

> (scan "baz" (perk ~[%foo %bar]))
{1 3}
syntax error

+plus

List of at least one match.

Parser modifier: parse +list of at least one match.

Accepts

fel is a +rule.

Produces

A +rule.

Source

++  plus  |*(fel=rule ;~(plug fel (star fel)))          ::

Examples

> (scan ">>>>" (cook lent (plus gar)))
4

> (scan "-  - " (plus ;~(pose ace hep)))
['-' [i=' ' t=~[' ' '-' ' ']]]

> `tape`(scan "-  - " (plus ;~(pose ace hep)))
"-  - "

> `(pole ,@t)`(scan "-  - " (plus ;~(pose ace hep)))
['-' [' ' [' ' ['-' [' ' ~]]]]]

+punt

Unitized parse

Either successfully apply +rule .a and produce a +unit of the result, or produce ~.

Accepts

.a is a +rule.

Produces

A +rule.

Source

++  punt  |*([a=rule] ;~(pose (stag ~ a) (easy ~)))

Example

> ((punt (jest 'foo')) 1^1 "foo")
[p=[p=1 q=4] q=[~ u=[p=[~ 'foo'] q=[p=[p=1 q=4] q=~]]]]

> ((punt (jest 'foo')) 1^1 "bar")
[p=[p=1 q=1] q=[~ [p=~ q=[p=[p=1 q=1] q="bar"]]]]

+sear

Conditional +cook

Conditional +cook. Slams the result through a gate that produces a unit; if that unit is empty, fail.

Accepts

pyq is a gate that produces a +unit.

sef is a +rule.

Produces

A +rule.

Source

++  sear
  |*  [pyq=$-(* (unit)) sef=rule]
  |=  tub=nail
  =+  vex=(sef tub)
  ?~  q.vex
    vex
  =+  gey=(pyq p.u.q.vex)
  ?~  gey
    [p=p.vex q=~]
  [p=p.vex q=[~ u=[p=u.gey q=q.u.q.vex]]]

Examples

> ((sear |=(a=* ?@(a (some a) ~)) (just 'a')) [[1 1] "abc"])
[p=[p=1 q=2] q=[~ u=[p=97 q=[p=[p=1 q=2] q="bc"]]]]

> ((sear |=(* ~) (just 'a')) [[1 1] "abc"])
[p=[p=1 q=2] q=~]

+shim

Char in range

Match characters (+char) within a range.

Accepts

les is an atom.

mos is an atom.

Produces

A +rule.

Source

++  shim
  ~/  %shim
  |=  [les=@ mos=@]
  ~/  %fun
  |=  tub=nail
  ^-  (like char)
  ?~  q.tub
    (fail tub)
  ?.  ?&((gte i.q.tub les) (lte i.q.tub mos))
    (fail tub)
  (next tub)

Examples

> `tape`(rash 'abc' (plus (shim 'a' 'z')))
"abc"

> `tape`(rash 'ABC' (plus (shim 'a' 'z')))
{1 1}
syntax error

+slug

Use gate to parse delimited list

Parser modifier: By composing with a gate, parse a delimited +list of matches.

Accepts

raq is a binary gate.

bus is a +rule.

fel is a +rule.

Produces

A +rule.

Source

++  slug
  |*  raq=_=>(~ |*([a=* b=*] [a b]))
  |*  [bus=rule fel=rule]
  ;~((comp raq) fel (stir +<+.raq raq ;~(pfix bus fel)))

Examples

> (scan "20+5+110" ((slug add) lus dem))
135

> `@t`(scan "a b c" ((slug |=(a=[@t @t] (cat 3 a))) ace alp))
'abc'

+stag

Add label

Add a label to an +edge parsed by a +rule.

Accepts

gob is a noun.

sef is a rule.

Produces

A +rule.

Source

++  stag
  ~/  %stag
  |*  [gob=* sef=rule]
  ~/  %fun
  |=  tub=nail
  =+  vex=(sef tub)
  ?~  q.vex
    vex
  [p=p.vex q=[~ u=[p=[gob p.u.q.vex] q=q.u.q.vex]]]

Examples

> (rash 'abc' (stag %foo (jest 'abc')))
[%foo 'abc']

+star

List of matches

Parser modifier: parse +list of matches.

Accepts

fel is a +rule.

Produces

A +rule.

Source

++  star
  |*  fel=rule
  (stir `(list _(wonk *fel))`~ |*([a=* b=*] [a b]) fel)

Examples

> (scan "aaaaa" (just 'a'))
! {1 2}
! 'syntax-error'
! exit

> (scan "aaaaa" (star (just 'a')))
"aaaaa"

> (scan "abcdef" (star (just 'a')))
! {1 2}
! 'syntax-error'
! exit

> (scan "abcabc" (star (jest 'abc')))
<|abc abc|>

> (scan "john smith" (star (shim 0 200)))
"john smith"

+stet

Add faces

Add faces [p q] to range-parser pairs in a list. Typically used in combination with +stew.

Accepts

leh is a list of range-parsers.

Produces

A (list [p=?(@ [@ @]) q=rule]).

Source

++  stet
  |*  leh=(list [?(@ [@ @]) rule])
  |-
  ?~  leh
    ~
  [i=[p=-.i.leh q=+.i.leh] t=$(leh t.leh)]

Examples

> =rule %-  stew
        %-  stet
        %-  limo
        :~
          [['a' 'z'] (cook |=(a=@ (sub a 32)) alp)]
          [['A' 'Z'] (cook |=(a=@ (add a 32)) alp)]
        ==

> `tape`(rash 'fooBARbaz' (star rule))
"FOObarBAZ"

+stew

Switch by first char

Parser generator. From an associative +list of characters or character ranges to +rules, construct a +map, and parse $tapes only with +rules associated with a range that the $tape's first character falls in.

Accepts

leh is a (list [p=?(@ [@ @]) q=rule]), where .p is a +char or +char range.

Produces

A +rule.

Source

++  stew                                                ::  switch by first char
  ~/  %stew
  |*  leh=(list [p=?(@ [@ @]) q=rule])                  ::  char+range keys
  =+  ^=  wor                                           ::  range complete lth
      |=  [ort=?(@ [@ @]) wan=?(@ [@ @])]
      ?@  ort
        ?@(wan (lth ort wan) (lth ort -.wan))
      ?@(wan (lth +.ort wan) (lth +.ort -.wan))
  =+  ^=  hel                                           ::  build parser map
      =+  hel=`(tree _?>(?=(^ leh) i.leh))`~
      |-  ^+  hel
      ?~  leh
        ~
      =+  yal=$(leh t.leh)
      |-  ^+  hel
      ?~  yal
        [i.leh ~ ~]
      ?:  (wor p.i.leh p.n.yal)
        =+  nuc=$(yal l.yal)
        ?>  ?=(^ nuc)
        ?:  (mor p.n.yal p.n.nuc)
          [n.yal nuc r.yal]
        [n.nuc l.nuc [n.yal r.nuc r.yal]]
      =+  nuc=$(yal r.yal)
      ?>  ?=(^ nuc)
      ?:  (mor p.n.yal p.n.nuc)
        [n.yal l.yal nuc]
      [n.nuc [n.yal l.yal l.nuc] r.nuc]
  ~%  %fun  ..^$  ~
  |=  tub=nail
  ?~  q.tub
    (fail tub)
  |-
  ?~  hel
    (fail tub)
  ?:  ?@  p.n.hel
        =(p.n.hel i.q.tub)
      ?&((gte i.q.tub -.p.n.hel) (lte i.q.tub +.p.n.hel))
    ::  (q.n.hel [(lust i.q.tub p.tub) t.q.tub])
    (q.n.hel tub)
  ?:  (wor i.q.tub p.n.hel)
    $(hel l.hel)
  $(hel r.hel)

Examples

> =rule %-  stew
        %-  stet
        %-  limo
        :~
          [['a' 'z'] (cook |=(a=@ (sub a 32)) alp)]
          [['A' 'Z'] (cook |=(a=@ (add a 32)) alp)]
        ==

> `tape`(rash 'fooBARbaz' (star rule))
"FOObarBAZ"

+stir

Parse repeatedly

Parse with +rule as many times as possible, and fold over results with a binary gate.

Accepts

rud is a noun.

raq is a gate that takes two nouns and produces a cell.

fel is a +rule.

Produces

A +rule.

Source

++  stir
  ~/  %stir
  |*  [rud=* raq=_=>(~ |*([a=* b=*] [a b])) fel=rule]
  ~/  %fun
  |=  tub=nail
  ^-  (like _rud)
  ::
  ::  lef: successful interim parse results (per .fel)
  ::  wag: initial accumulator (.rud in .tub at farthest success)
  ::
  =+  ^=  [lef wag]
    =|  lef=(list _(fel tub))
    |-  ^-  [_lef (pair hair [~ u=(pair _rud nail)])]
    =+  vex=(fel tub)
    ?~  q.vex
      :-  lef
      [p.vex [~ rud tub]]
    $(lef [vex lef], tub q.u.q.vex)
  ::
  ::  fold .lef into .wag, combining results with .raq
  ::
  %+  roll  lef
  |=  _[vex=(fel tub) wag=wag]  :: q.vex is always (some)
  ^+  wag
  :-  (last p.vex p.wag)
  [~ (raq p.u.+.q.vex p.u.q.wag) q.u.q.wag]

Examples

> (scan "abc" (stir *@ add prn))
294

> (roll "abc" add)
294

+stun

Parse several times

Parse bounded number of times.

Accepts

lig is a cell of atoms ([@ @]) indicating the bounds.

fel is a +rule.

Produces

A +rule.

Source

++  stun
  ~/  %stun
  |*  [lig=[@ @] fel=rule]
  |=  tub=nail
  ^-  (like (list _(wonk (fel))))
  ?:  =(0 +.lig)
    [p.tub [~ ~ tub]]
  =+  vex=(fel tub)
  ?~  q.vex
    ?:  =(0 -.lig)
      [p.vex [~ ~ tub]]
    vex
  =+  ^=  wag  %=  $
                 -.lig  ?:(=(0 -.lig) 0 (dec -.lig))
                 +.lig  ?:(=(0 +.lig) 0 (dec +.lig))
                 tub  q.u.q.vex
               ==
  ?~  q.wag
    wag
  [p.wag [~ [p.u.q.vex p.u.q.wag] q.u.q.wag]]

Examples

> ((stun [5 10] prn) [1 1] "aquickbrownfoxran")
[p=[p=1 q=11] q=[~ [p="aquickbrow" q=[p=[p=1 q=11] q="nfoxran"]]]]

> ((stun [5 10] prn) [1 1] "aquickbro")
[p=[p=1 q=10] q=[~ [p="aquickbro" q=[p=[p=1 q=10] q=""]]]]

> ((stun [5 10] prn) [1 1] "aqui")
[p=[p=1 q=5] q=~]

Last updated