一些额外的信息: - 是的,我需要一个DSL,即使我不需要,我仍然希望在项目中构建和使用它。 - DSL仅包含数据(声明性?),它不会被“执行”。 大多数行看起来像:SOMETHING: !abc @123 #xyz/123。我只需要读取数据树。
我一直对 pyparsing 感到印象深刻。作者 Paul McGuire 在 python list/comp.lang.python 上积极参与,对任何有关它的问题都非常乐于助人。
abc= ONETHING( ... )
xyz= ANOTHERTHING( ... )
pqr= SOMETHING( this=abc, that=123, more=(xyz,123) )
声明式的。易于解析的。
而且...
它实际上是Python。只需几个类声明就可以完成工作。DSL实际上是类声明。
重要的是,DSL仅创建对象。当您定义DSL时,首先必须从对象模型开始。稍后,您在该对象模型周围放置一些语法。您不是从语法开始,而是从模型开始。
DSL(领域特定语言)是一件好事,所以您无需自卫 :-)
然而,您是否考虑过使用内部DSL?与外部(解析)DSL相比,它们有很多优点,因此至少值得考虑。将DSL与本地语言的强大功能混合使用确实可以为您解决许多问题,而Python在内部DSL方面表现不错,特别是“with”语句非常方便。
with
语句对于内部领域特定语言有什么好处?我很好奇。 - fferri>>> 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')
a <=> b
to:
a , b = b , a
from tokenize import untokenize, tokenize, NUMBER, STRING, NAME, OP, COMMA
import io
import ast
s = b"a <=> b\n" # i may read it from file
b = io.BytesIO(s)
g = tokenize(b.readline)
result = []
for token_num, token_val, _, _, _ in g:
# naive simple approach to compile a<=>b to a,b = b,a
if token_num == OP and token_val == '<=' and next(g).string == '>':
first = result.pop()
next_token = next(g)
second = (NAME, next_token.string)
result.extend([
first,
(COMMA, ','),
second,
(OP, '='),
second,
(COMMA, ','),
first,
])
else:
result.append((token_num, token_val))
src = untokenize(result).decode('utf-8')
exp = ast.parse(src)
code = compile(exp, filename='', mode='exec')
def my_swap(a, b):
global code
env = {
"a": a,
"b": b
}
exec(code, env)
return env['a'], env['b']
print(my_swap(1,10))
借鉴Python的声明性编程思想,我编写了一个辅助模块名为“bpyml”。它可以让你以更类似XML结构的方式在Python中声明数据,而不需要冗长的标签。该模块也可以实现Python与XML之间的互相转换,且输出结果仍是合法的Python代码。
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