def test_11_namespaceRules(self): """ Test the namespace handling """ parser = parsing.Parser() @meta.add_method(parsing.Parser) def dummy(self): res = parsing.Node() res.text = "cool" self.rule_nodes["_"] = res return True meta.set_one(parsing.Parser._rules, "A.B.C.test", parsing.Call(parsing.Parser.dummy)) bRes = parser.eval_rule('test') self.assertEqual(bRes.text, "cool", "failed rule node in global namespace") bRes = parser.eval_rule('C.test') self.assertEqual(bRes.text, "cool", "failed rule node in global namespace") bRes = parser.eval_rule('B.C.test') self.assertEqual(bRes.text, "cool", "failed rule node in global namespace") bRes = parser.eval_rule('A.B.C.test') self.assertEqual(bRes.text, "cool", "failed rule node in global namespace")
def set_directives(cls, directives: dict) -> bool: """ Merge internal directives set with the given directives. For working directives, attach it only in the dsl.Parser class """ meta._directives = meta._directives.new_child() for dir_name, dir_pt in directives.items(): meta.set_one(meta._directives, dir_name, dir_pt) dir_pt.ns_name = dir_name return True
def set_hooks(cls, hooks: dict) -> bool: """ Merge internal hooks set with the given hooks """ cls._hooks = cls._hooks.new_child() for hook_name, hook_pt in hooks.items(): if '.' not in hook_name: hook_name = cls.__module__ \ + '.' + cls.__name__ \ + '.' + hook_name meta.set_one(cls._hooks, hook_name, hook_pt) return True
def set_rules(cls, rules: dict) -> bool: """ Merge internal rules set with the given rules """ cls._rules = cls._rules.new_child() for rule_name, rule_pt in rules.items(): if '.' not in rule_name: rule_name = cls.__module__ \ + '.' + cls.__name__ \ + '.' + rule_name meta.set_one(cls._rules, rule_name, rule_pt) return True
def __new__(metacls, name, bases, namespace): # for multi heritance we have a simple inheritance relation # from the first class in declaration order. metabp = parsing.MetaBasicParser if len(bases) <= 1: cls = metabp.__new__(metacls, name, bases, namespace) else: b = tuple([bases[0]]) cls = metabp.__new__(metacls, name, b, namespace) # lookup for the metaclass of parsing. # Grammar magically inherit rules&hooks from Parser if 'Parser' in parsing.base._MetaBasicParser: clsbase = parsing.base._MetaBasicParser['Parser'] # link rules&hooks cls._rules = clsbase._rules.new_child() cls._hooks = clsbase._hooks.new_child() # add rules from DSL if 'grammar' in namespace and namespace['grammar'] is not None: sname = None if 'source' in namespace and namespace['source'] is not None: sname = namespace['source'] rules = cls.dsl_parser(namespace['grammar'], sname).get_rules() if not rules: return rules # namespace rules with module/classe name for rule_name, rule_pt in rules.items(): if '.' not in rule_name: rule_name = cls.__module__ \ + '.' + cls.__name__ \ + '.' + rule_name meta.set_one(cls._rules, rule_name, rule_pt) # add localy define rules (and thus overloads) if '_rules' in namespace and namespace['_rules'] is not None: cls._rules.update(namespace['_rules']) # add localy define hooks if '_hooks' in namespace and namespace['_hooks'] is not None: cls._hooks.update(namespace['_hooks']) # Manage Aggregation if len(bases) > 1: aggreg_rules = ChainMap() aggreg_hooks = ChainMap() for subgrammar in bases: if hasattr(subgrammar, '_rules'): aggreg_rules = ChainMap(*(aggreg_rules.maps + subgrammar._rules.maps)) if hasattr(subgrammar, '_hooks'): aggreg_hooks = ChainMap(*(aggreg_hooks.maps + subgrammar._hooks.maps)) # aggregate at toplevel the branch grammar cls._rules = ChainMap(*(cls._rules.maps + aggreg_rules.maps)) cls._hooks = ChainMap(*(cls._hooks.maps + aggreg_hooks.maps)) # clean redondant in chain for rules orderedunique_rules = [] tocpy_rules = set([id(_) for _ in cls._rules.maps]) for ch in cls._rules.maps: idch = id(ch) if idch in tocpy_rules: orderedunique_rules.append(ch) tocpy_rules.remove(idch) cls._rules = ChainMap(*orderedunique_rules) # clean redondant in chain for hooks orderedunique_hooks = [] tocpy_hooks = set([id(_) for _ in cls._hooks.maps]) for ch in cls._hooks.maps: idch = id(ch) if idch in tocpy_hooks: orderedunique_hooks.append(ch) tocpy_hooks.remove(idch) cls._hooks = ChainMap(*orderedunique_hooks) return cls