mirror of
https://github.com/urbit/shrub.git
synced 2024-12-17 07:14:52 +03:00
653 lines
19 KiB
Markdown
653 lines
19 KiB
Markdown
section 2eC, parsing (custom rules)
|
|
===================================
|
|
|
|
<h3 id="++cold"><code>++cold</code></h3>
|
|
|
|
Replace with constant
|
|
|
|
++ cold :: replace w/ constant
|
|
~/ %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]]]
|
|
::
|
|
|
|
Parser modifier. Accepts a rule `sef` and produces a parser that
|
|
produces a constant `cus`, if `sef` is successful.
|
|
|
|
`cus` is a constant [noun]().
|
|
|
|
`sef` is a [`++rule`]().
|
|
|
|
~zod/try=> ((cold %foo (just 'a')) [[1 1] "abc"])
|
|
[p=[p=1 q=2] q=[~ u=[p=%foo q=[p=[p=1 q=2] q="bc"]]]]
|
|
~zod/try=> ((cold %foo (just 'a')) [[1 1] "bc"])
|
|
[p=[p=1 q=1] q=~]
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++cook"><code>++cook</code></h3>
|
|
|
|
Apply gate
|
|
|
|
++ cook :: apply gate
|
|
~/ %cook
|
|
|* [poq=_,* 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]]]
|
|
::
|
|
|
|
Parser modifier. Produces a parser that takes a (successful) result of a
|
|
rule `sef` and slams it through `poq`.
|
|
|
|
`poq` is a [gate]().
|
|
|
|
`sef` is a [`++rule`]().
|
|
|
|
~zod/try=> ((cook ,@ud (just 'a')) [[1 1] "abc"])
|
|
[p=[p=1 q=2] q=[~ u=[p=97 q=[p=[p=1 q=2] q="bc"]]]]
|
|
~zod/try=> ((cook ,@tas (just 'a')) [[1 1] "abc"])
|
|
[p=[p=1 q=2] q=[~ u=[p=%a q=[p=[p=1 q=2] q="bc"]]]]
|
|
~zod/try=> ((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"]]]]
|
|
~zod/try=> ((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"]]]]
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++easy"><code>++easy</code></h3>
|
|
|
|
Always parse
|
|
|
|
++ easy :: always parse
|
|
~/ %easy
|
|
|* huf=*
|
|
~/ %fun
|
|
|= tub=nail
|
|
^- (like ,_huf)
|
|
[p=p.tub q=[~ u=[p=huf q=tub]]]
|
|
::
|
|
|
|
Parser generator. Produces a parser that succeeds with given noun `huf`
|
|
without consuming any text.
|
|
|
|
~zod/try=> ((easy %foo) [[1 1] "abc"])
|
|
[p=[p=1 q=1] q=[~ [p=%foo q=[p=[p=1 q=1] q="abc"]]]]
|
|
~zod/try=> ((easy %foo) [[1 1] "bc"])
|
|
[p=[p=1 q=1] q=[~ [p=%foo q=[p=[p=1 q=1] q="bc"]]]]
|
|
~zod/try=> ((easy 'a') [[1 1] "bc"])
|
|
[p=[p=1 q=1] q=[~ [p='a' q=[p=[p=1 q=1] q="bc"]]]]
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++fail"><code>++fail</code></h3>
|
|
|
|
Never parse
|
|
|
|
++ fail |=(tub=nail [p=p.tub q=~]) :: never parse
|
|
|
|
Produces an [edge]() at the same text position ([hair]()) with a failing
|
|
result (`q=~`).
|
|
|
|
`tub` is a [`++nail`]().
|
|
|
|
~zod/try=> (fail [[1 1] "abc"])
|
|
[p=[p=1 q=1] q=~]
|
|
~zod/try=> (fail [[p=1.337 q=70] "Parse me, please?"])
|
|
[p=[p=1.337 q=70] q=~]
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++full"><code>++full</code></h3>
|
|
|
|
Parse to end
|
|
|
|
++ full :: parse to end
|
|
|* sef=_rule
|
|
|= tub=nail
|
|
=+ vex=(sef tub)
|
|
?~(q.vex vex ?:(=(~ q.q.u.q.vex) vex [p=p.vex q=~]))
|
|
::
|
|
|
|
Accepts a [`++nail`](), `tub`, and produces a parser that succeeds only
|
|
when a `tub` success consumes the remainder of the [tape]().
|
|
|
|
`sef` is a [`++rule`]().
|
|
|
|
~zod/try=> ((full (just 'a')) [[1 1] "ab"])
|
|
[p=[p=1 q=2] q=~]
|
|
~zod/try=> ((full (jest 'ab')) [[1 1] "ab"])
|
|
[p=[p=1 q=3] q=[~ u=[p='ab' q=[p=[p=1 q=3] q=""]]]]
|
|
~zod/try=> ((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=""]]]]
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++funk"><code>++funk</code></h3>
|
|
|
|
Add to tape
|
|
|
|
++ funk :: add to tape first
|
|
|* [pre=tape sef=_rule]
|
|
|= tub=nail
|
|
(sef p.tub (weld pre q.tub))
|
|
::
|
|
|
|
Parser modifier: prepend text to tape before applying parser.
|
|
|
|
`pre` is a [`++tape`]()
|
|
|
|
`sef` is a [`++rule`]()
|
|
|
|
~zod/try=> ((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"]]]]
|
|
~zod/try=> ((funk "parse" (just 'a')) [[1 4] " me"])
|
|
[p=[p=1 q=4] q=~]
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++here"><code>++here</code></h3>
|
|
|
|
Place-based apply
|
|
|
|
++ here :: place-based apply
|
|
~/ %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]]]
|
|
::
|
|
|
|
Parser modifier. Similar to [`++cook`](), 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.
|
|
|
|
`hez` is a [gate]().
|
|
|
|
`sef` is a [`++rule`]()
|
|
|
|
~zod/try=> (scan "abc" (star alf))
|
|
"abc"
|
|
~zod/try=> (scan "abc" (here |*(^ +<) (star alf)))
|
|
[[[p=1 q=1] p=1 q=4] "abc"]
|
|
~zod/try=> (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]]
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++inde"><code>++inde</code></h3>
|
|
|
|
Indentation block
|
|
|
|
++ inde |* sef=_rule :: indentation block
|
|
|= 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))
|
|
::
|
|
|
|
Apply rule to indented block starting at current column number, omitting
|
|
the leading whitespace.
|
|
|
|
`sef` is a [`++rule`]()
|
|
|
|
~zod/try=> (scan "abc" (inde (star ;~(pose prn (just `@`10)))))
|
|
"abc"
|
|
~zod/try=> (scan "abc" (star ;~(pose prn (just `@`10))))
|
|
"abc"
|
|
~zod/try=> (scan " abc\0ade" ;~(pfix ace ace (star ;~(pose prn (just `@`10)))))
|
|
"abc
|
|
de"
|
|
~zod/try=> (scan " abc\0ade" ;~(pfix ace ace (inde (star ;~(pose prn (just `@`10))))))
|
|
! {1 6}
|
|
! exit
|
|
~zod/try=> (scan " abc\0a de" ;~(pfix ace ace (inde (star ;~(pose prn (just `@`10))))))
|
|
"abc
|
|
de"
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++jest"><code>++jest</code></h3>
|
|
|
|
Match a cord
|
|
|
|
++ jest :: match a cord
|
|
|= daf=@t
|
|
|= tub=nail
|
|
=+ fad=daf
|
|
|- ^- (like ,@t)
|
|
?: =(0 daf)
|
|
[p=p.tub q=[~ u=[p=fad q=tub]]]
|
|
?: |(?=(~ q.tub) !=((end 3 1 daf) i.q.tub))
|
|
(fail tub)
|
|
$(p.tub (lust i.q.tub p.tub), q.tub t.q.tub, daf (rsh 3 1 daf))
|
|
::
|
|
|
|
Match and consume a cord.
|
|
|
|
`daf` is a `@t`
|
|
|
|
~zod/try=> ((jest 'abc') [[1 1] "abc"])
|
|
[p=[p=1 q=4] q=[~ [p='abc' q=[p=[p=1 q=4] q=""]]]]
|
|
~zod/try=> (scan "abc" (jest 'abc'))
|
|
'abc'
|
|
~zod/try=> (scan "abc" (jest 'acb'))
|
|
! {1 2}
|
|
! 'syntax-error'
|
|
! exit
|
|
~zod/try=> ((jest 'john doe') [[1 1] "john smith"])
|
|
[p=[p=1 q=6] q=~]
|
|
~zod/try=> ((jest 'john doe') [[1 1] "john doe"])
|
|
[p=[p=1 q=9] q=[~ [p='john doe' q=[p=[p=1 q=9] q=""]]]]
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++just"><code>++just</code></h3>
|
|
|
|
Match a char
|
|
|
|
++ just :: XX redundant, jest
|
|
~/ %just :: match a char
|
|
|= daf=char
|
|
~/ %fun
|
|
|= tub=nail
|
|
^- (like char)
|
|
?~ q.tub
|
|
(fail tub)
|
|
?. =(daf i.q.tub)
|
|
(fail tub)
|
|
(next tub)
|
|
::
|
|
|
|
Match and consume a single character.
|
|
|
|
`daf` is a [`++char`]()
|
|
|
|
~zod/try=> ((just 'a') [[1 1] "abc"])
|
|
[p=[p=1 q=2] q=[~ [p=~~a q=[p=[p=1 q=2] q="bc"]]]]
|
|
~zod/try=> (scan "abc" (just 'a'))
|
|
! {1 2}
|
|
! 'syntax-error'
|
|
! exit
|
|
~zod/try=> (scan "a" (just 'a'))
|
|
~~a
|
|
~zod/try=> (scan "%" (just '%'))
|
|
~~~25.
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++knee"><code>++knee</code></h3>
|
|
|
|
Recursive parsers
|
|
|
|
++ knee :: callbacks
|
|
|* [gar=* sef=_|.(rule)]
|
|
|= tub=nail
|
|
^- (like ,_gar)
|
|
((sef) tub)
|
|
::
|
|
|
|
Used for recursive parsers, which would otherwise be infinite when
|
|
compiled.
|
|
|
|
`gar` is a noun.
|
|
|
|
`sef` is a [gate]() that accepts a [`++rule`]()
|
|
|
|
~zod/try=> |-(;~(plug prn ;~(pose $ (easy ~))))
|
|
! rest-loop
|
|
! exit
|
|
~zod/try=> |-(;~(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 ...
|
|
]
|
|
>
|
|
~zod/try=> (scan "abcd" |-(;~(plug prn ;~(pose (knee *tape |.(^$)) (easy ~)))))
|
|
[~~a "bcd"]
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++mask"><code>++mask</code></h3>
|
|
|
|
Match char
|
|
|
|
++ mask :: match char in set
|
|
~/ %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)
|
|
::
|
|
|
|
Parser generator. Matches the next character if it is in a list of
|
|
characters.
|
|
|
|
`bud` is a list of [`++char`]()
|
|
|
|
~zod/try=> (scan "a" (mask "cba"))
|
|
~~a
|
|
~zod/try=> ((mask "abc") [[1 1] "abc"])
|
|
[p=[p=1 q=2] q=[~ [p=~~a q=[p=[p=1 q=2] q="bc"]]]]
|
|
~zod/try=> ((mask "abc") [[1 1] "bbc"])
|
|
[p=[p=1 q=2] q=[~ [p=~~b q=[p=[p=1 q=2] q="bc"]]]]
|
|
~zod/try=> ((mask "abc") [[1 1] "dbc"])
|
|
[p=[p=1 q=1] q=~]
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++next"><code>++next</code></h3>
|
|
|
|
Consume char
|
|
|
|
++ next :: consume a char
|
|
|= tub=nail
|
|
^- (like char)
|
|
?~ q.tub
|
|
(fail tub)
|
|
=+ zac=(lust i.q.tub p.tub)
|
|
[zac [~ i.q.tub [zac t.q.tub]]]
|
|
::
|
|
|
|
Consume any character, producing it as a result.
|
|
|
|
`tub` is a [`++nail`]()
|
|
|
|
~zod/try=> (next [[1 1] "ebc"])
|
|
[p=[p=1 q=2] q=[~ [p=~~e q=[p=[p=1 q=2] q="bc"]]]]
|
|
~zod/try=> (next [[1 1] "john jumps jones"])
|
|
[p=[p=1 q=2] q=[~ [p=~~j q=[p=[p=1 q=2] q="ohn jumps jones"]]]]
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++sear"><code>++sear</code></h3>
|
|
|
|
Conditional `++cook`
|
|
|
|
++ sear :: conditional cook
|
|
|* [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]]]
|
|
::
|
|
|
|
Conditional [`++cook`](). Slams the result through a gate that produces
|
|
a unit; if that unit is empty, fail.
|
|
|
|
`tub` is a [`++nail`](/doc/hoon/library/1#++nail)
|
|
|
|
~zod/try=> ((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"]]]]
|
|
~zod/try=> ((sear |=(* ~) (just 'a')) [[1 1] "abc"])
|
|
[p=[p=1 q=2] q=~]
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++shim"><code>++shim</code></h3>
|
|
|
|
Char in range
|
|
|
|
++ shim :: match char in range
|
|
~/ %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)
|
|
::
|
|
|
|
Match characters within a range.
|
|
|
|
`les` and `mos` are atoms, `@`.
|
|
|
|
~zod/try=> ((shim 'a' 'z') [[1 1] "abc"])
|
|
[p=[p=1 q=2] q=[~ [p=~~a q=[p=[p=1 q=2] q="bc"]]]]
|
|
~zod/try=> ((shim 'a' 'Z') [[1 1] "abc"])
|
|
[p=[p=1 q=1] q=~]
|
|
~zod/try=> ((shim 'a' 'Z') [[1 1] "Abc"])
|
|
[p=[p=1 q=2] q=[~ [p=~~~41. q=[p=[p=1 q=2] q="bc"]]]]
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++stag"><code>++stag</code></h3>
|
|
|
|
Add label
|
|
|
|
++ stag :: add a label
|
|
~/ %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]]]
|
|
::
|
|
|
|
Add a label to an edge parsed by a rule.
|
|
|
|
`gob` is a noun.
|
|
|
|
`sef` is a rule.
|
|
|
|
~zod/try=> ((stag %foo (just 'a')) [[1 1] "abc"])
|
|
[p=[p=1 q=2] q=[~ u=[p=[%foo ~~a] q=[p=[p=1 q=2] q="bc"]]]]
|
|
~zod/try=> ((stag "xyz" (jest 'abc')) [[1 1] "abc"])
|
|
[p=[p=1 q=4] q=[~ u=[p=["xyz" 'abc'] q=[p=[p=1 q=4] q=""]]]]
|
|
~zod/try=> ((stag 10.000 (shim 0 100)) [[1 1] "abc"])
|
|
[p=[p=1 q=2] q=[~ u=[p=[10.000 ~~a] q=[p=[p=1 q=2] q="bc"]]]]
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++stet"><code>++stet</code></h3>
|
|
|
|
Add faces
|
|
|
|
++ stet
|
|
|* leh=(list ,[?(@ [@ @]) _rule])
|
|
|-
|
|
?~ leh
|
|
~
|
|
[i=[p=-.i.leh q=+.i.leh] t=$(leh t.leh)]
|
|
::
|
|
|
|
Add `[p q]` faces to range-parser pairs in a list.
|
|
|
|
`leh` is a list of range-parsers.
|
|
|
|
~zod/try=> (stet (limo [[5 (just 'a')] [1 (jest 'abc')] [[1 1] (shim 0 200)]
|
|
[[1 10] (cold %foo (just 'a'))]~]))
|
|
~[
|
|
[p=5 q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
|
|
[p=1 q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
|
|
[p=[1 1] q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
|
|
[p=[1 10] q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
|
|
]
|
|
~zod/try=> [[[1 1] (just 'a')] [[2 1] (shim 0 200)] ~]
|
|
[ [[1 1] <1.tnv [tub=[p=[p=@ud q=@ud] q=""] <1.ktu [daf=@tD <414.fvk 101.jzo 1.ypj %164>]>]>]
|
|
[[2 1] <1.fvg [tub=[p=[p=@ud q=@ud] q=""] <1.khu [[les=@ mos=@] <414.fvk 101.jzo 1.ypj %164>]>]>]
|
|
~
|
|
]
|
|
~zod/try=> (stet (limo [[[1 1] (just 'a')] [[2 1] (shim 0 200)] ~]))
|
|
~[
|
|
[p=[1 1] q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
|
|
[p=[2 1] q=<1.lrk [tub=[p=[p=@ud q=@ud] q=""] <1.nqy [daf=@tD <394.imz 97.kdz 1.xlc %164>]>]>]
|
|
]
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++stew"><code>++stew</code></h3>
|
|
|
|
Switch by first
|
|
|
|
++ 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)
|
|
?: (vor 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)
|
|
?: (vor 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)
|
|
::
|
|
|
|
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 the tape's first character falls in.
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++stir"><code>++stir</code></h3>
|
|
|
|
Parse repeatedly
|
|
|
|
++ stir :: parse repeatedly
|
|
~/ %stir
|
|
|* [rud=* raq=_|*([a=* b=*] [a b]) fel=_rule]
|
|
~/ %fun
|
|
|= tub=nail
|
|
^- (like ,_rud)
|
|
=+ vex=(fel tub)
|
|
?~ q.vex
|
|
[p.vex [~ rud tub]]
|
|
=+ wag=$(tub q.u.q.vex)
|
|
?> ?=(^ q.wag)
|
|
[(last p.vex p.wag) [~ (raq p.u.q.vex p.u.q.wag) q.u.q.wag]]
|
|
::
|
|
|
|
Parse with rule as many times as possible, and fold over results with a
|
|
binary gate.
|
|
|
|
`rud` is a noun.
|
|
|
|
`raq` is a gate that takes two nouns and produces a cell.
|
|
|
|
`fel` is a rule.
|
|
|
|
~zod/try=> (scan "abc" (stir *@ add prn))
|
|
294
|
|
~zod/try=> (roll "abc" add)
|
|
b=294
|
|
|
|
------------------------------------------------------------------------
|
|
|
|
<h3 id="++stun"><code>++stun</code></h3>
|
|
|
|
Parse several times
|
|
|
|
++ stun :: parse several times
|
|
|* [[les=@ mos=@] fel=_rule]
|
|
|= tub=nail
|
|
^- (like (list ,_(wonk (fel))))
|
|
?: =(0 mos)
|
|
[p.tub [~ ~ tub]]
|
|
=+ vex=(fel tub)
|
|
?~ q.vex
|
|
?: =(0 les)
|
|
[p.vex [~ ~ tub]]
|
|
vex
|
|
=+ ^= wag %= $
|
|
les ?:(=(0 les) 0 (dec les))
|
|
mos ?:(=(0 mos) 0 (dec mos))
|
|
tub q.u.q.vex
|
|
==
|
|
?~ q.wag
|
|
wag
|
|
[p.wag [~ [p.u.q.vex p.u.q.wag] q.u.q.wag]]
|
|
|
|
Parse bounded number of times.
|
|
|
|
`[les=@ mos=@]` is a cell of atoms indicating the bounds.
|
|
|
|
`fel` is a rule.
|
|
|
|
~zod/try=> ((stun [5 10] prn) [1 1] "aquickbrownfoxran")
|
|
[p=[p=1 q=11] q=[~ [p="aquickbrow" q=[p=[p=1 q=11] q="nfoxran"]]]]
|
|
~zod/try=> ((stun [5 10] prn) [1 1] "aquickbro")
|
|
[p=[p=1 q=10] q=[~ [p="aquickbro" q=[p=[p=1 q=10] q=""]]]]
|
|
~zod/try=> ((stun [5 10] prn) [1 1] "aqui")
|
|
[p=[p=1 q=5] q=~]
|
|
|
|
------------------------------------------------------------------------
|