Grako"code"代

Grako "code" generation

我想了解如何重新创建由 grako 生成的解析器解析的文档。

在深入研究 grako 源代码之后,我相信我终于理解了如何 returns 从 AST 到生成文档。有人可以检查一下我的以下理解是否正确,如果有更直接的方法请告诉我?

  1. 创建一个希望解析的 PEG 语法。 Grako 基于它创建了一个解析器 class 和一个语义学 class。
  2. 一个人(手动)创建一个 python 模块,其中包含(或多或少)一个单独的 class(grako.model.Node 的子class)语法。每个 class 必须至少有一个构造函数,其中包含对应规则中每个命名元素的参数,并将其值存储在 class 属性.
  3. 一个子class(手动)生成的语义class用步骤 2 中创建的相应 class 替换每条规则的 ast。
  4. 一个人(手动)创建一个 python 模块 grako.codegen.ModelRenderer 的一个子 class 定义模板 "code" 生成(或多或少)每个规则一个人的语法。
  5. 将由节点子classes 和包含模板的python 模块组成的AST 提供给grako.codegen.CodeGenerator().render(...) 以创建输出。

这样可以吗?这看起来一点也不直观。

如果您查看 Grako 本身如何解析语法,您会注意到步骤 2 classes 是由 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= 参数中不存在 classes,则合成它们。 ModelBuilderSemantics 所需要的只是每个语法规则都带有一个参数,该参数为相应的 Node:

提供 class 名称
module::Module = .... ;

或者,

module(Module) = ... ;

第3步是免不了的,因为必须指定翻译"somewhere"。 Grako 的方式允许 str 指定的模板与 CodeGenerator 完成的调度内联,这是我首选的翻译方式。但当我只需要从模型中提取信息时,我会使用 grako.model.DepthFirstNodeWalker,例如生成符号 table 或计算指标时。

步骤 3 无法自动化,因为将源语言的语义映射到目标语言的语义需要脑力,即使源语言和目标语言相同。

也可以像您建议的那样遍历 parse()grako.model.Node.asjson() 生成的 JSON 类 Python 结构(AST),但是处理代码将充满 if-then-elseif 以区分一个字典与另一个字典,或一个列表与另一个列表。对于模型,层次结构中的每个字典都有一个 Python class 作为类型。

最后,Grako 没有强加一种方法来创建已解析内容的模型,也没有强加一种将其转换为其他内容的方法。在其基本形式中,Grako 仅提供 具体语法树 (CST) 或 抽象语法树 (AST) 如果元素命名被明智地使用。其他一切都是由特定的语义class产生的,可以是任何人想要的。