如何在 python 中使用运算符模块编写小型 DSL 解析器

发布于 2024-11-13 11:30:45 字数 1147 浏览 4 评论 0原文

请参阅下面的矩阵数据:

    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

我需要定义“规则”函数可以为每行数据的以下断言字符串返回“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 = {"+": 操作.add(), “/”:操作.div(), “和”:my_and_define() 我

  3. 如果以上 2 种可能,我如何在 lambda 和映射器中处理“A in $listname”?

感谢您的帮助。

Rgs,

KC

See below matrix data:

    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

I need to define "rule" function can return "true" or "false" for below asserts string for each row data:

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

Take "A=B and B=C" for example: If I pass row 1 into this rule, I want the rule return false because it is not right in this case.

My questions are:

  1. How can I define a DSL parser to translater those "rules string" into a workable lambda function, then I can invoke this lambda with data row as parameter to return the assert result?

  2. I noticed the module operation has a lot of math functions I can reuse to define the rule, can I create a "mapper" for those keywords for DSL parser use?
    It may looks like:

    keywords = {"+": operation.add(),
    "/": operation.div(),
    "and": my_and_define()
    }

  3. if above 2 are possible, how can I process the "A in $listname" in the lambda and in the mapper?

Thanks for your help.

Rgs,

KC

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

記柔刀 2024-11-20 11:30:45

像这样。

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) 行军正则表达式"[2-5][0-2]"
  • myfoo(A) > 100
  • A is in 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 教程可能会有所帮助。

Like this.

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

etc.

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

Edit.

  • str(A) march regex"[2-5][0-2]"
  • myfoo(A) > 100
  • A is in myfoo(B)

These are all trivial Python code. I'm not sure why the comment is even included as being interesting or difficult.

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

There's a trick to this. The trick is to write the Python code; and then enclose the code in quotes. Any Python code is legal.

If the Python aspect of these rules is confusion, a Python tutorial may be helpful.

青春有你 2024-11-20 11:30:45

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

How important is the example syntax of your DSL? The simplest approach would be to use the Python expression syntax and eval(). Otherwise it might be possible to translate from your form to something eval()able.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文