格雷科“代码”生成

2024-04-30 03:43:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图理解如何重新创建由grako生成的解析器解析的文档。在

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

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

这是对的吗?这似乎一点都不直观。在

  • 为什么要经过步骤2和3的大量工作,只存储AST中已经包含的信息?在
  • 与直接从AST工作相比,这种方法的优势是什么?在
  • 如果只想用原始语法重新创建文档,是否有一种方法可以自动执行或跳过步骤2和3?在
  • 给定一个PEG语法定义,理论上是否可以像创建“解析器生成器”一样自动创建“代码生成器”?在

Tags: 模块方法文档解析器定义规则语义语法
1条回答
网友
1楼 · 发布于 2024-04-30 03:43:08

如果您看看Grako本身是如何解析语法的,您会注意到step2类是由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的类名:

^{pr2}$

或者

^{3}$

第3步是不可避免的,因为翻译必须指定为“某处”。Grako的方法允许使用str模板,这些模板与由CodeGenerator完成的调度一起内联指定,这是我进行翻译的首选方式。但是当我只需要从模型中提取信息时,比如在生成符号表或计算度量时,我使用grako.model.DepthFirstNodeWalker。在

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

您还可以通过遍历parse()或{}生成的类似JSON的Python结构(AST)来避免,但是处理代码中会充满if-then-elseif来区分一个字典与另一个字典,或者一个列表与另一个。对于模型,层次结构中的每个dict都有一个Python类作为类型。在

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

相关问题 更多 >