在python中为DSL编写编译器

时间:2008-12-04 00:17:15

标签: python dsl dsl-tools

我正在用python编写游戏,并决定为地图数据文件创建一个DSL。我知道我可以用regex编写自己的解析器,但我想知道是否有现成的python工具可以更容易地做到这一点,比如在PHP引擎中使用的re2c。

一些额外信息:

  • 是的,我需要DSL,即使我没有,我仍然需要在项目中构建和使用它的经验。
  • DSL只包含数据(声明性?),它不会被“执行”。大多数行看起来像:

    SOMETHING: !abc @123 #xyz/123

    我只需要阅读数据树。

8 个答案:

答案 0 :(得分:12)

pyparsing给我留下了深刻的印象。作者Paul McGuire积极参与python list / comp.lang.python,对任何有关它的疑问一直非常有帮助。

答案 1 :(得分:7)

答案 2 :(得分:6)

这是一种非常有效的方法。

abc= ONETHING( ... )
xyz= ANOTHERTHING( ... )
pqr= SOMETHING( this=abc, that=123, more=(xyz,123) )

声明。易于解析。

和...

它实际上是Python。一些类声明和工作已经完成。 DSL实际上是类声明。

重要的是DSL只是创建对象。定义DSL时,首先必须从对象模型开始。稍后,您在该对象模型周围添加了一些语法。您不是从语法开始,而是从模型开始。

答案 3 :(得分:4)

是的,有很多 - 太多 - 解析工具,但标准库中没有。

从我看到的PLY和SPARK很受欢迎。 PLY就像是yacc,但是你在Python中做了所有事情,因为你在docstrings中写了你的语法。

就个人而言,我喜欢解析器组合器的概念(取自函数式编程),我非常喜欢pyparsing:你可以直接在python中编写你的语法和动作,并且很容易入手。我最终使用操作生成自己的树节点类型,而不是使用默认的ParserElement类型。

否则,您也可以使用现有的声明性语言,如YAML

答案 4 :(得分:2)

我已经在工作中写了类似的内容来读取SNMP通知定义并自动生成Java类和SNMP MIB文件。使用这个小DSL,我可以编写20行规范,它将生成大约80行Java代码和100行MIB文件。

为了实现这一点,我实际上只是使用直接的Python字符串处理(split(),切片等)来解析文件。我发现Pythons字符串功能足以满足我(解决)大部分(简单)解析需求。

除了其他人提到的库,如果我写的东西更复杂并需要适当的解析功能,我可能会使用ANTLR,它支持Python(和其他语言)。

答案 5 :(得分:2)

彼得,

DSL是好东西,所以你不需要为自己辩护:-) 但是,您考虑过内部DSL吗?这些有很多专业人士与外部(解析)DSL相比,他们至少值得考虑。将DSL与本机语言的强大功能混合在一起可以为您解决许多问题,并且Python在内部DSL上并不是很糟糕,with语句很方便。

答案 6 :(得分:2)

对于您所描述的“小语言”,我使用简单的分割,shlex(注意#定义注释)或正则表达式。

>>> line = 'SOMETHING: !abc @123 #xyz/123'

>>> line.split()
['SOMETHING:', '!abc', '@123', '#xyz/123']

>>> import shlex
>>> list(shlex.shlex(line))
['SOMETHING', ':', '!', 'abc', '@', '123']

以下是一个例子,因为我不确切地知道你在寻找什么。

>>> import re
>>> result = re.match(r'([A-Z]*): !([a-z]*) @([0-9]*) #([a-z0-9/]*)', line)
>>> result.groups()
('SOMETHING', 'abc', '123', 'xyz/123')

答案 7 :(得分:1)

在声明性python的行中,我编写了一个名为'bpyml'的辅助模块,它允许您以更加XML结构的方式在python中声明数据,而不需要详细标记,它也可以转换为XML或从XML转换,但是有效蟒。

https://svn.blender.org/svnroot/bf-blender/trunk/blender/release/scripts/modules/bpyml.py

使用示例 http://wiki.blender.org/index.php/User:Ideasman42#Declarative_UI_In_Blender