2008-12-04 86 views
5

我正在用python编写游戏,并决定为地图数据文件创建一个DSL。我知道我可以使用正则表达式编写我自己的解析器,但我想知道是否有现成的Python工具可以更轻松地完成此工作,例如PHP引擎中使用的re2c。在python中编写DSL的编译器

一些额外的信息:

  • 是的,我做需要一个DSL,即使我不是我还是想建设的经验,利用一个在项目中。
  • DSL只包含数据(声明?),它不会“执行”。大多数行类似:

    SOMETHING: !abc @123 #xyz/123

    我只需要读取数据的树。

回答

3

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

从我看到的PLY和SPARK中受欢迎。 PLY就像yacc,但是你在Python中执行所有操作,因为你在文档字符串中编写了语法。个人而言,我喜欢解析器组合器的概念(取自函数式编程),我非常喜欢pyparsing:您直接在Python中编写语法和动作,并且很容易就可以开始。我最终通过动作产生了我自己的树节点类型,而不是使用它们的默认ParserElement类型。

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

11

我一直对pyparsing印象深刻。作者Paul McGuire在python list/comp.lang.python上活跃,并且对任何疑问都非常有帮助。

+0

我会建议,如果你不这么做了! PyParsing非常棒。 – 2008-12-04 08:36:57

6

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

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

声明。易于解析。

And ...

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

重要的是DSL仅仅创建对象。当你定义一个DSL时,首先你必须从一个对象模型开始。稍后,您将围绕该对象模型提供一些语法。您不是从语法开始,而是从模型开始。

+0

我知道你在说什么,但是编写所有这些注释,括号,等号,前缀都是对实际数据的混淆。而且,这种方法并不适用于PHP或Java等更冗长的语言。 – 2008-12-04 01:23:38

+0

@Peter。不同意。您可以使用位置参数并删除标签和=。它完全转化为Java。已经在生产应用中使用它来定义声明式DSL。 – 2008-12-04 01:28:58

2

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

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

除了别人提到的库之外,如果我写的东西比较复杂,需要正确的解析能力,我可能会使用支持Python(和其他语言)的ANTLR

2

彼得,

的DSL是一个好事,所以你不需要为自己辩护:-) 但是,你有没有考虑内部DSL?这些有很多专业人士与外部(解析)的DSL,他们至少值得考虑。将DSL与本地语言的强大功能相结合确实为您解决了许多问题,并且Python在内部DSL方面并不是很糟糕,因为with语句非常方便。

2

对于所描述的“小语言”,我使用简单的split,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')