4f: Parsing (Rule-Builders)
+bass
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+ifix
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
++ 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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+stew
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
++ 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
+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
+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