# 4f: Parsing (Rule-Builders)

## `+bass` <a href="#bass" id="bass"></a>

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

#### Accepts

`.wuc` is an `$atom`.

`.tyd` is a `$rule`.

#### Produces

A `$rule`.

#### Source

```hoon
++  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` <a href="#boss" id="boss"></a>

Parser modifier, LSB.

Ordered `+list` as `$atom` of a `$base`.

#### Accepts

`.wuc` is an `$atom`.

`.tyd` is a `$rule`.

#### Produces

A `$rule`.

#### Source

```hoon
++  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` <a href="#cold" id="cold"></a>

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

```hoon
++  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` <a href="#cook" id="cook"></a>

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

```hoon
++  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` <a href="#easy" id="easy"></a>

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

```hoon
++  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` <a href="#fuss" id="fuss"></a>

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

```hoon
++  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` <a href="#full" id="full"></a>

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

```hoon
++  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` <a href="#funk" id="funk"></a>

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

```hoon
++  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` <a href="#here" id="here"></a>

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

```hoon
++  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` <a href="#inde" id="inde"></a>

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

```hoon
++  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` <a href="#ifix" id="ifix"></a>

Infix.

Parser modifier: surround with pair of `$rule`s, the output of which is discarded.

#### Accepts

`.fel` is a pair of `$rule`s.

`.hof` is a `$rule`.

#### Produces

A `$rule`.

#### Source

```hoon
++  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` <a href="#jest" id="jest"></a>

Match a cord.

Match and consume a cord.

#### Accepts

`.daf` is a `@t`.

#### Produces

A `$rule`.

#### Source

```hoon
++  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` <a href="#just" id="just"></a>

Match a char.

Match and consume a single character.

#### Accepts

`.daf` is a `$char`

#### Produces

A `$rule`.

#### Source

```hoon
++  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` <a href="#knee" id="knee"></a>

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

```hoon
++  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` <a href="#mask" id="mask"></a>

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

```hoon
++  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` <a href="#more" id="more"></a>

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

```hoon
++  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` <a href="#most" id="most"></a>

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

```hoon
++  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` <a href="#next" id="next"></a>

Consume char.

Consume any character, producing it as a result.

#### Accepts

`.tub` is a `$nail`.

#### Produces

An `$edge`.

#### Source

```hoon
++  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` <a href="#perk" id="perk"></a>

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

```hoon
++  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` <a href="#plus" id="plus"></a>

List of at least one match.

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

#### Accepts

`.fel` is a `$rule`.

#### Produces

A `$rule`.

#### Source

```hoon
++  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` <a href="#punt" id="punt"></a>

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

```hoon
++  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` <a href="#sear" id="sear"></a>

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

```hoon
++  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` <a href="#shim" id="shim"></a>

Char in range.

Match characters (`$char`) within a range.

#### Accepts

`.les` is an `$atom`.

`.mos` is an `$atom`.

#### Produces

A `$rule`.

#### Source

```hoon
++  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` <a href="#slug" id="slug"></a>

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

```hoon
++  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` <a href="#stag" id="stag"></a>

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

```hoon
++  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` <a href="#star" id="star"></a>

List of matches.

Parser modifier: parse `+list` of matches.

#### Accepts

`.fel` is a `$rule`.

#### Produces

A `$rule`.

#### Source

```hoon
++  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` <a href="#stet" id="stet"></a>

Add faces.

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

#### Accepts

`.leh` is a list of range-parsers.

#### Produces

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

#### Source

```hoon
++  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` <a href="#stew" id="stew"></a>

Switch by first char.

Parser generator. From an associative `+list` of characters or character ranges to `$rule`s, construct a `+map`, and parse `$tape`s only with `$rule`s 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

```hoon
++  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` <a href="#stir" id="stir"></a>

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 `$noun`s and produces a cell.

`.fel` is a `$rule`.

#### Produces

A `$rule`.

#### Source

```hoon
++  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` <a href="#stun" id="stun"></a>

Parse several times.

Parse bounded number of times.

#### Accepts

`.lig` is a cell of `$atom`s (`[@ @]`) indicating the bounds.

`.fel` is a `$rule`.

#### Produces

A `$rule`.

#### Source

```hoon
++  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=~]
```

***
