133 lines
4.2 KiB
Python
133 lines
4.2 KiB
Python
from parsimonious.grammar import Grammar
|
|
from parsimonious.nodes import NodeVisitor
|
|
|
|
from . import logger
|
|
from .terms import (
|
|
constant_term,
|
|
define_equal,
|
|
define_walrus,
|
|
define_term,
|
|
binop,
|
|
compare,
|
|
cmdarg_term,
|
|
command_shell,
|
|
get_var,
|
|
ternary_term,
|
|
run_function,
|
|
cascade_term,
|
|
)
|
|
|
|
|
|
class Execuitor(NodeVisitor):
|
|
"""
|
|
NodeVisitor that visits each node in a parsed command component,
|
|
and builds a forward-directional ExecTerm from them.
|
|
"""
|
|
|
|
def lift_child_log(self, node, visited_children):
|
|
print(f"NODE: {node} WITH {visited_children}")
|
|
return self.lift_child(node, visited_children)
|
|
|
|
visit_basicterm = lift_child_log
|
|
|
|
def visit_parenthised(self, node, visited_children):
|
|
print(f"PARENTH: {visited_children}")
|
|
_, child, _ = visited_children[0]
|
|
return child
|
|
|
|
def visit_command(self, node, visited_children):
|
|
print(f"COMMAND: {visited_children}")
|
|
_, component, _ = visited_children
|
|
return command_shell(node.text, component)
|
|
|
|
def visit_bool(self, node, boolterm):
|
|
(value,) = boolterm[0]
|
|
if value.text.lower() == "true":
|
|
return constant_term(node.text, True)
|
|
elif value.text.lower() == "false":
|
|
return constant_term(node.text, False)
|
|
else:
|
|
raise ValueError(f"Unrecognised bool {value.text}")
|
|
|
|
def visit_test(self, node, testterm):
|
|
(expr,) = testterm
|
|
term1, op, term2 = expr
|
|
return compare(node.text, term1, op.text, term2)
|
|
|
|
def generic_visit(self, node, visited_children):
|
|
"""If we don't have a rule for this node return it as raw text, but evaluatable"""
|
|
print(f"GENERIC: {node} WITH {visited_children}")
|
|
return visited_children or node
|
|
|
|
def visit_quoted(self, node, visited_children):
|
|
return constant_term(node.text, node.text[1:-1])
|
|
|
|
def visit_keyword(self, node, visited_children):
|
|
return node.text
|
|
|
|
def visit_word(self, node, visited_children):
|
|
return node.text
|
|
|
|
def visit_equals(self, node, defineterms):
|
|
var, _, _, _, term = defineterms
|
|
return define_equal(node.text, str(var), term)
|
|
|
|
def visit_defines(self, node, defineterms):
|
|
var, _, _, _, term = defineterms
|
|
return define_walrus(node.text, str(var), term)
|
|
|
|
def visit_definesterm(self, node, defineterms):
|
|
var, _, _, _, term = defineterms
|
|
return define_term(node.text, str(var), term)
|
|
|
|
def visit_numeric(self, node, numeric_term):
|
|
return constant_term(node.text, int(node.text))
|
|
|
|
def visit_cmdarg(self, node, visited_children):
|
|
_, argspec = visited_children
|
|
return cmdarg_term(
|
|
node.text, int(argspec.text.strip("$*")), argspec.text.endswith("*")
|
|
)
|
|
|
|
def visit_ternary(self, node, visited_children):
|
|
print(f"TERNARY: {visited_children}")
|
|
cond, _, arg1, _, arg2 = visited_children
|
|
return ternary_term(node.text, cond, arg1, arg2)
|
|
|
|
def visit_term(self, node, visited_children):
|
|
print(f"TERM: {visited_children}")
|
|
_, value, _ = visited_children
|
|
(child,) = value
|
|
return child
|
|
|
|
def visit_component(self, node, visited_children):
|
|
print(f"COMPONENT: {visited_children}")
|
|
_, value, _ = visited_children
|
|
(child,) = value
|
|
return child
|
|
|
|
def visit_var(self, node, varterm):
|
|
root, remaining = varterm
|
|
(root,) = root
|
|
terms = (root, *(attr for _, attr in remaining))
|
|
return get_var(node.text, *terms)
|
|
|
|
def visit_function(self, node, visited_children):
|
|
print(f"FUNCTION: {node.text}, {visited_children}")
|
|
func, remaining = visited_children
|
|
args = (term for _, term in remaining)
|
|
return run_function(node.text, func, *args)
|
|
|
|
def visit_cascade(self, node, visited_children):
|
|
print(f"CASCADE: {visited_children}")
|
|
term, remaining = visited_children
|
|
terms = (term, *(bterm for _, bterm in remaining))
|
|
return cascade_term(node.text, *terms)
|
|
|
|
def visit_binop(self, node, binopterm):
|
|
(expr,) = binopterm
|
|
term1, remaining = expr
|
|
op = remaining[0][0]
|
|
terms = (term1, *(bterm for _, bterm in remaining))
|
|
return binop(node.text, op.text, *terms)
|