Grako"code"代
Grako "code" generation
我想了解如何重新创建由 grako 生成的解析器解析的文档。
在深入研究 grako 源代码之后,我相信我终于理解了如何 returns 从 AST 到生成文档。有人可以检查一下我的以下理解是否正确,如果有更直接的方法请告诉我?
- 创建一个希望解析的 PEG 语法。 Grako 基于它创建了一个解析器 class 和一个语义学 class。
- 一个人(手动)创建一个 python 模块,其中包含(或多或少)一个单独的 class(
grako.model.Node
的子class)语法。每个 class 必须至少有一个构造函数,其中包含对应规则中每个命名元素的参数,并将其值存储在 class 属性. 中
- 一个子class(手动)生成的语义class用步骤 2 中创建的相应 class 替换每条规则的 ast。
- 一个人(手动)创建一个 python 模块
grako.codegen.ModelRenderer
的一个子 class 定义模板 "code" 生成(或多或少)每个规则一个人的语法。
- 将由节点子classes 和包含模板的python 模块组成的AST 提供给
grako.codegen.CodeGenerator().render(...)
以创建输出。
这样可以吗?这看起来一点也不直观。
- 为什么要经过第 2 步和第 3 步的巨大努力,除了存储已经包含在 AST 中的信息外什么都不做?
- 这种方法比直接从 AST 工作有什么优势?
- 如果只想用原始语法重新创建文档,有没有办法自动执行或回避步骤 2 和 3?
- 给定 PEG 语法定义,理论上是否可以像创建 "parser generator" 一样自动创建 "code generator generator"?
如果您查看 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产生的,可以是任何人想要的。
我想了解如何重新创建由 grako 生成的解析器解析的文档。
在深入研究 grako 源代码之后,我相信我终于理解了如何 returns 从 AST 到生成文档。有人可以检查一下我的以下理解是否正确,如果有更直接的方法请告诉我?
- 创建一个希望解析的 PEG 语法。 Grako 基于它创建了一个解析器 class 和一个语义学 class。
- 一个人(手动)创建一个 python 模块,其中包含(或多或少)一个单独的 class(
grako.model.Node
的子class)语法。每个 class 必须至少有一个构造函数,其中包含对应规则中每个命名元素的参数,并将其值存储在 class 属性. 中
- 一个子class(手动)生成的语义class用步骤 2 中创建的相应 class 替换每条规则的 ast。
- 一个人(手动)创建一个 python 模块
grako.codegen.ModelRenderer
的一个子 class 定义模板 "code" 生成(或多或少)每个规则一个人的语法。 - 将由节点子classes 和包含模板的python 模块组成的AST 提供给
grako.codegen.CodeGenerator().render(...)
以创建输出。
这样可以吗?这看起来一点也不直观。
- 为什么要经过第 2 步和第 3 步的巨大努力,除了存储已经包含在 AST 中的信息外什么都不做?
- 这种方法比直接从 AST 工作有什么优势?
- 如果只想用原始语法重新创建文档,有没有办法自动执行或回避步骤 2 和 3?
- 给定 PEG 语法定义,理论上是否可以像创建 "parser generator" 一样自动创建 "code generator generator"?
如果您查看 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
:
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产生的,可以是任何人想要的。