whitequark / parser

A Ruby parser.
Other
1.58k stars 198 forks source link

What is the best way to inject an environment? #1006

Closed akimd closed 6 months ago

akimd commented 6 months ago

Hi,

I would like to parse snippets, say x + y, but in an environment where x and y are variables, so it should not be parsed as self.x + self.y.

Because I have read "If you reuse the same parser object for multiple #parse runs, you need to #reset it" I first tried to parse x = nil; y = nil and then x + y with the same parser object, but the second parse returns nil.

AFAICT, most of the parser state is locked in private instance variables, so I don't see a way to define by environment.

Of course I can concatenate my prologue to my actual input and eliminate it when traversing the AST, but I'd like to avoid that if possible (and keep line numbers correct, etc.).

What would be the recommended way to do that?

Thanks!

iliabylich commented 6 months ago

Hello.

Of course, the most naive (and the most unbreakable) solution would be prepending a = nil; b = nil to your code, but it's a) breaks source maps and b) looks hacky.

Instead you could do what parser does internally in unit tests:

%w(foo bar baz).each do |metasyntactic_var|
  parser.static_env.declare(metasyntactic_var)
end

This API is public and it will not go away.

akimd commented 6 months ago

Thanks a lot!