pythoncode-generationgrako

Context sensitve code generation with grako


I'm in a situation where I've built an abstract syntax tree (AST) with grako's model builder semantics. Now I need to generate javascript code from that AST. I have defined several templates, but I realized not all cases can be handled with simple templates. The concrete rule I'm stuck with is:

fcall::FunctionCall   = name:identifier '(' ','.{args:expression} ')' ;

This rule matches both, simple function calls and constructor calls, as there is no way to lexically determine which is which, it depends if there is a class with that name is defined within that scope.

So e.g. "a = Func();"

in javascript the two cases require different syntax ("a = new Func();" or "a = Func();")

So I need a symbol table to keep track which is which. Is there a way to achive this with grako?

Aditional Info:

My idea on how to do this: Create a walker class, that builds up a symbol table and when it handles a FunctionCall object, check if it is actually a constructor call and in that case replace the FunctionCall node with a ConstructorCall node. Then simply have two templates for the two.

What I don't like about the approach is that it feels too separated and it requires a new class for each template.


Solution

  • You can change the template and the rendered fields at runtime. Because an instance of the ModelRenderer is created for each AST node, the changes you make affect only the rendering of that single Node:

    def render_fields(self, fields):
       if self.is_constructor_call():
          self.template = self.constructor_template
    

    Note that the assignment is to an instance variable, and that ClassName.template remains the same.