如何在python中编写带有运算符模块的小型DSL解析器

时间:2011-06-01 17:56:30

标签: python dsl operation

见下面的矩阵数据:

    A   B   C   D   E   F   G
1   89  92  18  7   90  35  60
2   62  60  90  91  38  30  50
3   59  91  98  81  67  88  70
4   20  28  31  9   91  6   18
5   80  27  66  1   33  91  18
6   82  30  47  8   39  22  32
7   14  11  70  39  18  10  56
8   98  95  84  47  28  62  99

我需要定义“rule”函数可以为每行数据的下面断言字符串返回“true”或“false”:

A=B and B=C
A>C
B>C
C>D and D<E or D>F
A+B<30
A+B<=30                # this may using "A+B<30 or A+B=30" as alternative
str(A) march regex"[2-5][0-2]" 
myfoo(A) > 100 
A in myfoo(B)
A not_in $listname
A in $listname

“A = B和B = C”为例:如果我将第1行传递给此规则,我希望规则返回false,因为在这种情况下它不正确。

我的问题是:

  1. 如何定义DSL解析器以将这些“规则字符串”转换为可行的lambda函数,然后我可以调用此lambda并将数据行作为参数来返回断言结果?

  2. 我注意到模块操作有很多数学函数我可以重用来定义规则,我可以为DSL解析器使用这些关键字创建一个“映射器”吗? 它可能看起来像:

    keywords = {“+”:operation.add(),             “/”:operation.div(),             “和”:my_and_define()            }

  3. 如果可能超过2,我如何处理lambda和mapper中的“A in $ listname”?

  4. 感谢您的帮助。

    RGS,

    KC

2 个答案:

答案 0 :(得分:1)

DSL的示例语法有多重要?最简单的方法是使用Python表达式语法和eval()。否则,可能会从您的表单转换为eval()能够。

答案 1 :(得分:1)

喜欢这个。

class Rule( object ):
    def __init__( self, text ):
        self.text= text
    def test( self, A, B, C, D, E, F, G ):
        return eval( self.text )

r1= Rule( "A==B" )
r2= Rule( "A==B and B==C" )
r3= Rule( "A in {listname!s}".format( listname=someList ) )

>>> r1.test( 89,  92,  18,  7,   90,  35, 60 )
False

编辑。

  • str(A)march regex“[2-5] [0-2]”
  • myfoo(A)&gt; 100
  • A在myfoo(B)

这些都是微不足道的Python代码。我不确定为什么评论甚至被包括在内有趣或困难。

r4= Rule( "re.match( r'[2-5][0-2]', str(A) )" )
r5= Rule( "myfoo(A) > 100" )
r6= Rule( "A in myfoo(B)" )

这有一个诀窍。诀窍是编写Python代码;然后将代码括在引号中。 任何 Python代码都是合法的。

如果这些规则的Python方面很混乱,那么Python教程可能会有所帮助。