@classmethod
def _builddefn(cls, defn, args):
    """Parse an alias definition into a tree and marks substitutions

        This function marks alias argument references as ``_aliasarg``. The
        parsing rule is provided by ``_parse()``.

        ``args`` is a list of alias argument names, or None if the alias
        is declared as a symbol.

        >>> from . import pycompat
        >>> parsemap = {
        ...     b'$1 or foo': (b'or', (b'symbol', b'$1'), (b'symbol', b'foo')),
        ...     b'$1 or $bar':
        ...         (b'or', (b'symbol', b'$1'), (b'symbol', b'$bar')),
        ...     b'$10 or baz':
        ...         (b'or', (b'symbol', b'$10'), (b'symbol', b'baz')),
        ...     b'"$1" or "foo"':
        ...         (b'or', (b'string', b'$1'), (b'string', b'foo')),
        ... }
        >>> class aliasrules(basealiasrules):
        ...     _parse = staticmethod(parsemap.__getitem__)
        ...     _trygetfunc = staticmethod(lambda x: None)
        >>> builddefn = aliasrules._builddefn
        >>> def pprint(tree):
        ...     s = prettyformat(tree, (b'_aliasarg', b'string', b'symbol'))
        ...     print(pycompat.sysstr(s))
        >>> args = [b'$1', b'$2', b'foo']
        >>> pprint(builddefn(b'$1 or foo', args))
        (or
          (_aliasarg '$1')
          (_aliasarg 'foo'))
        >>> try:
        ...     builddefn(b'$1 or $bar', args)
        ... except error.ParseError as inst:
        ...     print(pycompat.sysstr(parseerrordetail(inst)))
        invalid symbol '$bar'
        >>> args = [b'$1', b'$10', b'foo']
        >>> pprint(builddefn(b'$10 or baz', args))
        (or
          (_aliasarg '$10')
          (symbol 'baz'))
        >>> pprint(builddefn(b'"$1" or "foo"', args))
        (or
          (string '$1')
          (string 'foo'))
        """
    tree = cls._parse(defn)
    if args:
        args = set(args)
    else:
        args = set()
    return cls._relabelargs(tree, args)
