def _ParseArgs(self, args, known_only):
    """Helper function to do the main argument parsing.

    This function goes through args and does the bulk of the flag parsing.
    It will find the corresponding flag in our flag dictionary, and call its
    .parse() method on the flag value.

    Args:
      args: List of strings with the arguments to parse.
      known_only: parse and remove known flags, return rest in unparsed_args

    Returns:
      A tuple with the following:
        unknown_flags: List of (flag name, arg) for flags we don't know about.
        unparsed_args: List of arguments we did not parse.
        undefok: Set of flags that were given via --undefok.

    Raises:
       Error: on any parsing error.
       ValueError: on flag value parsing error.
    """
    unknown_flags, unparsed_args, undefok = [], [], set()

    flag_dict = self.FlagDict()
    args = iter(args)
    for arg in args:
      value = None

      def GetValue():
        # pylint: disable=cell-var-from-loop
        try:
          return next(args) if value is None else value
        except StopIteration:
          raise exceptions.Error('Missing value for flag ' + arg)

      if not arg.startswith('-'):
        # A non-argument: default is break, GNU is skip.
        unparsed_args.append(arg)
        if self.IsGnuGetOpt():
          continue
        else:
          break

      if arg == '--':
        if known_only:
          unparsed_args.append(arg)
        break

      if '=' in arg:
        name, value = arg.lstrip('-').split('=', 1)
      else:
        name, value = arg.lstrip('-'), None

      if not name:
        # The argument is all dashes (including one dash).
        unparsed_args.append(arg)
        if self.IsGnuGetOpt():
          continue
        else:
          break

      # --undefok is a special case.
      if name == 'undefok':
        if known_only:
          unparsed_args.append(arg)
        value = GetValue()
        undefok.update(v.strip() for v in value.split(','))
        undefok.update('no' + v.strip() for v in value.split(','))
        continue

      flag = flag_dict.get(name)
      if flag:
        value = (flag.boolean and value is None) or GetValue()
      elif name.startswith('no') and len(name) > 2:
        # Boolean flags can take the form of --noflag, with no value.
        noflag = flag_dict.get(name[2:])
        if noflag and noflag.boolean:
          if value is not None:
            raise ValueError(arg + ' does not take an argument')
          flag = noflag
          value = False


      if flag:
        flag.parse(value)
        flag.using_default_value = False
      elif known_only:
        unparsed_args.append(arg)
      else:
        unknown_flags.append((name, arg))

    unparsed_args.extend(args)
    return unknown_flags, unparsed_args, undefok