The PARSE of PROGRESS

I've mentioned that this is pretty easy to write. But it doesn't mean there shouldn't be a name for it...

It seems to me a reasonably good name for this is PARSE-THRU..

>> parse-thru "aaabbb" [some "a"]
== "bbb"

It can be implemented any number of ways, but an easy one is to ADAPT the rules slightly before running the PARSE. Since RULES is a BLOCK!, you can just compose it in, and follow it with an ACCEPT of wherever the current position is.

/parse-thru: adapt parse/ [
    rules: compose [(rules) accept <here>]
]

This will default to erroring if it doesn't match, so you'd have to use try parse-thru if you wanted a null when there was a deliberate mismatch:

>> parse-thru "bbbaaa" [some "a"]
** Error: PARSE BLOCK! combinator did not match input

>> try parse-thru "bbbaaa" [some "a"]
== ~null~

If you want to work around this, there's lots of ways to do it. You could make an alternative to return null:

/parse-thru: adapt parse/ [
    rules: compose:deep [[(rules) accept <here>] | accept null]
]

Or rig it up so that the rule is optional, and use PARSE:RELAX to remove the requirement that it reach the end:

/parse-thru: adapt parse:relax/ [
    rules: compose*:deep [opt [(rules) accept <here>]]
]

Lots of ways to get the effect:

>> parse-thru "bbbaaa" [some "a"]
== ~null~  ; anti

Another Interesting Interface: PARSE-MATCH

Being able to get the input, or a NULL, can be useful as well. Similar technique will get it, just swap the <input> combinator for the <here> combinator, and don't remove the requirement to reach the end:

/parse-match: adapt parse/ [
    rules: compose [(rules) <end> <input> | accept null]
]

>> parse-match "aaabbb" [some "a" some "b"]
== "aaabbb"

>> parse-match "bbbaaa" [some "a" some "b"]
== ~null~  ; anti

>> parse-match "aaabbb" [some "a"]
== ~null~  ; anti

Endless Possibilities... But How To Compose Them?

In the Visual Parse Demo I showed how a tweaked PARSE variant, that I called eparse, could be rigged up to make underlines in the web-based text editor for anything you marked with a MARK combinator (with rollback, such that marks would not be made if the whole rule did not ultimately match...)

So do you have to write EPARSE-THRU and EPARSE-MATCH?

If instead of having these modes be done with wrappers--that they were instead refinements on PARSE itself--you'd get EPARSE:THRU and EPARSE:MATCH "for free". Perhaps they could be more efficient in their implementation as well.

But then you start having situations where people can do nonsensical combinatorics, like eparse:thru:match. :frowning:

...or (Weird Idea) Could PARSE Have Some Other Hookability?

It might be that if you ask to PARSE an OBJECT!, that the object could act as some kind of specification... like providing the combinators and where to look for the data.

e.g. parse editor [some "a"] could look at the editor object, and have behaviors particular to that object. This would mean that parse-match editor [some "a"] could work as well.

Separate Entry Points vs. Refinements Is The Safer Bet

In the scheme of things, having PARSE-MATCH and a PARSE-THRU entry points is easiest, because you'll be able to do that regardless.

But like I say, the default being the synthesized result of the rules... with error by default if a match or ACCEPT is not reached... that's a super powerful default that I'm really happy with.

1 Like