Recoil logo

Recoil

PARSE — a compiled grammar dialect

  • Home
  • Getting Started
  • Guide
  • Reference
  • PARSE
  • State Machines
  • FFI & Systems
  • Ports
  • Packages
  • f00 & Embedded
  • Examples
  • Internals

On this page

Loading…

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 slot p; :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.

↑

Recoil — an ownership-first, statically-typed language with a static borrow checker.

codeberg.org/rebolek/recoil · boleslav@brezovsky.eu · Apache-2.0