def _process_macro_args(self):
        """Macro args are pretty tricky! Arg names themselves are simple, but
        you can set arbitrary default values, including doing stuff like:
        {% macro my_macro(arg="x" + ("}% {# {% endmacro %}" * 2)) %}

        Which makes you a jerk, but is valid jinja.
        """
        # we are currently after the first parenthesis (+ any whitespace) after
        # the macro args started. You can either have the close paren, or a
        # name.
        while self._parenthesis_stack:
            match = self._expect_match('macro arguments',
                                       MACRO_ARGS_END_PATTERN,
                                       MACRO_ARG_PATTERN)
            self.advance(match.end())
            matchgroups = match.groupdict()
            if matchgroups.get('macro_end') is not None:
                self._parenthesis_stack.pop()
            # we got an argument. let's see what it has
            elif matchgroups.get('value') is not None:
                # we have to process a single macro argument. This mutates
                # the parenthesis stack! If it finds a comma, it will continue
                # the loop.
                self._process_macro_default_arg()
            elif matchgroups.get('more_args') is not None:
                continue
            else:
                raise dbt.exceptions.InternalException(
                    'unhandled regex in _process_macro_args(), no match: {}'
                    .format(matchgroups)
                )
Macro args are pretty tricky! Arg names themselves are simple, but
        you can set arbitrary default values, including doing stuff like:
        {% macro my_macro(arg="x" + ("}% {# {% endmacro %}" * 2)) %}

        Which makes you a jerk, but is valid jinja.