goyacc:获取yacc解析器的上下文/没有`%param`

What is the most idiomatic way to get some form of context to the yacc parser in goyacc, i.e. emulate the %param command in traditional yacc?

I need to parse to my .Parse function some context (in this case including for instance where to build its parse tree).

The goyacc .Parse function is declared

func ($$rcvr *$$ParserImpl) Parse($$lex $$Lexer) int {

Things I've thought of:

  • $$ParserImpl cannot be changed by the .y file, so the obvious solution (to add fields to it) is right out, which is a pity.
  • As $$Lexer is an interface, I could stuff the parser context into the Lexer implementation, then force type convert $$lex to that implementation (assuming my parser always used the same lexer), but this seems pretty disgusting (for which read non-idiomatic). Moreover there is (seemingly) no way to put a user-generated line at the top of the Parse function like c := yylex.(*lexer).c, so in the many tens of places I want to refer to this variable, I have to use the rather ugly form yylex.(*lexer).c rather than just c.
  • Normally I'd use %param in normal yacc / C (well, bison anyway), but that doesn't exist in goyacc.
  • I'd like to avoid postprocessing my generated .go file with sed or perl for what are hopefully obvious reasons.
  • I want to be able to (go)yacc parse more than one file at once, so a global variable is not possible (and global variables are hardly idiomatic).

What's the most idiomatic solution here? I keep thinking I must be missing something simple.

My own solution is to modify goyacc (see this PR) which adds a %param directive allowing one or more fields to be added to the $$ParserImpl structure (accessible as $$rcvr in code). This seems the most idiomatic route. This permits not only passing context in, but the ability for the user to add additional func()s using $$ParserImpl as a receiver.