Blog › ICP guides

Rebol developer on retainer: parse dialect, word! vs string! distinction, parse/all refinement, block! data types, and Rebol dialect programming on monthly retainer

December 8, 2026 · ~15 min read

A Rebol program parsed structured configuration blocks where each line contained a key, a separator character, and a value. The developer wrote a parse rule value-rule: [copy val to newline] to capture everything from the current position up to (but not including) the next newline character. The program called parse config-block value-rule at each line start. The parse succeeded — val was set — but val contained only the first word of the value, not the entire text up to the newline. The developer expected a line like "server address = 192.168.1.1" to have its value portion captured in full after the key, but val contained only "server". The problem was the parse refinement: without /all, Rebol’s parse function uses the default grammar that treats whitespace as a delimiter between tokens, similar to how parse works on block! values — each space-separated token is a separate element. The to newline rule correctly identifies the endpoint, but the copy val prefix captures the matched data as a single token, and in the default parse grammar, a single token ends at whitespace. The developer added the /all refinement: parse/all config-string value-rule. The /all refinement makes parse treat every character literally without special-casing whitespace, matching the string character by character. copy val to newline now captures the entire string up to the newline. Four wrong captures per block → 0. The Rebol developer on retainer diagnosed the parse/all vs parse distinction: parse on a string applies Rebol’s default parse grammar (tokens delimited by whitespace, skip whitespace between rules); parse/all on a string applies character-by-character matching without whitespace treatment. Most structured text parsing in Rebol requires parse/all — the default parse on strings is for token-oriented input.

The work log entry read “fixed configuration parser, 5h.” It names the result and duration. It cannot explain why parse without /all treats whitespace as a delimiter for string input — Rebol’s parse function was designed for block! data (where elements are already tokenized) and for token-oriented string parsing; the default grammar skips whitespace between rule matches, treating the input as a sequence of tokens; this is useful for parsing Rebol-like grammars where spaces between tokens are insignificant, but destructive for capturing raw string segments that contain spaces as meaningful characters. It cannot explain the difference between to and thru in parse rules — to newline advances to the position just before the newline and leaves the newline as the next character; thru newline advances to the position just after the newline and consumes it; the choice determines whether the newline is included in the next rule’s input. It cannot explain when to use copy vs set in parse rules — copy captures a series (a substring or block subset) as a new value; set captures a single element (the next token or item in a block) as a value; for capturing a variable-length sequence up to a delimiter, copy val to delimiter is correct; for capturing a single word or value, set val skip or set val word! is correct. The 5 hours of parse refinement diagnosis, rule composition analysis, and character-by-character matching design are invisible in the diff.

Rebol parse dialect: parse vs parse/all, copy/set/to/thru rules, and word! vs string! vs block! in parse patterns

Rebol’s parse dialect is a domain-specific language for pattern matching embedded in the Rebol language itself. Parse rules are written as Rebol block! values where the elements are a mix of Rebol datatypes (used as literal matchers), keywords (copy, set, to, thru, any, some, opt, into, end, skip), and rule names (words bound to sub-rules). The parse function takes a series (string! or block!) and a rule block: parse series rule. The critical distinction between parse and parse/all applies to string! input: parse on a string applies the default grammar (whitespace-insensitive, tokens), while parse/all applies character-by-character matching. For block! input, the distinction does not apply — blocks are already sequences of Rebol values, and parse matches each element of the block against the rule. Most real-world Rebol parse programs that process arbitrary text use parse/all; parse (without /all) is appropriate for token-oriented input where whitespace between tokens is insignificant.

The to and thru keywords control how far the parser advances when matching up to a delimiter. to delimiter advances the current position to just before the first occurrence of delimiter in the input and succeeds if delimiter is found; the delimiter remains as the next unmatched input. thru delimiter advances the current position to just after the first occurrence of delimiter and succeeds if found; the delimiter is consumed. copy val to newline captures everything from the current position up to (not including) the first newline — the newline remains as the next input character. copy val thru newline captures everything including the newline and advances past it. The copy keyword captures the matched region: copy val rule sets val to the portion of the input that rule matched, as a new series (substring or block!). set var rule matches exactly one element (the next character for strings, the next element for blocks) and sets var to that value without creating a new series. The any and some quantifiers apply to rules: any rule matches zero or more repetitions; some rule matches one or more. opt rule matches zero or one.

Rebol’s type system is central to parse rule design because parse patterns are themselves Rebol values of specific types. In a parse rule for a block! series, a word! value in the rule matches the corresponding word! in the series; a string! value matches that literal string; an integer! rule matches an integer. The distinction between word! and string! is a common source of parse errors: in Rebol, server (unquoted) is a word! and "server" (quoted) is a string!; they are different types and a rule that expects a word! will not match a string! and vice versa. In block! parse rules, [copy val string!] matches and captures the next string! element; [copy val word!] matches and captures the next word!. lit-word! ('server) matches a literal word without evaluating it. get-word! (:server) retrieves the value of server at parse time to use as a dynamic rule. into block-rule descends into a nested block: [into [copy items some integer!]] matches a block! element and parses its contents with the inner rule. Rebol was created by Carl Sassenrath, who also designed AmigaOS’s IPC system. REBOL stands for Relative Expression Based Object Language. Red is a modern language inspired by Rebol with a compiled target. Rebol’s retainer ecosystem includes legacy enterprise systems on Rebol/Core, web applications on Rebol/View, and modern systems migrating to Red; the retainer work is primarily dialect design, parse rule diagnosis, and the maintenance of domain-specific languages built on Rebol’s homoiconic data model. Its closest retainer neighbors are Tcl (string processing, embedded scripting) and Forth (stack language, embedded DSL), but Rebol’s parse dialect, block! data model, and homoiconicity make the retainer work distinct in rule composition analysis, type-specific matching, and dialect engineering.

Rebol data types, DO dialect, series operations, and context/object model

Rebol’s type system has over 40 datatypes that are first-class values. The most important for retainer work are: word! (an identifier that evaluates to its binding, like a variable name), lit-word! (a quoted word that does not evaluate, like a symbol), get-word! (retrieves a word’s value without invoking it), set-word! (assigns a value to a word), block! (a sequence of values, unevaluated by default), paren! (evaluated immediately), string!, integer!, decimal!, date!, time!, url!, email!, file!, and binary!. The distinction between word! and string! is the single most common type confusion in Rebol programs: server evaluates to the current binding of the word server (which may be a string, an integer, a function, etc.), while "server" is the literal string "server". In parse rules for block! series, these distinctions matter for every pattern: [copy name string!] captures the next string! element; [copy name word!] captures the next word!. A parse rule that uses string! to match a word in a block will never match, and the error is silent (parse fails or returns a wrong result) rather than a type error.

Rebol’s DO dialect is the default evaluation model: a block of Rebol code is evaluated left to right, with words evaluated as function calls or variable references, and blocks passed unevaluated. do [print "hello"] evaluates the block as code. Series operations (append, insert, remove, find, select, copy, change) are fundamental to Rebol programming: append block value appends a value to the end of the block series; find series value returns the position of the first occurrence; select series key searches for key and returns the following value; copy/part series n copies the first n elements. These series operations work uniformly on string!, block!, and binary!, making Rebol’s string processing and data structure manipulation share the same API. Rebol’s object/context model uses make object! [fields] to create prototype-based objects: obj: make object! [name: "Alice" age: 30]. Objects are contexts — they bind words to values. Methods are closures that capture the enclosing context. self refers to the current object inside a method. Retainer work involving Rebol objects typically covers context binding (why name inside a method refers to the method’s local context rather than the object’s context), make vs copy for object creation, and the prototype chain for shared behavior.

How HourTab tracks Rebol developer retainer hours

Rebol retainer work carries the invisible-hours problem specific to dialect-based languages: the difference between parse and parse/all is a single word in the source, but diagnosing it requires understanding Rebol’s parsing model, testing with string inputs that contain spaces, and recognizing that the parse failure is silent (parse returns a different result rather than throwing an error). The 4 wrong captures per block in the story above are typical: Rebol parse failures often manifest as partial captures or as none values where a captured value was expected, and the root cause — whitespace treatment in the default parse grammar — is not visible in the rule definition. Similarly, word! vs string! type confusion in parse rules for block! data is a common source of retainer work: the developer writes a parse rule that seems correct for the block structure but never matches because the block contains string! values and the rule expects word! values (or vice versa). The retainer work is the type system audit (what type are these block elements actually?), the parse/all diagnosis (does this input contain significant whitespace?), the to/thru selection (should the delimiter be consumed or left in the input stream?), and the rule composition analysis (are these sub-rules composing correctly?).

HourTab gives Rebol developers a public retainer-hours URL they send to clients — typically organizations running legacy Rebol enterprise systems that require ongoing parse dialect expertise, teams maintaining Rebol-based domain-specific languages for configuration management or data transformation, and projects with Rebol-based configuration parsers or data transformation pipelines. For Rebol retainers, each work log entry should name the mechanism (parse refinement: parse changed to parse/all for string input with significant whitespace; type matching: word! changed to string! in block parse rule because block elements are strings; rule composition: to changed to thru to consume the delimiter; context binding: make object! prototype chain for shared method behavior), the specific rule, input type, and before/after capture count, and the rule composition rationale. Rebol retainers are often compared to Tcl developer retainers (string processing, embedded scripting) and Lisp retainers (homoiconicity, code-as-data), but Rebol’s parse dialect with word!/string!/block! type matching, to/thru advancement rules, and context-based object model make the work distinct in rule composition analysis, type-specific matching, and dialect engineering. HourTab’s work log makes the parse refinement decision, type system audit, and rule composition analysis visible to clients who would otherwise see only the symptom — wrong captures or silent parse failures — and not understand why the fix required knowing that parse and parse/all produce fundamentally different results on string input containing spaces, and why choosing the correct capture keyword and advancement rule at each parse step is the work that keeps the Rebol dialect correct and maintainable.

Track Rebol developer retainer hours without the status emails

HourTab gives Rebol developers a public URL per client retainer. One link, no login, live burn-down. Your clients stop asking “how many hours do I have left?” and your parse dialect engineering log becomes the proof of value that gets the retainer renewed.

See HourTab pricing →

FAQ: Rebol developer retainers

What does a Rebol developer on retainer typically do?

A Rebol developer on monthly retainer covers Rebol parse dialect (parse vs parse/all for string input; copy/set/to/thru rule keywords; any/some/opt quantifiers; into for nested block parsing; word!/string!/integer! type matchers in block parse rules), Rebol data types (word! vs lit-word! vs get-word! vs set-word! distinctions; block! unevaluated sequences; string! vs word! in parse patterns; date!, url!, email!, file! as first-class types), Rebol DO evaluation model (block evaluation; word binding; context/object model; make object!; self reference in methods), and Rebol series operations (append, insert, remove, find, select, copy/part on string!, block!, and binary! uniformly).

What Rebol work is most commonly underlogged in a retainer?

Parse/all refinement diagnosis (parse on string applies whitespace-insensitive token grammar; parse/all applies character-by-character matching; structured text parsing almost always requires parse/all; 4 wrong captures per block → 0; 5–9 hrs invisible); word! vs string! type audit in block parse rules (block contains string! values but rule matches word!; or vice versa; parse silently fails or returns wrong result; no type error is thrown; 3 wrong-match patterns per block parse rule → 0; 4–8 hrs invisible); to/thru selection analysis (to leaves delimiter in input stream; thru consumes delimiter; wrong choice causes next rule to match or skip the delimiter unexpectedly; 2 rule composition errors per parser → 0; 3–7 hrs invisible).

What are typical Rebol developer retainer rates?

Entry-level Rebol developers (1–2 years, basic parse dialect, DO evaluation, series operations) bill at $60–$110/hr. Mid-level Rebol programmers (2–4 years, parse/all refinement, word!/string! type discipline, dialect design, context model) bill at $100–$175/hr. Senior Rebol architects (4–8 years, large-scale dialect architecture, Rebol/Red migration, embedded DSL design, legacy system maintenance) bill at $145–$255/hr. Monthly retainer ranges: $2,000–$4,500/mo advisory (15–25 hrs), $6,000–$16,000/mo for full Rebol dialect engineering engagements.

What should a Rebol developer retainer agreement include?

A Rebol developer retainer agreement should specify: parse dialect scope (parse vs parse/all for string input; copy/set for capture; to/thru for advancement; any/some/opt quantifiers; into for nested blocks; word!/string!/integer! type matchers); data type scope (word! vs string! distinction; lit-word! for symbols; get-word! for dynamic rules; block! unevaluated sequences; series operations on string!, block!, binary!); DO evaluation scope (block evaluation; word binding; context/object model; make object!; method self reference); and hour logging format (advisory category, before/after capture count or parse failure mode, whether fix required parse/all refinement, type matcher correction, to/thru selection, or context binding redesign).

How should Rebol developer retainer hours be logged?

Log each Rebol retainer session with: advisory category (parse refinement: parse changed to parse/all for string input with significant whitespace; type matching: word! changed to string! in block parse rule; rule composition: to changed to thru for delimiter consumption; context binding: object method context vs local word binding); the specific rule, input type, and before/after capture count (rule: copy val to newline; input: string with spaces; parse result: captures first token only; fix: parse/all; result: captures full string to newline; wrong captures: 4 → 0); and the before/after metric. Include whether fix required parse/all refinement addition, word!/string! type matcher correction, to/thru advancement rule change, or copy/set capture keyword switch.