from typing import Any, Callable, List, Tuple, TypeAlias



Source: TypeAlias = Tuple[str, int]

class Node:  # pylint: disable=too-few-public-methods
    """Node objects are used to build parse trees."""

    def __init__(self, name: str, *children: "Node") -> None:
        super().__init__()
        self.name = name
        self.children = list(children)

    @property
    def value(self) -> str:
        """Returns the node value as generated by a parser."""

        return "".join(child.value for child in self.children)

    def __str__(self) -> str:
        return "Node(name=%s, children=[%s])" % (
            self.name,
            ", ".join(x.__str__() for x in self.children),
        )

    def __eq__(self, other: Any):
        return self.__class__ == other.__class__ and self.__dict__ == other.__dict__


ParseMatch = Tuple[list[Node], Source]
Parser: TypeAlias = Callable[[Source], List[ParseMatch]]


def bind(p1: Parser, p2: Parser) -> Parser:
    def f(src: Source) -> List[ParseMatch]:
        result = p1(src)
        if result[1]:
            return p2(result[0]) + result[1]

    return f