Skip to content

Instantly share code, notes, and snippets.

@shippy
Last active September 18, 2018 07:40
Show Gist options
  • Save shippy/e10448321f6b9c1e51f836a7abf1c05c to your computer and use it in GitHub Desktop.
Save shippy/e10448321f6b9c1e51f836a7abf1c05c to your computer and use it in GitHub Desktop.
Using nested rules with Dragonfly
# A proof of concept for implementing re-usable nested rules in Dragonfly.
#
# See http://simon.podhajsky.net/blog/2017/executing-nested-rules-with-dragonfly/
# for the accompanying article.
try:
import pkg_resources
pkg_resources.require("dragonfly >= 0.6.5beta1.dev-r99")
except ImportError:
pass
from dragonfly import *
from execute_factory import executeFactory, multipleExecuteFactory
print 'Test grammar accessed.'
config = Config("test")
config.cmd = Section("Language section")
namespace = config.load()
# Debug functions
def inspectFunctionCall(**kwargs):
print "I was called with", len(kwargs), "kwarguments:", kwargs
# Rules proper
class RuleA(MappingRule):
exported = False
mapping = {
"add <n>": Text('RuleA %(n)s'),
}
extras = [
IntegerRef("n", 1, 10),
]
class RuleB(MappingRule):
exported = False
mapping = {
"bun <n>": Text("RuleB %(n)s") ,
}
extras = [
IntegerRef("n", 1, 10),
]
class RuleMain(MappingRule):
name = "rule_main"
exported = True
mapping = {
"boo <rule_b> and <rule_a>": Text("Rule matched: B and A!") + multipleExecuteFactory(['rule_b', 'rule_a']),
"fair <rule_a> and <rule_b>": Text("Rule matched: A and B!") + executeFactory('rule_a') + executeFactory('rule_b'),
}
extras = [
RuleRef(rule = RuleA(), name = "rule_a"),
RuleRef(rule = RuleB(), name = "rule_b")
]
grammar = Grammar("Test grammar")
grammar.add_rule(RuleMain())
grammar.load()
def unload():
global grammar
if grammar: grammar.unload()
grammar = None
# Use in mapping of nested rules.
#
# mapping = {
# "do <rule_a> <rule_b>": execute_rule("rule_b") + execute_rule("rule_a"),
# "boo <rule_a> <rule_b>": execute_rule("rule_b", "rule_a"),
# }
#
# extras = [
# RuleRef(rule = RuleA(), name = "rule_a"),
# RuleRef(rule = RuleB(), name = "rule_b"),
# ]
from dragonfly import Function, ActionBase
def _executeRecursive(executable):
if isinstance(executable, ActionBase):
executable.execute()
elif hasattr(executable, '__iter__'):
for item in executable:
_executeRecursive(item)
else:
print "Neither executable nor a list: ", executable
def execute_rule(*rule_names):
def _exec_function(**kwargs):
for name in rule_names:
executable = kwargs.get(name)
_executeRecursive(executable)
return Function(_exec_function)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment