Estoy en una situación en la que he construido un árbol de sintaxis abstracta (AST) con la semántica del generador de modelos de Grako. Ahora necesito generar código javascript a partir de ese AST. He definido varias plantillas, pero me di cuenta de que no todos los casos se pueden manejar con plantillas simples. La regla concreta con la que estoy atrapado es:

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

Esta regla coincide tanto con las llamadas a funciones simples como con las llamadas al constructor, ya que no hay forma de determinar léxicamente cuál es cuál, depende de si hay una clase con ese nombre definida dentro de ese ámbito.

Entonces, por ejemplo "a = Func ();"

En javascript, los dos casos requieren una sintaxis diferente ("a = new Func ();" o "a = Func ();")

Entonces necesito una tabla de símbolos para realizar un seguimiento de cuál es cuál. ¿Hay alguna forma de lograr esto con grako?

Información adicional:

Mi idea sobre cómo hacer esto: Cree una clase de caminante, que construya una tabla de símbolos y cuando maneje un objeto FunctionCall, verifique si en realidad es una llamada de constructor y, en ese caso, reemplace el nodo FunctionCall con un nodo ConstructorCall. Luego, simplemente tenga dos plantillas para los dos.

Lo que no me gusta del enfoque es que se siente demasiado separado y requiere una nueva clase para cada plantilla.

0
G.G 4 dic. 2016 a las 14:37

1 respuesta

La mejor respuesta

Puede cambiar la plantilla y los campos renderizados en tiempo de ejecución. Debido a que se crea una instancia de ModelRenderer para cada nodo AST, los cambios que realice afectarán solo la representación de ese Node único:

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

Tenga en cuenta que la asignación es a una variable de instancia y que ClassName.template permanece igual.

1
Apalala 5 dic. 2016 a las 14:30