docs: def parse_cfgstr3(string, debug=None):
      r"""
      http://stackoverflow.com/questions/4801403/how-can-i-use-pyparsing-to-parse-nested-expressions-that-have-mutiple-opener-clo
  
      Ignore:
          >>> from utool.util_gridsearch import *  # NOQA
          cfgopt_strs = 'f=2,c=[(1,2),(3,4)],d=1,j=[[1,2],[3,4]],foobar,x="[fdsfds",y="]fdsfds",e=[[1,2],[3,4]],[]'
          string  =  cfgopt_strs
          parse_cfgstr3(string)
  
      CommandLine:
          python -m utool.util_gridsearch parse_cfgstr3 --show
  
      Example:
          >>> # ENABLE_DOCTEST
          >>> from utool.util_gridsearch import *  # NOQA
          >>> import utool as ut
          >>> cfgopt_strs = 'b=[1,2]'
          >>> cfgdict = parse_cfgstr3(cfgopt_strs)
          >>> result = ('cfgdict = %s' % (ut.repr2(cfgdict),))
          >>> print(result)
          cfgdict = {'b': [1, 2]}
  
      Example:
          >>> # ENABLE_DOCTEST
          >>> from utool.util_gridsearch import *  # NOQA
          >>> import utool as ut
          >>> cfgopt_strs = 'myprefix=False,sentence_break=False'
          >>> cfgdict = parse_cfgstr3(cfgopt_strs, debug=True)
          >>> print('cfgopt_strs = %r' % (cfgopt_strs,))
          >>> result = ('cfgdict = %s' % (ut.repr2(cfgdict),))
          >>> print(result)
          cfgdict = {'myprefix': False, 'sentence_break': False}
      """
      import utool as ut  # NOQA
      import pyparsing as pp
  
      if debug is None:
          debug_ = ut.VERBOSE
      else:
          debug_ = debug
  
      def as_tagged(parent, doctag=None, namedItemsOnly=False):
          """Returns the parse results as XML. Tags are created for tokens and lists that have defined results names."""
          namedItems = dict((v[1], k) for (k, vlist) in parent._ParseResults__tokdict.items()
                            for v in vlist)
          # collapse out indents if formatting is not desired
          parentTag = None
          if doctag is not None:
              parentTag = doctag
          else:
              if parent._ParseResults__name:
                  parentTag = parent._ParseResults__name
          if not parentTag:
              if namedItemsOnly:
                  return ""
              else:
                  parentTag = "ITEM"
          out = []
          for i, res in enumerate(parent._ParseResults__toklist):
              if isinstance(res, pp.ParseResults):
                  if i in namedItems:
                      child = as_tagged(
                          res, namedItems[i], namedItemsOnly and doctag is None)
                  else:
                      child = as_tagged(
                          res, None, namedItemsOnly and doctag is None)
                  out.append(child)
              else:
                  # individual token, see if there is a name for it
                  resTag = None
                  if i in namedItems:
                      resTag = namedItems[i]
                  if not resTag:
                      if namedItemsOnly:
                          continue
                      else:
                          resTag = "ITEM"
                  child = (resTag, pp._ustr(res))
                  out += [child]
          return (parentTag, out)
  
      def combine_nested(opener, closer, content, name=None):
          """
          opener, closer, content = '(', ')', nest_body
          """
          import utool as ut  # NOQA
          ret1 = pp.Forward()
          _NEST = ut.identity
          #_NEST = pp.Suppress
          opener_ = _NEST(opener)
          closer_ = _NEST(closer)
          # ret1 <<= pp.Group(opener_ + pp.ZeroOrMore(content) + closer_)
          ret2 = ret1 << pp.Group(opener_ + pp.ZeroOrMore(content) + closer_)
          if ret2 is None:
              ret2 = ret1
          else:
              pass
              #raise AssertionError('Weird pyparsing behavior. Comment this line if encountered. pp.__version__ = %r' % (pp.__version__,))
          if name is None:
              ret3 = ret2
          else:
              ret3 = ret2.setResultsName(name)
          assert ret3 is not None, 'cannot have a None return'
          return ret3
  
      # Current Best Grammar
      STRING = (pp.quotedString.copy()).setResultsName('quotedstring')
      NUM    = pp.Word(pp.nums).setResultsName('num')
      NAME   = pp.Regex('[a-zA-Z_][a-zA-Z_0-9]*')
      atom   = (NAME | NUM | STRING).setResultsName('atom')
      key    = pp.Word(pp.alphanums + '_').setResultsName('key')  # identifier
  
      nest_body = pp.Forward().setResultsName('nest_body')
      nestedParens   = combine_nested('(', ')', content=nest_body, name='paren')
      nestedBrackets = combine_nested('[', ']', content=nest_body, name='brak')
      nestedCurlies  = combine_nested('{', '}', content=nest_body, name='curl')
  
      nest_stmt = pp.Combine((nestedParens | nestedBrackets | nestedCurlies).setResultsName('sequence'))
  
      val = (atom | nest_stmt)
  
      # Nest body cannot have assignments in it
      #COMMA = pp.Suppress(',')
      COMMA = ','
      nest_body << val + pp.ZeroOrMore(COMMA + val)
  
      assign = pp.Group(key + pp.Suppress('=') + (val)).setResultsName('assign')
      #item = (assign | val).setResultsName('item')
      item = (assign | val)
      # OMG THIS LINE CAUSES NON-DETERMENISTIC RESULTS IN PYTHON3
      #item = (assign | val).setResultsName('item')
  
      # Assignments only allowed at outer level
      assign_body = item + pp.ZeroOrMore(pp.Suppress(',') + item)
  
      if len(string) > 0:
          tokens = assign_body.parseString(string)
          if debug_:
              print('string = %r' % (string,))
              print('tokens List: ' + ut.repr3(tokens.asList()))
              print('tokens XML: ' + tokens.asXML())
          parsed_blocks = as_tagged(tokens)[1]
          if debug_:
              print('PARSED_BLOCKS = ' + ut.repr3(parsed_blocks, nl=1))
      else:
          parsed_blocks = []
  
      from utool import util_type  # NOQA
      #from collections import OrderedDict
      #cfgdict = OrderedDict()
      cfgdict = {}
      for item in parsed_blocks:
          if item[0] == 'assign':
              keyval_pair = item[1]
              keytup, valtup = keyval_pair
              key = keytup[1]
              val = util_type.smart_cast2(valtup[1])
              #val = valtup[1]
          elif item[0] == 'atom':
              key = item[1]
              val = True
          else:
              key = None
              val = None
          if key is not None:
              cfgdict[key] = val
      if debug_:
          print('[TOKENS] CFGDICT ' + ut.repr3(cfgdict, nl=1))
          #x = list(map(type, cfgdict.keys()))
          #print(x)
          #print(list(cfgdict.keys()))
          #if len(x) > 0 and str(x[0]).find('Word') > -1:
          #    import utool
          #    utool.embed()
      return cfgdict