From 00a146dbd5faff6bd7906a680694c9397e300867 Mon Sep 17 00:00:00 2001 From: asagi4 <130366179+asagi4@users.noreply.github.com> Date: Wed, 22 Nov 2023 01:09:18 +0200 Subject: [PATCH] Use new parser --- utils/wildcards.py | 170 +++------------------------------------------ 1 file changed, 11 insertions(+), 159 deletions(-) diff --git a/utils/wildcards.py b/utils/wildcards.py index a18ff09..6ce0ebe 100644 --- a/utils/wildcards.py +++ b/utils/wildcards.py @@ -3,10 +3,8 @@ from os import environ import random import re from pathlib import Path -from collections import ChainMap -from .jinja_render import render_jinja -from .parse import parse, pparse +from .parse import parse # from .parse import parse @@ -36,6 +34,13 @@ def handle_wildcard_node(json_data, node_id): return json_data +def read_preamble(): + curfile = Path(__file__) + defaults = curfile.parent / "default_functions.txt" + with open(defaults, "r") as f: + return parse(f.read())[1] + + def find_and_remove(regexp, text, placeholder=""): m = regexp.search(text) res = {} @@ -55,159 +60,6 @@ def find_and_remove(regexp, text, placeholder=""): return res, text -def function_definitions(text): - # $foo($a, $b...) { bodygoeshere \} } - func_re = re.compile( - r"def(?Pj?)\s+(?P\$[a-z]+)\((?P(\s*\$[a-z]+\s*;)*(\s*\$[a-z]+\s*)?)\)\s*\{(?P.*?)(?\$[a-z]+)\((?P.*?)(?(\s*?\$[a-z]+\s*=[^;\n]*;?)+)") - defs, text = find_and_remove(var_re, text) - res = {} - for k, v in defs.items(): - for d in (x for x in v["name"].strip().split(";") if x.strip()): - name, value = d.split("=", 1) - res[name.strip()] = value.strip() - return res, text - - -def push_context(ctx): - for k in ctx.keys(): - ctx[k] = ctx[k].new_child() - - -def pop_context(ctx): - for k in ctx.keys(): - ctx[k] = ctx[k].parents - - -def parent_context(ctx): - new_ctx = {} - for k in ctx.keys(): - new_ctx[k] = ctx[k].parents - return new_ctx - - -class Nothing: - def __repr__(self): - return "Nothing" - - -RECURSIVE_VARIABLE = Nothing() - - -def read_preamble(): - curfile = Path(__file__) - defaults = curfile.parent / "default_functions.txt" - with open(defaults, "r") as f: - defs = f.read() - _, defs = find_and_remove(re.compile("^#.*"), defs) - return defs - - -def read_preamble_new(func): - curfile = Path(__file__) - defaults = curfile.parent / "default_functions2.txt" - with open(defaults, "r") as f: - return func(f.read()) - - -def init_context(): - ctx = {"funcs": ChainMap(), "vars": ChainMap()} - curfile = Path(__file__) - defaults = curfile.parent / "default_functions.txt" - with open(defaults, "r") as f: - defs = f.read() - _, defs = find_and_remove(re.compile("^#.*"), defs) - funcs, _ = function_definitions(defs) - ctx["funcs"].update(funcs) - return ctx - - -def variable_substitution(text, ctx=None, allow_definitions=True, jinja_render=False): - if ctx is None: - ctx = init_context() - - funcs, text = function_definitions(text) - if allow_definitions: - ctx["funcs"].update(funcs) - vars, text = variable_definitions(text) - ctx["vars"].update(vars) - calls, text = function_calls(text) - - regex = re.compile(r"(?P\$[a-z]+)(?!\()\b") - vars, text = find_and_remove(regex, text, placeholder="VARIABLE") - - for placeholder, var in vars.items(): - value = ctx["vars"].get(var["name"]) - name = var["name"] - if value is None: - raise ValueError(f"Undefined variable {name}") - if value is RECURSIVE_VARIABLE: - raise ValueError(f"Recursive variable in definition of {name}") - push_context(ctx) - ctx["vars"][name] = RECURSIVE_VARIABLE - value = variable_substitution(value, ctx, allow_definitions=False) - pop_context(ctx) - text = text.replace(placeholder, value) - - for k, v in calls.items(): - f = ctx["funcs"].get(v["name"]) - if not f: - text = text.replace(k, "") - log.warning("Function %s not found, ignoring", v["name"]) - continue - if len(v["args"]) != len(f["vars"]): - log.warning("Invalid function call to %s, ignoring", v["name"]) - ex = "; ".join(f["vars"]) - log.warning("Call syntax: %s(%s)", v["name"], ex) - - continue - - push_context(ctx) - for var, val in zip(f["vars"], v["args"]): - r = variable_substitution(val, parent_context(ctx)) - r = r.replace("\(", "(").replace("\)", ")") - ctx["vars"][var] = r - - j = f.get("jinja") - replacement = variable_substitution(f["body"], ctx, jinja_render=j) - text = text.replace(k, replacement) - pop_context(ctx) - - if jinja_render: - t = render_jinja(text) - if t.strip() != text.strip(): - text = t - - return text.strip() - - class MUSimpleWildcard: RAND = random.Random() @@ -271,7 +123,8 @@ class MUSimpleWildcard: if use_pnginfo and unique_id in extra_pnginfo.get(CLASS_NAME, {}): text = extra_pnginfo[CLASS_NAME][unique_id] log.info("MUSimpleWildcard using prompt: %s", text) - newtext = variable_substitution(text) + ctx = read_preamble() + newtext = parse(text, ctx) if newtext != text: log.info("MUSimpleWildcard result:\n%s", newtext) return (newtext,) @@ -285,5 +138,4 @@ except ImportError: print("Could not install wildcard prompt handler, node won't work") if __name__ == "__main__": - _, ctx = read_preamble_new(parse) - pparse("") + ctx = read_preamble()