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

***


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.urbit.org/hoon/stdlib/4f.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
