Why PARSE?
PARSE is a declarative pattern-matching dialect built into the language — not a regex library, not a parser generator, and not a runtime interpreter. Rules compile straight to C alongside the rest of your program.
Most statically-typed, compiled languages make you reach for a regex engine or a separate grammar tool with its own build step. Recoil inherits Rebol's PARSE idea and compiles it: you describe what to match with ordinary blocks, and the compiler turns it into a tight byte-oriented matcher. The same rules can drive state machines for full protocol handling.
print parse "abcd" ["ab" "cd"] ; true
print parse "cd" ["ab" | "cd"] ; true (alternation)
Status & result type
parse is a compiler-recognized form (not a library call) and a
compiled matcher for byte-oriented string parsing. It does not aim for full
Rebol PARSE compatibility.
It returns a logic!: true on full rule success,
false on failure, and false for empty rules.
Accepted inputs
Input may be a string literal, a string!, or a url!.
print parse "abcd" ["ab" "cd"]
s: make string! "abcd"
print parse s ["ab" "cd"]
Name resolution in rules
Names inside a rule resolve in this order: built-in PARSE keywords, then
cursor markers (p: / :p), then visible bindings.
Keywords: to, thru, some,
any, opt, skip, set,
copy, capture, none, end,
ahead, not, if, |.
A binding used as a rule unit must be a rule!,
string!, char!, or bitset! — anything
else is a compile-time error.
Core matching
Exact match
A string item matches at the cursor and advances by its length; a char item matches one byte.
print parse "abcd" ["ab" "cd"]
print parse "aaa" [3 #"a"]
bitset! / charset
chs: make bitset! charset ":/#?"
print parse "?" [chs]
print parse "abc?" [thru chs]
to / thru
to x seeks to the start of x; thru x
seeks through its end.
print parse "abcd" [to "cd" "cd"]
print parse "abcd" [thru "ab" "cd"]
Alternation
left | right tries the left side first and, on failure, retries
the right side from the same cursor.
print parse "cd" ["ab" | "cd"]
Repetition
some item matches 1+, any item matches 0+,
opt item matches 0 or 1.
print parse "ababab" [some "ab"]
print parse "b" [any "a" "b"]
print parse "b" [opt "a" "b"]
Numeric forms: N item (exactly N), 1 N item
(between 1 and N), 0 N item (between 0 and N).
print parse "aaab" [3 #"a" #"b"]
print parse "aab" [1 3 #"a" #"b"]
Cursor, predicates & zero-width rules
skip— consume exactly one byte.none— always succeeds, consumes nothing.end— succeeds only at input end.p:— save the cursor into slotp;:p— restore it (fails if unset).ahead rule— test a nested rule without consuming.not rule— succeed only when the nested rule fails here.
print parse "abcd" [p: thru "ab" :p "ab" thru "cd"]
print parse "a" [ahead "a" "a" end]
print parse "a" [not end some #"a"]
Captures
set — one char
Captures a single matched char into a char! target.
ch: make char! #"x"
print parse "q" [set ch skip]
print ch = #"q"
copy — substring
Captures the exact matched substring into a string! target.
val: make string! ""
print parse "aaa" [copy val 3 #"a"]
capture — zero-copy slice
Captures the matched region as a slice! [char!] pointing into
the original input (no copy).
text: make string! "abcd"
out: make [slice! [char!]] at text 0 0
print parse text [capture out "ab" "cd"]
Guards & paren actions
if (cond) <rule-unit>
cond must be logic!. When true, the
guarded unit is evaluated; when false, it fails at that point and
normal backtracking applies.
print parse "abcd" ["a" opt ["b" if (false) "c"] "bcd"]
(expr)
A paren item runs embedded Recoil code and is invisible to parse flow: it always succeeds, consumes nothing, and its value is ignored. This is how parse rules trigger side effects — including sending events to a state machine.
parse "GET /path" [
"GET" (send conn got-method [])
" "
thru end
]
rule! & nested blocks
Reusable rule! bodies and inline [...] blocks are
first-class rule units with the same rollback semantics as other composite
units.
needle: make string! "ab"
ab: make rule! [thru needle]
print parse "ababab" [some ab]
Diagnostics
Compile-time (not runtime) checks include: non-string!/url!
input; invalid named targets; unsupported binding types in rules; malformed
to/thru, alternation, repetition, range bounds,
set/copy; invalid capture target types; malformed
ahead/not; and a malformed or non-logic!
if condition.
See also: Parse + FSM integration.