Search code examples
parsingrebolrebol3

How to SET a variable to the result of a rule matching multiple elements in Rebol PARSE?


Imagine a simple example, where we want to turn the string "0-5" into "012345".

This works:

>> parse "0-5" [
    set a char!
    "-"
    set b char!

    (
        while [a <= b] [
            prin a
            a: a + 1
        ]
    )
]

The result is:

012345
true

But what if I wanted something more general, that could turn "10-12" into "101112", or beyond? This doesn't work:

>> parse "0-5" [
    set a [some char!]
    "-"
    set b [some char!]

    (
        a-int: to integer! a
        b-int: to integer! b
        while [a-int <= b-int] [
            prin to string! a-int
            a-int: a-int + 1
        ]
    )
]

The reason it doesn't work is because instead of set a [some char!] capturing a string of characters, it errors:

>> parse "10" [set a [some char!] (print a)]
** Script error: PARSE - invalid rule or usage of rule: char
** Where: parse
** Near: parse "10" [set a [some char] (print a)]

As a bonus question, why does that fail and using skip returns the first digit only?

>> parse "10" [set a [some skip] (print a)]
1
== true

...when some skip and some char! match equivalently on strings, since the only thing in a string to skip is a character...?


Solution

  • In Parse dialect, SET captures only the first element of the input matched by the sub-rule, while COPY captures all of it. So, you need to use COPY when you want to extract more than one character from a any-string! series.