我试图了解如何重新创建由grako生成的解析器解析的文档。
在将自己深深地嵌入到grako源代码中之后,我相信我终于了解了人们是如何从AST返回到生成的文档的。有人可以检查一下我的理解是否正确,然后让我知道是否有更直接的方法吗?
grako.model.Node
的子类),用于一个人语法中的每个规则。每个类至少必须具有一个构造函数,该构造函数必须具有对应规则中每个命名元素的参数,并将其值存储在class属性中。 grako.codegen.ModelRenderer
的子类,该子类定义了(或多或少)一个人的语法规则中“代码”生成的模板。 grako.codegen.CodeGenerator().render(...)
以创建输出。 这样可以吗?这似乎一点都不直观。
最佳答案
如果查看 Grako 本身如何解析语法,您会注意到第2步类是由ModelBuilderSemantics
后代综合创建的:
# from grako/semantics.py
class GrakoSemantics(ModelBuilderSemantics):
def __init__(self, grammar_name):
super(GrakoSemantics, self).__init__(
baseType=grammars.Model,
types=grammars.Model.classes()
)
self.grammar_name = grammar_name
self.rules = OrderedDict()
...
如果这些类不存在于
types=
参数中,则进行合成。 ModelBuilderSemantics
所需要的就是每个语法规则都带有一个参数,该参数给出对应的Node
的类名称:module::Module = .... ;
或者,
module(Module) = ... ;
步骤3是不可避免的,因为必须在“某处”指定翻译。 Grako 的方法允许在由
str
完成的分派(dispatch)中内联指定CodeGenerator
模板,这是我首选的翻译方式。但是,当我只需要从模型中提取信息时(例如生成符号表或计算指标时),我就使用grako.model.DepthFirstNodeWalker
。步骤3无法自动执行,因为将源语言的语义映射到目标语言的语义需要脑力,即使源和目标相同。
正如您所建议的,您还可以遍历
parse()
或grako.model.Node.asjson()
(AST)生成的类似JSON的Python结构,但是处理代码将充满if-then-elseif
来区分一个字典与另一个字典,或一个列表与另一个字典。对于模型,层次结构中的每个字典都有一个Python类作为类型。最后, Grako 不会强加一种方法来创建已解析内容的模型,也不会强加将其转换为其他内容的方法。在基本形式中, Grako 仅在合理使用元素命名的情况下才提供具体语法树(CST)或抽象语法树(AST)。其他所有内容均由特定的语义类生成,可以随心所欲。
关于python - Grako "code"世代,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35565052/