def register(cls, symbol, **kwargs):
        """
        Register/update a token class in the symbol table.

        :param symbol: The identifier symbol for a new class or an existent token class.
        :param kwargs: Optional attributes/methods for the token class.
        :return: A token class.
        """
        try:
            try:
                if ' ' in symbol:
                    raise ValueError("%r: a symbol can't contain whitespaces" % symbol)
            except TypeError:
                assert isinstance(symbol, type) and issubclass(symbol, Token), \
                    "A %r subclass requested, not %r." % (Token, symbol)
                symbol, token_class = symbol.symbol, symbol
                assert symbol in cls.symbol_table and cls.symbol_table[symbol] is token_class, \
                    "Token class %r is not registered." % token_class
            else:
                token_class = cls.symbol_table[symbol]

        except KeyError:
            # Register a new symbol and create a new custom class. The new class
            # name is registered at parser class's module level.
            if symbol not in cls.SYMBOLS:
                raise NameError('%r is not a symbol of the parser %r.' % (symbol, cls))

            kwargs['symbol'] = symbol
            label = kwargs.get('label', 'symbol')
            if isinstance(label, tuple):
                label = kwargs['label'] = MultiLabel(*label)

            token_class_name = "_{}{}".format(
                symbol_to_classname(symbol), str(label).title().replace(' ', '')
            )
            token_class_bases = kwargs.get('bases', (cls.token_base_class,))
            kwargs.update({
                '__module__': cls.__module__,
                '__qualname__': token_class_name,
                '__return__': None
            })
            token_class = ABCMeta(token_class_name, token_class_bases, kwargs)
            cls.symbol_table[symbol] = token_class
            MutableSequence.register(token_class)
            setattr(sys.modules[cls.__module__], token_class_name, token_class)

        else:
            for key, value in kwargs.items():
                if key == 'lbp' and value > token_class.lbp:
                    token_class.lbp = value
                elif key == 'rbp' and value > token_class.rbp:
                    token_class.rbp = value
                elif callable(value):
                    setattr(token_class, key, value)

        return token_class
    def schema_constructor(self, atomic_type_name: str, bp: int = 90) \
            -> Type[XPathFunction]:
        """Registers a token class for a schema atomic type constructor function."""
        if atomic_type_name in (XSD_ANY_ATOMIC_TYPE, XSD_NOTATION):
            raise xpath_error('XPST0080')

        def nud_(self_: XPathFunction) -> XPathFunction:
            self_.parser.advance('(')
            self_[0:] = self_.parser.expression(5),
            self_.parser.advance(')')

            try:
                self_.value = self_.evaluate()  # Static context evaluation
            except MissingContextError:
                self_.value = None
            return self_

        def evaluate_(self_: XPathFunction, context: Optional[XPathContext] = None) \
                -> Union[List[None], AtomicValueType]:
            arg = self_.get_argument(context)
            if arg is None or self_.parser.schema is None:
                return []

            value = self_.string_value(arg)
            try:
                return self_.parser.schema.cast_as(value, atomic_type_name)
            except (TypeError, ValueError) as err:
                raise self_.error('FORG0001', err)

        symbol = get_prefixed_name(atomic_type_name, self.namespaces)
        token_class_name = "_%sConstructorFunction" % symbol.replace(':', '_')
        kwargs = {
            'symbol': symbol,
            'nargs': 1,
            'label': 'constructor function',
            'pattern': r'\b%s(?=\s*\(|\s*\(\:.*\:\)\()' % symbol,
            'lbp': bp,
            'rbp': bp,
            'nud': nud_,
            'evaluate': evaluate_,
            '__module__': self.__module__,
            '__qualname__': token_class_name,
            '__return__': None
        }
        token_class = cast(
            Type[XPathFunction],
            ABCMeta(token_class_name, (XPathFunction, ), kwargs))
        MutableSequence.register(token_class)
        self.symbol_table[symbol] = token_class
        return token_class
Beispiel #3
0
    def schema_constructor(self, atomic_type, bp=90):
        """Registers a token class for a schema atomic type constructor function."""
        if atomic_type in {XSD_ANY_ATOMIC_TYPE, XSD_NOTATION}:
            raise xpath_error('XPST0080')

        def nud_(self_):
            self_.parser.advance('(')
            self_[0:] = self_.parser.expression(5),
            self_.parser.advance(')')

            try:
                self_.value = self_.evaluate()  # Static context evaluation
            except MissingContextError:
                self_.value = None
            return self_

        def evaluate_(self_, context=None):
            arg = self_.get_argument(context)
            if arg is None:
                return []

            value = self_.string_value(arg)
            try:
                return self_.parser.schema.cast_as(value, atomic_type)
            except (TypeError, ValueError) as err:
                raise self_.error('FORG0001', err)

        symbol = get_prefixed_name(atomic_type, self.namespaces)
        token_class_name = str("_%s_constructor_token" %
                               symbol.replace(':', '_'))
        kwargs = {
            'symbol': symbol,
            'label': 'constructor function',
            'pattern': r'\b%s(?=\s*\(|\s*\(\:.*\:\)\()' % symbol,
            'lbp': bp,
            'rbp': bp,
            'nud': nud_,
            'evaluate': evaluate_,
            '__module__': self.__module__,
            '__qualname__': token_class_name,
            '__return__': None
        }
        token_class = ABCMeta(token_class_name, (self.token_base_class, ),
                              kwargs)
        MutableSequence.register(token_class)
        self.symbol_table[symbol] = token_class
        return token_class
Beispiel #4
0
 def __jclass_init__(self):
     Sequence.register(self)
     MutableSequence.register(self)
Beispiel #5
0
        """
        Helper classmethod to construct a ``ParseResults`` from a ``dict``, preserving the
        name-value relations as results names. If an optional ``name`` argument is
        given, a nested ``ParseResults`` will be returned.
        """
        def is_iterable(obj):
            try:
                iter(obj)
            except Exception:
                return False
            else:
                return not isinstance(obj, str_type)

        ret = cls([])
        for k, v in other.items():
            if isinstance(v, Mapping):
                ret += cls.from_dict(v, name=k)
            else:
                ret += cls([v], name=k, asList=is_iterable(v))
        if name is not None:
            ret = cls([ret], name=name)
        return ret

    asList = as_list
    asDict = as_dict
    getName = get_name


MutableMapping.register(ParseResults)
MutableSequence.register(ParseResults)
Beispiel #6
0
    def extend(self, values):
        end = len(self._items)
        self[end:end] = values

    pop = MutableSequence.pop
    remove = MutableSequence.remove
    __iadd__ = MutableSequence.__iadd__

    # convenience

    def clear(self):
        del self[:]


MutableSequence.register(List)


class Selection(List):

    """Set of items with the additional notion of a cursor to the least
    recently *active* element. Each item can occur only once in the set.

    Note that the inherited ``List`` methods and signals can be used to listen
    for selection changes, and to query or delete items. However, for
    *inserting* or *modifying* elements, only use the methods defined in the
    ``Selection`` class can be used to ensure that items stay unique.
    """

    def __init__(self):
        super().__init__()
Beispiel #7
0
    def register(cls, symbol, **kwargs):
        """
        Register/update a token class in the symbol table.

        :param symbol: The identifier symbol for a new class or an existent token class.
        :param kwargs: Optional attributes/methods for the token class.
        :return: A token class.
        """
        def symbol_escape(s):
            s = re.escape(s)
            s.replace(r'\ ', r'\s+')

            if s.isalpha():
                s = r'\b%s\b(?![\-\.])' % s
            elif s[-2:] == r'\(':
                s = r'%s\s*%s' % (s[:-2], s[-2:])
            elif s[-4:] == r'\:\:':
                s = r'%s\s*%s' % (s[:-4], s[-4:])
            return s

        try:
            try:
                if ' ' in symbol:
                    raise ValueError(
                        "%r: a symbol can't contains whitespaces." % symbol)
            except TypeError:
                assert isinstance(symbol, type) and issubclass(symbol, Token), \
                    "A %r subclass requested, not %r." % (Token, symbol)
                symbol, token_class = symbol.symbol, symbol
                assert symbol in cls.symbol_table and cls.symbol_table[symbol] is token_class, \
                    "Token class %r is not registered." % token_class
            else:
                token_class = cls.symbol_table[symbol]

        except KeyError:
            # Register a new symbol and create a new custom class. The new class
            # name is registered at parser class's module level.
            if symbol not in cls.SYMBOLS:
                raise NameError('%r is not a symbol of the parser %r.' %
                                (symbol, cls))

            kwargs['symbol'] = symbol
            if 'pattern' not in kwargs:
                pattern = symbol_escape(
                    symbol) if len(symbol) > 1 else re.escape(symbol)
                kwargs['pattern'] = pattern

            label = kwargs.get('label', 'symbol')
            if isinstance(label, tuple):
                label = kwargs['label'] = MultiLabel(*label)

            token_class_name = "_{}_{}_token".format(
                symbol_to_identifier(symbol),
                str(label).replace(' ', '_'))
            token_class_bases = (getattr(cls, 'token_base_class', object), )
            kwargs.update({
                '__module__': cls.__module__,
                '__qualname__': token_class_name,
                '__return__': None
            })
            token_class = ABCMeta(token_class_name, token_class_bases, kwargs)
            cls.symbol_table[symbol] = token_class
            MutableSequence.register(token_class)
            setattr(sys.modules[cls.__module__], token_class_name, token_class)

        else:
            for key, value in kwargs.items():
                if key == 'lbp' and value > token_class.lbp:
                    token_class.lbp = value
                elif key == 'rbp' and value > token_class.rbp:
                    token_class.rbp = value
                elif callable(value):
                    setattr(token_class, key, value)

        return token_class
Beispiel #8
0
    @staticmethod
    def _c_one_lsb(index: int, stop: int = 0) -> _Gen:
        """ Consuming set bits starting from LSB."""
        while index > stop:
            yield index
            index &= index - 1

    @staticmethod
    def _c_zero_lsb(index: int, start: int = 2) -> _Gen:
        """ Yields powers of two that perfectly divide index.
        Consuming unset bits starting from LSB.
        """
        while index & 1 == 0:
            yield start // 2
            start <<= 1
            index >>= 1

    @staticmethod
    def _nmlz_index(index: int, length: int) -> int:
        """ Normalize index, bringing it in [0, len(self)),
        IndexError is raised if index is out of bounds.
        """
        index = index + length if index < 0 else index
        if index >= length or length == 0:
            raise IndexError("Index out of range.")
        return index


# Register as virtual subclass.
MutableSequence.register(BIT)
Beispiel #9
0
        return getattr(self, '_{}'.format(idx))

    def __repr__(self):
        with stringify_context(self) as nested:
            cls = type(self).__qualname__
            if nested:
                return "@{}".format(get_short_id(self))
            else:
                return "{}@{}({})".format(
                    cls,
                    get_short_id(self),
                    repr(list(self)),
                )


MutableSequence.register(ManagedList)

# ------------- TEST -------------------


class Test(Managed):
    def init(self):
        self.a = 1
        self.a = 2
        self.node = self._resmngr.new(Node, 123)
        self.more = self._resmngr.new_list([
            self._resmngr.new(Node, 100),
            self._resmngr.new(Node, 200),
        ])

Beispiel #10
0
    def extend(self, values):
        end = len(self._items)
        self[end:end] = values

    pop = MutableSequence.pop
    remove = MutableSequence.remove
    __iadd__ = MutableSequence.__iadd__

    # convenience

    def clear(self):
        del self[:]


MutableSequence.register(List)


class Selection(List):

    """Set of items with the additional notion of a cursor to the least
    recently *active* element. Each item can occur only once in the set.

    Note that the inherited ``List`` methods and signals can be used to listen
    for selection changes, and to query or delete items. However, for
    *inserting* or *modifying* elements, only use the methods defined in the
    ``Selection`` class can be used to ensure that items stay unique.
    """

    def __init__(self):
        super().__init__()