예제 #1
0
def parse_binary_expr(node):
    g_flag_vals = list(map(parse_unary, node["val"]))
    g_ops = list(map(parse_bi_oper, node["op"]))
    g_vals = []

    partial_idx = -1
    for i in range(len(g_flag_vals)):
        g_vals.append(g_flag_vals[i][1])
        if g_flag_vals[i][0] == "PARTIAL":
            syntax_cond_assert(
                partial_idx < 0,
                "partial binary expression can only have one unknown arg")
            partial_idx = i

    def ori_warpper(env):
        vals, ops = copy.copy(g_vals), copy.copy(g_ops)
        return compute_expr(env, vals, ops)

    def partial_warpper(env):
        def warpper(v):
            vals, ops = copy.copy(g_vals), copy.copy(g_ops)
            vals[partial_idx] = lambda env: g_vals[partial_idx](env)(v)
            return compute_expr(env, vals, ops)

        return warpper

    func = ori_warpper if partial_idx < 0 else partial_warpper
    return exception_warp(func, node["msg"])
예제 #2
0
 def proc(*arg_val_list):
     syntax_cond_assert(len(arg_var_list) == len(arg_val_list), \
         "unmatched arguments, need %d actually %d"%(len(arg_var_list), len(arg_val_list)))
     new_env = Env(arg_var_list, arg_val_list, outer=env)
     val = body_f(new_env)
     del new_env
     return val
예제 #3
0
def parse_case_expr(node, args_num=0):

    val = parse_block_or_expr(node["val"])

    if node["type"] == "CASE_IF":
        cond_expr = parse_pipe_or_expr(node["cases"])
        cond = lambda env, args: (cond_expr(env), [])
    elif node["type"] == "CASE_MULTI":
        syntax_cond_assert(args_num >= len(node["cases"]),
                           "args less than case patterns")
        match_cases = list(map(parse_case_match_expr, node["cases"]))
        cond = lambda env, args: match_multi_cases(match_cases, args)
    else:
        # CASE_OTHERWISE
        cond = lambda env, args: (True, [])

    return (cond, val)
예제 #4
0
def parse_args(node):
    syntax_cond_assert(node["type"] in ("ARGS", "TUPLE", "PARN", "PARTIAL"),
                       "error type")
    arg_vals = list(map(parse_pipe_or_expr, node["val"]))
    default_vals = []
    if "default_vals" in node:
        default_vals = list(map(parse_pipe_or_expr, node["default_vals"]))

    partial_idx = []
    for i, t in enumerate(arg_vals):
        if t is PARTIAL_FLAG_LAMBDA:
            partial_idx.append(i)

    def _args(env):
        r_default = {}
        if "default_args" in node:
            r_default_vals = [f(env) for f in default_vals]
            r_default = dict(zip(node["default_args"], r_default_vals))
        r_arg_vals = [f(env) for f in arg_vals]
        return (r_arg_vals, r_default)

    return _args, tuple(partial_idx)
예제 #5
0
    def python_import(_from, _import, _as):
        if _from:
            fromlist = _from.split(".")
            top_module = __import__(_from, fromlist=fromlist)
        _import_str, _import_val = "", []
        for tkn in _import:
            if tkn.tp == "SEP":
                syntax_cond_assert(_import_str != "")
                _import_val.append(_import_str)
                _import_str = ""
            else:
                _import_str += tkn.val

        if _import_str: _import_val.append(_import_str)

        env = {}
        syntax_cond_assert(len(_as) == 0 or len(_as) == len(_import_val))
        as_name = _as + [None] * len(_import_val)
        for t, g in zip(_import_val, as_name):
            sub_modules = t.split(".")
            nm = g if g else sub_modules[-1]
            if _from: env[nm] = top_module.__getattribute__(t)
            else: env[nm] = __import__(t, fromlist=sub_modules)
        return env
예제 #6
0
def parse_assign(node):
    if node["val"]["type"] in ("ASSIGN", "GASSIGN"):
        val = parse_assign(node["val"])
    else:
        val = parse_pipe_or_expr(node["val"])
    var_idx_val = None

    def _assign_var(env):
        right_val = val(env)
        if node["type"] == "GASSIGN":
            env = env.globals
        env[var] = right_val
        return right_val

    def _assign_expr_val(env):
        right_val = val(env)
        left_idx = var_idx_val(env)
        if node["type"] == "GASSIGN":
            env = env.globals
        left_val = var_val(env)
        left_val[left_idx] = right_val
        return right_val

    def _assign_unpack(env):
        right_val = val(env)
        if node["type"] == "GASSIGN":
            env = env.globals
        env.update(lst_combine(vars_tuple, right_val))
        return right_val

    if node["var"]["type"] == "VAR":
        var = node["var"]["name"]
        return _assign_var
    elif node["var"]["type"] == "TUPLE":
        vars_tuple = []
        for ele in node["var"]["val"]:
            if ele["type"] != "VAR":
                Error("multi assign only support variables, like a,b,c")
            vars_tuple.append(ele["name"])
        return _assign_unpack
    else:
        var = node["var"]
        syntax_cond_assert(var["type"] == "UNARY" and len(var["suffix"]) > 0,
                           "assign: left value is invalid")
        var_idx = var["suffix"][-1]
        var["suffix"] = var["suffix"][0:-1]
        syntax_cond_assert(var_idx["type"] == "LIST",
                           "assign: left value is invalid")
        syntax_cond_assert(
            len(var_idx["val"]) == 1, "assign: left value is invalid")
        var_idx_val = parse_pipe_or_expr(var_idx["val"][0])
        var_val = parse_pipe_or_expr(var)
        return _assign_expr_val
예제 #7
0
    nums = len(lines)
    time_start = time.time()
    for line in lines:
        query = line.strip()
        if not query: continue
        ans = engine.apply(query)
        print(query, " =>\t", ans)

    a_time = time.time() - time_start
    print('totally cost', a_time, a_time / nums)


if __name__ == "__main__":
    import sys
    ARGV = sys.argv[1:]
    lex_file, in_str, in_file, dict_dir = None, None, None, None
    for i in range(0, len(ARGV) - 1):
        if ARGV[i] == "-i":
            lex_file = ARGV[i + 1]
        elif ARGV[i] == "-f":
            in_file = ARGV[i + 1]
        elif ARGV[i] == "-s":
            in_str = ARGV[i + 1]
        elif ARGV[i] == "-d":
            dict_dir = ARGV[i + 1]

    syntax_cond_assert(lex_file is not None, "need input lex file")
    syntax_cond_assert(in_str or in_file, "need input str")
    run(lex_file, in_str, in_file, dict_dir)
예제 #8
0
def parse_parn(node):
    syntax_cond_assert(len(node["val"]) == 1, "error: empty parn")
    parn_node = parse_pipe_or_expr(node["val"][0])
    return lambda env: parn_node(env)
예제 #9
0
def lst_combine(var, v):
    syntax_cond_assert(
        len(var) == len(v),
        "Value error: unpack %d values with %d variables" % (len(var), len(v)))
    return list(zip(var, v))
예제 #10
0
 def _cd(env):
     cmd_val = cmd(env)
     syntax_cond_assert(
         type(cmd_val) in [str, int],
         "Value Error: cd accept a string or int")
     return cd(cmd_val)
예제 #11
0
def parse_import(node):

    import sys, os

    def python_import(_from, _import, _as):
        if _from:
            fromlist = _from.split(".")
            top_module = __import__(_from, fromlist=fromlist)
        _import_str, _import_val = "", []
        for tkn in _import:
            if tkn.tp == "SEP":
                syntax_cond_assert(_import_str != "")
                _import_val.append(_import_str)
                _import_str = ""
            else:
                _import_str += tkn.val

        if _import_str: _import_val.append(_import_str)

        env = {}
        syntax_cond_assert(len(_as) == 0 or len(_as) == len(_import_val))
        as_name = _as + [None] * len(_import_val)
        for t, g in zip(_import_val, as_name):
            sub_modules = t.split(".")
            nm = g if g else sub_modules[-1]
            if _from: env[nm] = top_module.__getattribute__(t)
            else: env[nm] = __import__(t, fromlist=sub_modules)
        return env

    def user_import_py(path, _as):
        from importlib.machinery import SourceFileLoader
        return SourceFileLoader(_as, path).load_module()

    def user_import_psh(path, module_name):
        from eval_ast import load_psh_file

        def _load(env):
            env.update({module_name: load_psh_file(path, env)})

        return _load

    """  not neccssily
    def user_import_package(path, file_suffix):
        if file_suffix == ".py":
            return user_import_py(path + file_suffix, _as)
        elif file_suffix == ".psh":
            return user_import_psh(path)
        else:
            onlyfiles = [ f for f in os.listdir(path) ]
            env[_as] = user_import_package(path)
    """

    _from, _import, _as = node["from"], node["import"], node["as"]
    module = {}
    if _from or _import[0].tp != "STRING":
        module = python_import(_from, _import, _as)
        return lambda env: env.update(module)
    else:
        syntax_cond_assert(
            len(_as) <= 1, "User Import Error: too many names after AS")
        path = _import[0].val.strip()
        syntax_cond_assert(os.path.isfile(path),
                           "Error: path %s is not a file" % path)
        if len(_as) == 1:
            module_name = _as[0]
        else:
            module_name = os.path.split(path)[1].split(".")[0]

        if path.endswith(".py"):
            module_context = user_import_py(path, module_name)
            return lambda env: env.update({module_name: module_context})
        elif path.endswith(".psh"):
            return user_import_psh(path, module_name)
        else:
            Error("expected py or psh file")
예제 #12
0
 def _sh(env):
     cmd_val = cmd(env)
     syntax_cond_assert(
         type(cmd_val) == str, "Value Error: sh handles a string")
     return osCall(cmd_val)