...

使用正则解析Python赋值及函数调用表达式

在使用BDD时,想实现一种描述函数调用及赋值操作的 通用步骤,因此实现了以下正则解析

特性

  • 支持函数调用,有参/无参,有返/无反
  • 支持关键字参数和位置参数
  • 支持变量赋值

TODO

  • $a.b取值
  • 支持字典/列表类型参数

代码实现

import re
from string import Template


# text = 'request'
# text = 'request get https://httpbin.org?a=1&b=2'

def smart_value(var: str):
    if var.isnumeric():  # TODO float
        return int(var)
    return var

def render(text, context):
    return Template(text).safe_substitute(context)

def parse(text, context=None):
    # text = Template(text).safe_substitute(context)
    patten = re.compile('((?P<var>\w+)\s*=\s*)?(?P<func>\S+)(\s+(?P<args>.*))?')
    matched = re.match(patten, text)
    if not matched:
        raise ValueError('不匹配')

    var_name = matched.group('var')
    func_or_value_name = matched.group('func')
    args_raw = matched.group('args')
    args = []
    kwargs = {}
    if args_raw:
        args_raw = render(args_raw, context)
        _args = args_raw.split()
        for arg in _args:
            if arg.startswith('"') or arg.startswith("'"):
                args.append(arg.strip('"|\''))
            else:
                if '=' not in arg:
                    args.append(smart_value(arg))
                else:
                    key, value = arg.split('=', 1)
                    kwargs[key] = smart_value(value)
    return var_name, func_or_value_name, args, kwargs


def call(text, context=None):
    var_name, func_or_value_name, args, kwargs = parse(text, context)
    func = context.get(func_or_value_name)
    value = render(func_or_value_name, context)

    if func:
        if callable(func):
            value = func(*args, **kwargs)
    if var_name:
        context[var_name] = value


if __name__ == '__main__':
    import requests

    context = {'request': requests.request, 'add': lambda a,b: a+b, 'a': '1'}
    text = 'res = add $a b=2'
    text = 'res = $a'
    print(parse(text, context))
    call(text, context)
    print(context['res'])
posted @ 2022-03-11 00:45  韩志超  阅读(199)  评论(0)    收藏  举报