code: def _process_macro_args(self):
          
          # 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)
                  )
docs: 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.