# Path: pyrser/meta.py
# def enum(*sequential, **named):
# def checktypes(func):
#     def check_type(sig, arg_name, arg_type, arg_value):
#     def wrapper(*args, **kwargs):
# def set_one(chainmap, thing_name, callobject):
# def _get_base_class(cls):
# def add_method(cls):
#     def wrapper(f):
# def hook(cls, hookname=None, erase=False):
#     def wrapper(f):
# def rule(cls, rulename=None, erase=False):
#     def wrapper(f):
# def directive(directname=None):
#     def wrapper(f):
# def decorator(directname=None):
#     def wrapper(f):
# 
# Path: pyrser/error.py
# class LocationInfo:
# class Notification:
# class Diagnostic(Exception):
#     def __init__(self, filepath: str, line: int, col: int, size: int=1):
#     def from_stream(stream: 'Stream', is_error=False) -> 'LocationInfo':
#     def from_maxstream(stream: 'Stream', is_error=False) -> 'LocationInfo':
#     def from_here(pos=1):
#     def get_content(self) -> str:
#     def __init__(self, severity: Severity, msg: str,
#                  location: LocationInfo=None, details: str=None):
#     def get_content(self, with_locinfos=False, with_details=False) -> str:
#     def __init__(self):
#     def __bool__(self):
#     def __str__(self) -> str:
#     def notify(self, severity: Severity, msg: str,
#                location: LocationInfo=None, details: str=None) -> int:
#     def add(self, n: Notification) -> int:
#     def get_content(self, with_locinfos=True, with_details=False) -> str:
#     def get_infos(self) -> {Severity, int}:
#     def have_errors(self) -> bool:
# 
# Path: pyrser/parsing/node.py
# class Node(dict):
#     """Base class for node manipulation."""
# 
#     def __bool__(self):
#         return True
# 
#     def __repr__(self):
#         #TODO: use to_yml
#         items = []
#         if len(self) > 0:
#             items.append(repr(self.items()))
#         for k, v in vars(self).items():
#             items.append("{} = {}".format(k, repr(v)))
#         return "{}({})".format(self.__class__.__name__, ', '.join(items))
# 
#     def check(self, ndict: dict, info="") -> bool:
#         """
#         Debug method, help detect cycle and/or
#         other incoherence in a tree of Node
#         """
#         def iscycle(thing, ndict: dict, info: str) -> bool:
#             # check if not already here
#             idthing = id(thing)
#             ndict[info] = idthing
#             if idthing not in ndict:
#                 # add myself
#                 ndict[idthing] = "%s:%s no cycle" % (type(thing), info)
#                 return False
#             else:
#                 ndict[idthing] += "\n%s:%s cycle" % (type(thing), info)
#                 return True
# 
#         def recurs(thing, ndict: dict, info: str) -> bool:
#             if not iscycle(thing, ndict, info):
#                 res = False
#                 if isinstance(thing, list):
#                     idx = 0
#                     for i in thing:
#                         res |= recurs(i, ndict, "%s[%d]" % (info, idx))
#                         idx += 1
#                 elif isinstance(thing, Node):
#                     res |= thing.check(ndict, info)
#                 elif isinstance(thing, dict):
#                     for k, v in thing.items():
#                         res |= recurs(v, ndict, "%s[%s]" % (info, k))
#                 return res
#             return True
#         # add ME FIRST
#         if len(ndict) == 0:
#             ndict['self'] = id(self)
#             info = 'self'
#         if not iscycle(self, ndict, info):
#             res = False
#             if len(self) > 0:
#                 if hasattr(self, 'keys'):
#                     keys = list(self.keys())
#                     for k in keys:
#                         ndict["[" + repr(k) + "]"] = id(self[k])
#                         res |= recurs(self[k], ndict, "%s[%s]" % (info, k))
#             keys = list(vars(self).keys())
#             for k in keys:
#                 ndict["." + k] = id(getattr(self, k))
#                 res |= recurs(getattr(self, k), ndict, "%s.%s" % (info, k))
#             return res
#         return True
# 
#     def clean(self):
#         if len(self) > 0:
#             keys = list(self.keys())
#             for k in keys:
#                 del self[k]
#         keys = list(vars(self).keys())
#         for k in keys:
#             delattr(self, k)
# 
#     def set(self, othernode):
#         """allow to completly mutate the node into any subclasses of Node"""
#         self.__class__ = othernode.__class__
#         self.clean()
#         if len(othernode) > 0:
#             for k, v in othernode.items():
#                 self[k] = v
#         for k, v in vars(othernode).items():
#             setattr(self, k, v)


import collections
import os
from pyrser import meta
from pyrser import error
from pyrser.parsing.stream import Stream
from pyrser.parsing.stream import Tag
from pyrser.parsing.node import Node
        """Save the current index under the given name."""
        # Check if we could attach tag cache to current rule_nodes scope
        self.tag_cache[name] = Tag(self._stream, self._stream.index)
        return True

    def end_tag(self, name: str) -> Node:
        """Extract the string between saved and current index."""
        self.tag_cache[name].set_end(self._stream.index)
        return True

    def get_tag(self, name: str) -> Tag:
        """Extract the string previously saved."""
        return self.tag_cache[name]

    def tag_node(self, name: str, node: Node):
        self.id_cache[id(node)] = name

####

    @classmethod
    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

# Path: pyrser/meta.py
# def enum(*sequential, **named):
# def checktypes(func):
#     def check_type(sig, arg_name, arg_type, arg_value):
#     def wrapper(*args, **kwargs):
# def set_one(chainmap, thing_name, callobject):
# def _get_base_class(cls):
# def add_method(cls):
#     def wrapper(f):
# def hook(cls, hookname=None, erase=False):
#     def wrapper(f):
# def rule(cls, rulename=None, erase=False):
#     def wrapper(f):
# def directive(directname=None):
#     def wrapper(f):
# def decorator(directname=None):
#     def wrapper(f):
# 
# Path: pyrser/error.py
# class LocationInfo:
# class Notification:
# class Diagnostic(Exception):
#     def __init__(self, filepath: str, line: int, col: int, size: int=1):
#     def from_stream(stream: 'Stream', is_error=False) -> 'LocationInfo':
#     def from_maxstream(stream: 'Stream', is_error=False) -> 'LocationInfo':
#     def from_here(pos=1):
#     def get_content(self) -> str:
#     def __init__(self, severity: Severity, msg: str,
#                  location: LocationInfo=None, details: str=None):
#     def get_content(self, with_locinfos=False, with_details=False) -> str:
#     def __init__(self):
#     def __bool__(self):
#     def __str__(self) -> str:
#     def notify(self, severity: Severity, msg: str,
#                location: LocationInfo=None, details: str=None) -> int:
#     def add(self, n: Notification) -> int:
#     def get_content(self, with_locinfos=True, with_details=False) -> str:
#     def get_infos(self) -> {Severity, int}:
#     def have_errors(self) -> bool:
# 
# Path: pyrser/parsing/node.py
# class Node(dict):
#     """Base class for node manipulation."""
# 
#     def __bool__(self):
#         return True
# 
#     def __repr__(self):
#         #TODO: use to_yml
#         items = []
#         if len(self) > 0:
#             items.append(repr(self.items()))
#         for k, v in vars(self).items():
#             items.append("{} = {}".format(k, repr(v)))
#         return "{}({})".format(self.__class__.__name__, ', '.join(items))
# 
#     def check(self, ndict: dict, info="") -> bool:
#         """
#         Debug method, help detect cycle and/or
#         other incoherence in a tree of Node
#         """
#         def iscycle(thing, ndict: dict, info: str) -> bool:
#             # check if not already here
#             idthing = id(thing)
#             ndict[info] = idthing
#             if idthing not in ndict:
#                 # add myself
#                 ndict[idthing] = "%s:%s no cycle" % (type(thing), info)
#                 return False
#             else:
#                 ndict[idthing] += "\n%s:%s cycle" % (type(thing), info)
#                 return True
# 
#         def recurs(thing, ndict: dict, info: str) -> bool:
#             if not iscycle(thing, ndict, info):
#                 res = False
#                 if isinstance(thing, list):
#                     idx = 0
#                     for i in thing:
#                         res |= recurs(i, ndict, "%s[%d]" % (info, idx))
#                         idx += 1
#                 elif isinstance(thing, Node):
#                     res |= thing.check(ndict, info)
#                 elif isinstance(thing, dict):
#                     for k, v in thing.items():
#                         res |= recurs(v, ndict, "%s[%s]" % (info, k))
#                 return res
#             return True
#         # add ME FIRST
#         if len(ndict) == 0:
#             ndict['self'] = id(self)
#             info = 'self'
#         if not iscycle(self, ndict, info):
#             res = False
#             if len(self) > 0:
#                 if hasattr(self, 'keys'):
#                     keys = list(self.keys())
#                     for k in keys:
#                         ndict["[" + repr(k) + "]"] = id(self[k])
#                         res |= recurs(self[k], ndict, "%s[%s]" % (info, k))
#             keys = list(vars(self).keys())
#             for k in keys:
#                 ndict["." + k] = id(getattr(self, k))
#                 res |= recurs(getattr(self, k), ndict, "%s.%s" % (info, k))
#             return res
#         return True
# 
#     def clean(self):
#         if len(self) > 0:
#             keys = list(self.keys())
#             for k in keys:
#                 del self[k]
#         keys = list(vars(self).keys())
#         for k in keys:
#             delattr(self, k)
# 
#     def set(self, othernode):
#         """allow to completly mutate the node into any subclasses of Node"""
#         self.__class__ = othernode.__class__
#         self.clean()
#         if len(othernode) > 0:
#             for k, v in othernode.items():
#                 self[k] = v
#         for k, v in vars(othernode).items():
#             setattr(self, k, v)


# Path: pyrser/parsing/base.py
import collections
import os
from pyrser import meta
from pyrser import error
from pyrser.parsing.stream import Stream
from pyrser.parsing.stream import Tag
from pyrser.parsing.node import Node

        """Save the current index under the given name."""
        # Check if we could attach tag cache to current rule_nodes scope
        self.tag_cache[name] = Tag(self._stream, self._stream.index)
        return True

    def end_tag(self, name: str) -> Node:
        """Extract the string between saved and current index."""
        self.tag_cache[name].set_end(self._stream.index)
        return True

    def get_tag(self, name: str) -> Tag:
        """Extract the string previously saved."""
        return self.tag_cache[name]

    def tag_node(self, name: str, node: Node):
        self.id_cache[id(node)] = name

####

    @classmethod
    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)