def METHOD_NAME(w):
  """
  Args:
    CompoundWord
  Returns:
    CompoundWord or None?
  Another option:
  Grammar:
    # an alternative is a literal, possibly empty, or another brace_expr
    part = <any part except LiteralPart>
    alt = part* | brace_expr
    # a brace_expr is group of at least 2 braced and comma-separated
    # alternatives, with optional prefix and suffix.
    brace_expr = part* '{' alt ',' alt (',' alt)* '}' part*
  Problem this grammar: it's not LL(1) 
  Is it indirect left-recursive?
  What's the best way to handle it?  LR(1) parser?
  Iterative algorithm:
  Parse it with a stack?
    It's a stack that asserts there is at least one , in between {}
  Yeah just go through and when you see {, push another list.
  When you get ,  append to list
  When you get } and at least one ',', append o list
  When you get } without, then pop
  If there is no matching }, then abort with error
  if not balanced, return error too?
  """
  # Errors:
  # }a{    - stack depth dips below 0
  # {a,b}{ - Stack depth doesn't end at 0
  # {a}    - no comma, and also not an numeric range
  cur_parts = []
  stack = []
  found = False
  for i, part in enumerate(w.parts):
    append = True
    if part.tag == word_part_e.LiteralPart:
      id_ = part.token.id
      if id_ == Id.Lit_LBrace:
        # Save prefix parts.  Start new parts list.
        new_frame = _StackFrame(cur_parts)
        stack.append(new_frame)
        cur_parts = []
        append = False
        found = True  # assume found, but can early exit with None later
      elif id_ == Id.Lit_Comma:
        # Append a new alternative.
        #print('*** Appending after COMMA', cur_parts)
        # NOTE: Should we allow this:
        # ,{a,b}
        # or force this:
        # \,{a,b}
        # ?  We're forcing braces right now but not commas.
        if stack:
          stack[-1].saw_comma = True
          stack[-1].alt_part.words.append(ast.CompoundWord(cur_parts))
          cur_parts = []  # clear
          append = False
      elif id_ == Id.Lit_RBrace:
        # TODO:
        # - Detect lack of , -- abort the whole thing
        # - Detect {1..10} and {1..10..2}
        #   - bash and zsh only -- this is NOT implemented by mksh
        #   - Use a regex on the middle part:
        #     - digit+ '..' digit+  ( '..' digit+ )?
        # - Char ranges are bash only!
        #
        # ast.BracedIntRangePart()
        # ast.CharRangePart()
        if not stack:  # e.g. echo }  -- unbalancd {
          return None
        if not stack[-1].saw_comma:  # {foo} is not a real alternative
          return None
        stack[-1].alt_part.words.append(ast.CompoundWord(cur_parts))
        frame = stack.pop()
        cur_parts = frame.cur_parts
        cur_parts.append(frame.alt_part)
        append = False
    if append:
      cur_parts.append(part)
  if len(stack) != 0:
    return None
  if found:
    return ast.BracedWordTree(cur_parts)
  else:
    return None