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

如何用python编写带有运算符模块的小型DSL解析器,python,dsl,operation,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 1

见以下矩阵数据:

    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
A> C
B> C
C> D和DF

A+BDSL的示例语法有多重要?最简单的方法是使用Python表达式语法和eval()。否则,可能会将表单转换为可评估的内容。

如下所示

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 ) )
等等


编辑

  • str(A)march regex“[2-5][0-2]”
  • myfoo(A)>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教程可能会有所帮助。

谢谢您的回复,但我认为设计外部DSL是一个更好的主意,至少它会更具可扩展性。这是从我上一篇文章的答案中得到启发的,但坦率地说,到目前为止我还不知道如何做到这一点。我正在考虑使用eval(),问题是如何在一行中处理规则字符串?我的意思是,A B C D和$listname?如果规则不是精确的Python表达式,这将失败。OP的例子并非如此。@delnan:尽管如此,我怀疑OP的DSL是否已经被法律或其他标准所固定。我怀疑在指定的DSL中有一点机动空间。@s.Lott,感谢您的示例,它非常清晰简单。虽然我仍然对使用eval()代替DSL有疑问,但如何处理以下3个规则字符串:str(A)march regex“[2-5][0-2]”,myfoo(A)>100,A在myfoo(B)@delnan中,如果eval()可以解决我想要的所有请求,我认为它也是可以接受的,因为毕竟它是一个内部DSL,而设计外部DSL相当复杂,但我怀疑eval()可能不那么可扩展later@user478514:请更新问题,使其完整且符合所有要求。
r4= Rule( "re.match( r'[2-5][0-2]', str(A) )" )
r5= Rule( "myfoo(A) > 100" )
r6= Rule( "A in myfoo(B)" )