on f3ca521 help sign in
1195 lines 21 kB history raw
1+++
2title = "4f: Parsing (Rule-Builders)"
3weight = 33
4template = "doc.html"
5aliases = ["/docs/reference/library/4f"]
6+++
7### `++bass`
9Parser modifier: LSB
10ordered `++list` as atom of a `++base`.
12#### Accepts
14`wuc` is an atom.
16`tyd` is a `++rule`.
18#### Produces
20A `++rule`.
22#### Source
24```hoon
25 ++ bass
26 |* {wuc/@ tyd/rule}
27 %+ cook
28 |= waq/(list @)
29 %+ roll
30 waq
31 =|({p/@ q/@} |.((add p (mul wuc q))))
32 tyd
33 ::
34```
36#### Examples
38```
39 > (scan "123" (bass 10 (star dit)))
40 q=123
41 > (scan "123" (bass 8 (star dit)))
42 q=83
43 > `@ub`(scan "123" (bass 8 (star dit)))
44 0b101.0011
45```
48---
50### `++boss`
52Parser modifier: LSB
54Ordered `++list` as atom of a `++base`.
56#### Accepts
58`wuc` is an atom.
60`tyd` is a `++rule`.
62#### Produces
64A `++rule`.
66#### Source
68```hoon
69 ++ boss
70 |* {wuc/@ tyd/rule}
71 %+ cook
72 |= waq/(list @)
73 %+ reel
74 waq
75 =|({p/@ q/@} |.((add p (mul wuc q))))
76 tyd
77 ::
78```
80#### Examples
82```
83 > (scan "123" (boss 10 (star dit)))
84 q=321
86 > `@t`(scan "bam" (boss 256 (star alp)))
87 'bam'
89 > `@ux`(scan "bam" (boss 256 (star alp)))
90 0x6d.6162
91```
93---
94### `++cold`
96Replace with constant
98Parser modifier. Accepts a `++rule` `sef` and produces a parser that
99produces a constant `cus`, assuming `sef` is successful.
101#### Accepts
103`cus` is a constant noun.
105`sef` is a `++rule`.
107#### Produces
109An `++edge`.
111#### Source
113```hoon
114 ++ cold :: replace w+ constant
115 ~/ %cold
116 |* {cus/* sef/rule}
117 ~/ %fun
118 |= tub/nail
119 =+ vex=(sef tub)
120 ?~ q.vex
121 vex
122 [p=p.vex q=[~ u=[p=cus q=q.u.q.vex]]]
123```
125#### Examples
127```
128 > ((cold %foo (just 'a')) [[1 1] "abc"])
129 [p=[p=1 q=2] q=[~ u=[p=%foo q=[p=[p=1 q=2] q="bc"]]]]
131 > ((cold %foo (just 'a')) [[1 1] "bc"])
132 [p=[p=1 q=1] q=~]
133```
136---
137### `++cook`
139Apply gate
141Parser modifier. Produces a parser that takes a (successful) result of a
142`++rule` `sef` and slams it through `poq`.
144#### Accepts
146`poq` is a gate.
148`sef` is a `++rule`.
150#### Produces
152An `++rule`.
154#### Source
156```hoon
157 ++ cook :: apply gate
158 ~/ %cook
159 |* {poq/gate sef/rule}
160 ~/ %fun
161 |= tub/nail
162 =+ vex=(sef tub)
163 ?~ q.vex
164 vex
165 [p=p.vex q=[~ u=[p=(poq p.u.q.vex) q=q.u.q.vex]]]
166 ::
167```
169#### Examples
171```
172 > ((cook ,@ud (just 'a')) [[1 1] "abc"])
173 [p=[p=1 q=2] q=[~ u=[p=97 q=[p=[p=1 q=2] q="bc"]]]]
175 > ((cook ,@tas (just 'a')) [[1 1] "abc"])
176 [p=[p=1 q=2] q=[~ u=[p=%a q=[p=[p=1 q=2] q="bc"]]]]
178 > ((cook |=(a=@ +(a)) (just 'a')) [[1 1] "abc"])
179 [p=[p=1 q=2] q=[~ u=[p=98 q=[p=[p=1 q=2] q="bc"]]]]
181 > ((cook |=(a=@ `@t`+(a)) (just 'a')) [[1 1] "abc"])
182 [p=[p=1 q=2] q=[~ u=[p='b' q=[p=[p=1 q=2] q="bc"]]]]
183```
186---
187### `++easy`
189Always parse
191Parser generator. Produces a parser that succeeds with given noun `huf`
192without consuming any text.
194#### Accepts
196`huf` is a noun.
198#### Produces
200A `++rule`.
202#### Source
204```hoon
205 ++ easy :: always parse
206 ~/ %easy
207 |* huf=*
208 ~/ %fun
209 |= tub=nail
210 ^- (like ,_huf)
211 [p=p.tub q=[~ u=[p=huf q=tub]]]
212 ::
213```
215#### Examples
217```
218 > ((easy %foo) [[1 1] "abc"])
219 [p=[p=1 q=1] q=[~ [p=%foo q=[p=[p=1 q=1] q="abc"]]]]
221 > ((easy %foo) [[1 1] "bc"])
222 [p=[p=1 q=1] q=[~ [p=%foo q=[p=[p=1 q=1] q="bc"]]]]
224 > ((easy 'a') [[1 1] "bc"])
225 [p=[p=1 q=1] q=[~ [p='a' q=[p=[p=1 q=1] q="bc"]]]]
226```
229---
230### `++full`
232Parse to end
234Parser modifier. Accepts a `++rule` `sef`, and produces a parser that succeeds only
235when the of `tub` is fully consumed using `sef`.
237#### Accepts
239`sef` is a `++rule`.
241#### Produces
243A `++rule`.
245#### Source
247```hoon
248 ++ full :: parse to end
249 |* sef=_rule
250 |= tub=nail
251 =+ vex=(sef tub)
252 ?~(q.vex vex ?:(=(~ q.q.u.q.vex) vex [p=p.vex q=~]))
253 ::
254```
256#### Examples
258```
259 > ((full (just 'a')) [[1 1] "ab"])
260 [p=[p=1 q=2] q=~]
262 > ((full (jest 'ab')) [[1 1] "ab"])
263 [p=[p=1 q=3] q=[~ u=[p='ab' q=[p=[p=1 q=3] q=""]]]]
265 > ((full ;~(plug (just 'a') (just 'b'))) [[1 1] "ab"])
266 [p=[p=1 q=3] q=[~ u=[p=[~~a ~~b] q=[p=[p=1 q=3] q=""]]]]
267```
270---
271### `++funk`
273Add to tape
275Parser modifier: prepend text to `++tape` before applying parser.
277#### Accepts
279`pre` is a `++tape`
281`sef` is a `++rule`
283#### Produces
285A `++rule`.
287#### Source
289```hoon
290 ++ funk :: add to tape first
291 |* {pre/tape sef/rule}
292 |= tub/nail
293 (sef p.tub (weld pre q.tub))
294```
296#### Examples
298```
299 > ((funk "abc prefix-" (jest 'abc')) [[1 1] "to be parsed"])
300 [p=[p=1 q=4] q=[~ [p='abc' q=[p=[p=1 q=4] q=" prefix-to be parsed"]]]]
302 > ((funk "parse" (just 'a')) [[1 4] " me"])
303 [p=[p=1 q=4] q=~]
304```
307---
308### `++here`
310Place-based apply
312Parser modifier. Similar to `++cook` in that it produces a parser that takes a
313(successful) result of `sef` and slams it through `hez`. `hez` accepts a
314`++pint` `a` and a noun `b`, which is what the parser parsed.
316#### Accepts
318`hez` is a gate.
320`sef` is a `++rule`
322#### Produces
324A `++rule`.
326#### Source
328```hoon
329 ++ here :: place-based apply
330 ~/ %here
331 |* {hez/_|=({a/pint b/*} [a b]) sef/rule}
332 ~/ %fun
333 |= tub/nail
334 =+ vex=(sef tub)
335 ?~ q.vex
336 vex
337 [p=p.vex q=[~ u=[p=(hez [p.tub p.q.u.q.vex] p.u.q.vex) q=q.u.q.vex]]]
338 ::
339```
341#### Examples
343```
344 > (scan "abc" (star alf))
345 "abc"
347 > (scan "abc" (here |*(^ +<) (star alf)))
348 [[[p=1 q=1] p=1 q=4] "abc"]
350 > (scan "abc" (star (here |*(^ +<) alf)))
351 ~[[[[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]]
352```
355---
356### `++ifix`
358Infix
360Parser modifier: surround with pair of `++rule`s, the output of which is
361discarded.
363#### Accepts
365`fel` is a pair of `++rule`s.
367`hof` is a `++rule`.
369#### Produces
371A `++rule`.
373#### Source
375```hoon
376 ++ ifix
377 |* {fel/{rule rule} hof/rule}
378 ~! +<
379 ~! +<:-.fel
380 ~! +<:+.fel
381 ;~(pfix -.fel ;~(sfix hof +.fel))
382 ::
383```
385#### Examples
387```
388 > (scan "-40-" (ifix [hep hep] dem))
389 q=40
391 > (scan "4my4" (ifix [dit dit] (star alf)))
392 "my"
393```
396---
397### `++jest`
399Match a cord
401Match and consume a cord.
403#### Accepts
405`daf` is a `@t`.
407#### Produces
409An `++edge`.
411#### Source
413```hoon
414 ++ jest :: match a cord
415 |= daf/@t
416 |= tub/nail
417 =+ fad=daf
418 |- ^- (like @t)
419 ?: =(`@`0 daf)
420 [p=p.tub q=[~ u=[p=fad q=tub]]]
421 ?: |(?=($~ q.tub) !=((end 3 1 daf) i.q.tub))
422 (fail tub)
423 $(p.tub (lust i.q.tub p.tub), q.tub t.q.tub, daf (rsh 3 1 daf))
424 ::
425```
427#### Examples
429```
430 > ((jest 'abc') [[1 1] "abc"])
431 [p=[p=1 q=4] q=[~ [p='abc' q=[p=[p=1 q=4] q=""]]]]
433 > (scan "abc" (jest 'abc'))
434 'abc'
436 > (scan "abc" (jest 'acb'))
437 ! {1 2}
438 ! 'syntax-error'
439 ! exit
441 > ((jest 'john doe') [[1 1] "john smith"])
442 [p=[p=1 q=6] q=~]
444 > ((jest 'john doe') [[1 1] "john doe"])
445 [p=[p=1 q=9] q=[~ [p='john doe' q=[p=[p=1 q=9] q=""]]]]
446```
449---
450### `++just`
452Match a char
454Match and consume a single character.
456#### Accepts
458`daf` is a `++char`
460#### Produces
462A `++rule`.
464#### Source
466```hoon
467 ++ just :: XX redundant, jest
468 ~/ %just :: match a char
469 |= daf/char
470 ~/ %fun
471 |= tub/nail
472 ^- (like char)
473 ?~ q.tub
474 (fail tub)
475 ?. =(daf i.q.tub)
476 (fail tub)
477 (next tub)
478 ::
479```
481#### Examples
483```
484 > ((just 'a') [[1 1] "abc"])
485 [p=[p=1 q=2] q=[~ [p=~~a q=[p=[p=1 q=2] q="bc"]]]]
487 > (scan "abc" (just 'a'))
488 ! {1 2}
489 ! 'syntax-error'
490 ! exit
492 > (scan "a" (just 'a'))
494 ~~a
495 > (scan "%" (just '%'))
496 ~~~25.
497```
500---
501### `++knee`
503Recursive parsers
505Used for recursive parsers, which would otherwise be infinite when
506compiled.
508#### Accepts
510`gar` is a noun.
512`sef` is a gate that accepts a `++rule`
514#### Produces
516A `++rule`.
518#### Source
520```hoon
521 ++ knee :: callbacks
522 |* {gar/* sef/_|.(*rule)}
523 |= tub/nail
524 ^- (like _gar)
525 ((sef) tub)
526 ::
527```
529#### Examples
531```
532 > |-(;~(plug prn ;~(pose $ (easy ~))))
533 ! rest-loop
534 ! exit
536 > |-(;~(plug prn ;~(pose (knee *tape |.(^$)) (easy ~))))
537 < 1.obo
538 [ c=c=tub=[p=[p=@ud q=@ud] q=""]
539 b
540 < 1.bes
541 [ c=tub=[p=[p=@ud q=@ud] q=""]
542 b=<1.tnv [tub=[p=[p=@ud q=@ud] q=""] <1.ktu [daf=@tD <414.fvk 101.jzo 1.ypj %164>]>]>
543 a=<1.fvg [tub=[p=[p=@ud q=@ud] q=""] <1.khu [[les=@ mos=@] <414.fvk 101.jzo 1.ypj %164>]>]>
544 v=<414.fvk 101.jzo 1.ypj %164>
545 ]
546 >
547 a
548 ... 450 lines omitted ...
549 ]
550 >
551 > (scan "abcd" |-(;~(plug prn ;~(pose (knee *tape |.(^$)) (easy ~)))))
552 [~~a "bcd"]
553```
556---
557### `++mask`
559Match char
561Parser generator. Matches the next character if it is in a list of
562characters.
564#### Accepts
566`bud` is a list of `++char`
568#### Produces
570A `++rule`.
572#### Source
574```hoon
575 ++ mask :: match char in set
576 ~/ %mask
577 |= bud/(list char)
578 ~/ %fun
579 |= tub/nail
580 ^- (like char)
581 ?~ q.tub
582 (fail tub)
583 ?. (lien bud |=(a/char =(i.q.tub a)))
584 (fail tub)
585 (next tub)
586 ::
587```
589#### Examples
591```
592 > (scan "a" (mask "cba"))
593 ~~a
595 > ((mask "abc") [[1 1] "abc"])
596 [p=[p=1 q=2] q=[~ [p=~~a q=[p=[p=1 q=2] q="bc"]]]]
598 > ((mask "abc") [[1 1] "bbc"])
599 [p=[p=1 q=2] q=[~ [p=~~b q=[p=[p=1 q=2] q="bc"]]]]
601 > ((mask "abc") [[1 1] "dbc"])
602 [p=[p=1 q=1] q=~]
603```
605---
606### `++more`
608Parse list with delimiter
610Parser modifier: Parse a list of matches using a delimiter `++rule`.
612#### Accepts
614`bus` is a `++rule`.
616`fel` is a `++rule`.
618#### Produces
620A `++rule`.
622#### Source
624```hoon
625 ++ more
626 |* {bus/rule fel/rule}
627 ;~(pose (most bus fel) (easy ~))
628 ::
629```
631#### Examples
633```
634 > (scan "" (more ace dem))
635 ~
637 > (scan "40 20" (more ace dem))
638 [q=40 ~[q=20]]
640 > (scan "40 20 60 1 5" (more ace dem))
641 [q=40 ~[q=20 q=60 q=1 q=5]]
642```
645---
646### `++most`
648Parse list of at least one match
650Parser modifier: parse a `++list` of at least one match using a delimiter `++rule`.
652#### Accepts
654`bus` is a `++rule`.
656`fel` is a `++rule`.
658#### Produces
660A `++rule`.
662#### Source
664```hoon
665 ++ most
666 |* {bus/rule fel/rule}
667 ;~(plug fel (star ;~(pfix bus fel)))
668 ::
669```
671#### Examples
673```
674 > (scan "40 20" (most ace dem))
675 [q=40 ~[q=20]]
677 > (scan "40 20 60 1 5" (most ace dem))
678 [q=40 ~[q=20 q=60 q=1 q=5]]
680 > (scan "" (most ace dem))
681 ! {1 1}
682 ! exit
683```
686---
687### `++next`
689Consume char
691Consume any character, producing it as a result.
693#### Accepts
695`tub` is a `++nail`
697#### Produces
699An `++edge`.
701#### Source
703```hoon
704 ++ next :: consume a char
705 |= tub/nail
706 ^- (like char)
707 ?~ q.tub
708 (fail tub)
709 =+ zac=(lust i.q.tub p.tub)
710 [zac [~ i.q.tub [zac t.q.tub]]]
711 ::
712```
714#### Examples
716```
717 > (next [[1 1] "ebc"])
718 [p=[p=1 q=2] q=[~ [p=~~e q=[p=[p=1 q=2] q="bc"]]]]
720 > (next [[1 1] "john jumps jones"])
721 [p=[p=1 q=2] q=[~ [p=~~j q=[p=[p=1 q=2] q="ohn jumps jones"]]]]
722```
725---
727### `++plus`
729List of at least one match.
731Parser modifier: parse `++list` of at least one match.
733#### Accepts
735`fel` is a `++rule`.
737#### Produces
739A `++rule`.
741#### Source
743```hoon
744 ++ plus |*(fel/rule ;~(plug fel (star fel)))
745```
747#### Examples
749```
750 > (scan ">>>>" (cook lent (plus gar)))
751 4
753 > (scan "- - " (plus ;~(pose ace hep)))
754 [~~- " - "]
756 > `tape`(scan "- - " (plus ;~(pose ace hep)))
757 "- - "
759 > `(pole ,@t)`(scan "- - " (plus ;~(pose ace hep)))
760 ['-' [' ' [' ' ['-' [' ' ~]]]]]
761```
764---
765### `++sear`
767Conditional `++cook`
769Conditional `++cook`. Slams the result through a gate that produces
770a unit; if that unit is empty, fail.
772#### Accepts
774`tub` is a `++nail`.
776#### Produces
778A `++rule`.
780#### Source
782```hoon
783 ++ sear :: conditional cook
784 |* {pyq/$-(* (unit)) sef/rule}
785 |= tub/nail
786 =+ vex=(sef tub)
787 ?~ q.vex
788 vex
789 =+ gey=(pyq p.u.q.vex)
790 ?~ gey
791 [p=p.vex q=~]
792 [p=p.vex q=[~ u=[p=u.gey q=q.u.q.vex]]]
793 ::
794```
796#### Examples
798```
799 > ((sear |=(a/* ?@(a (some a) ~)) (just `a`)) [[1 1] "abc"])
800 [p=[p=1 q=2] q=[~ u=[p=97 q=[p=[p=1 q=2] q="bc"]]]]
802 > ((sear |=(* ~) (just 'a')) [[1 1] "abc"])
803 [p=[p=1 q=2] q=~]
804```
807---
808### `++shim`
810Char in range
812Match characters (`++char`) within a range.
814#### Accepts
816`les` is an atom.
818`mos` is an atom.
820#### Produces
822A `++rule`.
824#### Source
826```hoon
827 ++ shim :: match char in range
828 ~/ %shim
829 |= {les/@ mos/@}
830 ~/ %fun
831 |= tub/nail
832 ^- (like char)
833 ?~ q.tub
834 (fail tub)
835 ?. ?&((gte i.q.tub les) (lte i.q.tub mos))
836 (fail tub)
837 (next tub)
838 ::
839```
841#### Examples
843```
844 > ((shim 'a' 'z') [[1 1] "abc"])
845 [p=[p=1 q=2] q=[~ [p=~~a q=[p=[p=1 q=2] q="bc"]]]]
847 > ((shim 'a' 'Z') [[1 1] "abc"])
848 [p=[p=1 q=1] q=~]
850 > ((shim 'a' 'Z') [[1 1] "Abc"])
851 [p=[p=1 q=2] q=[~ [p=~~~41. q=[p=[p=1 q=2] q="bc"]]]]
852```
855---
856### `++slug`
858Use gate to parse delimited list
860Parser modifier: By composing with a gate, parse a delimited `++list` of
861matches.
863#### Accepts
865`bus` is a `++rule`.
867`fel` is a `++rule`.
869#### Produces
871A `++rule`.
873#### Source
875```hoon
876 ++ slug
877 |* raq/_|*({a/* b/*} [a b])
878 |* {bus/rule fel/rule}
879 ;~((comp raq) fel (stir +<+.raq raq ;~(pfix bus fel)))
880 ::
881```
883#### Examples
885```
886 > (scan "20+5+110" ((slug add) lus dem))
887 135
889 > `@t`(scan "a b c" ((slug |=(a/[@ @t] (cat 3 a))) ace alp))
890 'abc'
891```
894---
895### `++stag`
897Add label
899Add a label to an edge parsed by a rule.
901#### Accepts
903`gob` is a noun.
905`sef` is a rule.
907#### Produces
909A `++rule`.
911#### Source
913```hoon
914 ++ stag :: add a label
915 ~/ %stag
916 |* {gob/* sef/rule}
917 ~/ %fun
918 |= tub/nail
919 =+ vex=(sef tub)
920 ?~ q.vex
921 vex
922 [p=p.vex q=[~ u=[p=[gob p.u.q.vex] q=q.u.q.vex]]]
923 ::
924```
926#### Examples
928```
929 > ((stag %foo (just 'a')) [[1 1] "abc"])
930 [p=[p=1 q=2] q=[~ u=[p=[%foo ~~a] q=[p=[p=1 q=2] q="bc"]]]]
932 > ((stag "xyz" (jest 'abc')) [[1 1] "abc"])
933 [p=[p=1 q=4] q=[~ u=[p=["xyz" 'abc'] q=[p=[p=1 q=4] q=""]]]]
935 > ((stag 10.000 (shim 0 100)) [[1 1] "abc"])
936 [p=[p=1 q=2] q=[~ u=[p=[10.000 ~~a] q=[p=[p=1 q=2] q="bc"]]]]
937```
940---
941### `++star`
943List of matches
945Parser modifier: parse `++list` of matches.
947#### Accepts
949`fel` is a `++rule`.
951#### Produces
953```hoon
954 ++ star :: 0 or more times
955 |* fel/rule
956 (stir `(list _(wonk *fel))`~ |*({a/* b/*} [a b]) fel)
957```
959#### Examples
961```
962 > (scan "aaaaa" (just 'a'))
963 ! {1 2}
964 ! 'syntax-error'
965 ! exit
967 > (scan "aaaaa" (star (just 'a')))
968 "aaaaa"
970 > (scan "abcdef" (star (just 'a')))
971 ! {1 2}
972 ! 'syntax-error'
973 ! exit
975 > (scan "abcabc" (star (jest 'abc')))
976 <|abc abc|>
978 > (scan "john smith" (star (shim 0 200)))
979 "john smith"
980```
983---
984### `++stet`
986Add faces
988Add faces `[p q]` to range-parser pairs in a list.
990#### Accepts
992`leh` is a list of range-parsers.
994#### Produces
998#### Source
1000```hoon
1001 ++ stet
1002 |* leh/(list {?(@ {@ @}) rule})
1003 |-
1004 ?~ leh
1006 [i=[p=-.i.leh q=+.i.leh] t=$(leh t.leh)]
1007 ::
1008```
1010#### Examples
1012```
1013 > (stet (limo [[5 (just 'a')] [1 (jest 'abc')] [[1 1] (shim 0 200)]
1014 [[1 10] (cold %foo (just 'a'))]~]))
1015 ~[
1016 [p=5 q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
1017 [p=1 q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
1018 [p=[1 1] q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
1019 [p=[1 10] q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
1021 > [[[1 1] (just 'a')] [[2 1] (shim 0 200)] ~]
1022 [ [[1 1] <1.tnv [tub=[p=[p=@ud q=@ud] q=""] <1.ktu [daf=@tD <414.fvk 101.jzo 1.ypj %164>]>]>]
1023 [[2 1] <1.fvg [tub=[p=[p=@ud q=@ud] q=""] <1.khu [[les=@ mos=@] <414.fvk 101.jzo 1.ypj %164>]>]>]
1026 > (stet (limo [[[1 1] (just 'a')] [[2 1] (shim 0 200)] ~]))
1027 ~[
1028 [p=[1 1] q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
1029 [p=[2 1] q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
1031```
1034---
1035### `++stew`
1037Switch by first
1039```hoon
1040 ++ stew :: switch by first char
1041 ~/ %stew
1042 |* leh/(list {p/?(@ {@ @}) q/rule}) :: char+range keys
1043 =+ ^= wor :: range complete lth
1044 |= {ort/?(@ {@ @}) wan/?(@ {@ @})}
1045 ?@ ort
1046 ?@(wan (lth ort wan) (lth ort -.wan))
1047 ?@(wan (lth +.ort wan) (lth +.ort -.wan))
1048 =+ ^= hel :: build parser map
1049 =+ hel=`(tree _?>(?=(^ leh) i.leh))`~
1050 |- ^+ hel
1051 ?~ leh
1053 =+ yal=$(leh t.leh)
1054 |- ^+ hel
1055 ?~ yal
1056 [i.leh ~ ~]
1057 ?: (wor p.i.leh p.n.yal)
1058 =+ nuc=$(yal l.yal)
1059 ?> ?=(^ nuc)
1060 ?: (vor p.n.yal p.n.nuc)
1061 [n.yal nuc r.yal]
1062 [n.nuc l.nuc [n.yal r.nuc r.yal]]
1063 =+ nuc=$(yal r.yal)
1064 ?> ?=(^ nuc)
1065 ?: (vor p.n.yal p.n.nuc)
1066 [n.yal l.yal nuc]
1067 [n.nuc [n.yal l.yal l.nuc] r.nuc]
1068 ~% %fun ..^$ ~
1069 |= tub/nail
1070 ?~ q.tub
1071 (fail tub)
1072 |-
1073 ?~ hel
1074 (fail tub)
1075 ?: ?@ p.n.hel
1076 =(p.n.hel i.q.tub)
1077 ?&((gte i.q.tub -.p.n.hel) (lte i.q.tub +.p.n.hel))
1078 :: (q.n.hel [(lust i.q.tub p.tub) t.q.tub])
1079 (q.n.hel tub)
1080 ?: (wor i.q.tub p.n.hel)
1081 $(hel l.hel)
1082 $(hel r.hel)
1083 ::
1084```
1087Parser generator. From an associative `++list` of characters or character
1088ranges to `++rule`s, construct a `++map`, and parse `++tape`s only
1089with `++rules` associated with a range that the `++tape`'s first character falls in.
1093---
1094### `++stir`
1096Parse repeatedly
1098Parse with `++rule` as many times as possible, and fold over results with a
1099binary gate.
1101#### Accepts
1103`rud` is a noun.
1105`raq` is a gate that takes two nouns and produces a cell.
1107`fel` is a rule.
1109#### Produces
1111A rule.
1113#### Source
1115```hoon
1116 ++ stir
1117 ~/ %stir
1118 |* {rud/* raq/_=>(~ |*({a/* b/*} [a b])) fel/rule}
1119 ~/ %fun
1120 |= tub/nail
1121 ^- (like _rud)
1122 =+ vex=(fel tub)
1123 ?~ q.vex
1124 [p.vex [~ rud tub]]
1125 =+ wag=$(tub q.u.q.vex)
1126 ?> ?=(^ q.wag)
1127 [(last p.vex p.wag) [~ (raq p.u.q.vex p.u.q.wag) q.u.q.wag]]
1128```
1130#### Examples
1132```
1133 > (scan "abc" (stir *@ add prn))
1134 294
1136 > (roll "abc" add)
1137 b=294
1138```
1141---
1142### `++stun`
1144Parse several times
1146Parse bounded number of times.
1148#### Accepts
1150`[les=@ mos=@]` is a cell of atoms indicating the bounds.
1152`fel` is a `++rule`.
1154#### Produces
1156A `++rule`.
1158#### Source
1160```hoon
1161 ++ stun :: parse several times
1162 |* {lig/{@ @} fel/rule}
1163 |= tub/nail
1164 ^- (like (list _(wonk (fel))))
1165 ?: =(0 +.lig)
1166 [p.tub [~ ~ tub]]
1167 =+ vex=(fel tub)
1168 ?~ q.vex
1169 ?: =(0 -.lig)
1170 [p.vex [~ ~ tub]]
1171 vex
1172 =+ ^= wag %= $
1173 -.lig ?:(=(0 -.lig) 0 (dec -.lig))
1174 +.lig ?:(=(0 +.lig) 0 (dec +.lig))
1175 tub q.u.q.vex
1176 ==
1177 ?~ q.wag
1178 wag
1179 [p.wag [~ [p.u.q.vex p.u.q.wag] q.u.q.wag]]
1180```
1182#### Examples
1184```
1185 > ((stun [5 10] prn) [1 1] "aquickbrownfoxran")
1186 [p=[p=1 q=11] q=[~ [p="aquickbrow" q=[p=[p=1 q=11] q="nfoxran"]]]]
1188 > ((stun [5 10] prn) [1 1] "aquickbro")
1189 [p=[p=1 q=10] q=[~ [p="aquickbro" q=[p=[p=1 q=10] q=""]]]]
1191 > ((stun [5 10] prn) [1 1] "aqui")
1192 [p=[p=1 q=5] q=~]
1193```
1195---