import re


def build_regex(label, easyreg):
    """Convert a string with simplified syntax into lookahead regex.

    This allows one to search for the `easyreg` anywhere in the string and
    return a dict with matches.  brackets `{}` in the easy reg pattern
    are placeholders for digits (e.g. {d2}) or non digits ({D4}) and the
    number in the brackets determines how many characters/digits to match.
    '_stack{d4}' will convert to '(?=.*_stack(?P<t>\\d{4}))?'

    Args:
        label (str): label that will be associated when matching pattern
        easyreg (str): simplified regex pattern to search for

    Returns:
        regex (str): string that can be used to compile a regex

    Examples:
        This is intended to be used with a list of (label, easyreg) tuples,
        and a parser can be compiled as follows:
        >>> patterns = [('t','_stack{d4}'), ('c','_ch{d1}'), ('w','_{d3}nm')]
        >>> parser = re.compile("".join([build_regex(*p) for p in patterns]))
        >>> parser.match('cell2_CamA_ch3_stack0023_488nm.tif').groupdict()
        {'t': '0023', 'c': '3', 'w': '488'}

    """

    def wrap(label):
        def func(matchobj):
            t = matchobj.group("typ")
            t = ("\\" + t) if t is not None else "[a-zA-Z0-9]"
            n = matchobj.group("num")
            n = "{" + n + "}" if n is not None else "+"
            return r"(?P<" + label + ">" + t + n + ")"

        return func

    ss = re.sub(r"{(?P<typ>[dD])?(?P<num>\d+)?}", wrap(label), easyreg)
    assert ss != easyreg, "failed to parse pattern!: {}".format(easyreg)
    return "(?=.*{})?".format(ss)