If you look at how Grako himself analyzes grammars, you will notice that the 2nd stage classes are synthetically created by the ModelBuilderSemantics thread:
Classes are synthesized if they are not present in the types= parameter. All that ModelBuilderSemantics requires is that each grammar rule contains a parameter that gives the class name for the corresponding Node :
module::Module = .... ;
or,
module(Module) = ... ;
Step 3 is inevitable because the translation must be specified "somewhere." The Grako method allows you to use the str patterns specified on the line with the dispatcher executed by CodeGenerator , which is my preferred way of doing the translation. But I use grako.model.DepthFirstNodeWalker when I just need to extract information from the model, for example, when creating a symbol table or calculations.
Step 3 cannot be automated, since comparing the semantics of the source language with the semantics of the target language requires mental power, even when the source and target objects are the same.
You can also get along with the JSON-like Python structure that parse() or grako.model.Node.asjson() generates (AST) as you suggest, but the processing code will be filled with if-then-elseif to distinguish one dictionary from another or one list of another. With models, each dict in the hierarchy has a Python class as a type.
In the end, Grako does not impose a way to create a model of the analyzed file and not transfer it to something else. In it, the basic Grako form provides only a syntax tree (CST) or abstract syntax tree (AST), if it is reasonable to use element naming. Everything else is done by a separate class of semantics, which can be anything you want.
source share