Question about binding in parse

parse x: copy/deep [(-hi-there- 1 2 3 (hello 2 3 4))] function-rule

rule definition:

function-rule: [
   into [
      set code word! (probe code)
      any [integer! | function-rule]
   ]
]

-hi-there-
hello

function-rule: [
   into [
      set code word!
      any [integer! | function-rule]
      (probe code)
   ]
]

hello
hello

The idea is to have code be like it is in the first rule definition. It makes sense as to why this is happening because code is being overshadowed by the inner definition of code so that the probe call is calling the same word twice. Is there a way to set up context-sensitive words that look the same yet print out different results, I know there is in other cases but what about this case?

1 Like

The more common method of handling this is to use a stack:

stack: []
function-rule: [
   into [
      set code word! (append stack code)
      any [integer! | function-rule]
      (probe take stack)
   ]
]

To do this by manipulating context I believe would be tricky and likely costly.

Yea, that is pretty much the way they introduce a stack is by parsing parentheses. So I guess it is a bad idea to think about context in this situation?

You could potentially force a context solution but in effect I expect you'll end up with a stack anyway (of contexts) and as @rgchris points out doing so is likely to be costly and tricky (at least right now).

Parse does need something more to make life easier in this regard.

Six years later :no_mouth: we can now do this with LET.

LET is a UPARSE "keyword" (where UPARSE is the parser-combinator based variant of the PARSE dialect). It was able to be implemented due to a new model of binding which is based on compounding environments, instead of depending on "waves" of mutable binding.

There are some shuffles you have to do (when not using the PARSE2 emulation set of parser combinators)... anyway, here's the equivalent:

function-rule: [
   subparse group! [
       let code: word!
       optional some [integer! | function-rule]
       (probe code)
   ]
]

>> parse x: copy/deep [(-hi-there- 1 2 3 (hello 2 3 4))] function-rule
hello
-hi-there-
== -hi-there-

Adjustments are:

  • INTO (arity 1, rule inside) => SUBPARSE (arity 2, rule to match then rule inside)

  • Rules generate products, SET-WORD! for assignments (vs. SET)

  • ANY has a new meaning for meaning "any of the rules in the following block", so use OPTIONAL SOME (equivalent to OPT SOME) instead when you mean "any number including zero"

  • GROUP! is the name for the PAREN! type in Ren-C

I think it's not insignificant that old problems become solvable with new methods--it's worth pointing out. Also I've added this case to the PARSE LET tests.

1 Like