import re


def get_top_level_namespaces(demangled_symbols):
  """Gets all top-level C++ namespaces from a set of demangled symbols.

  Args:
    demangled_symbols: Set of demangled_symbols to scan for namespaces.
  Returns:
    A set of all top-level namespaces found.
  """
  # Alphanumeric followed by ::, but only if not prefixed with :: or another
  # alphanumeric. Also the :: must be followed by another alphanumeric.
  #
  # This should match the top-level namespaces in the following demangled names:
  #   namespace::Class::Method()
  #   Function(namespace::Type param)
  #   TemplatedFunction<namespace::Type>::Method()
  # etc., and we use findall() to match all of them in one symbol, e.g.
  #   namespace1::Function<namespace2::Type>::Method(namespace3::Type param)
  # It will specifically not match second-level or deeper namespaces:
  #   matched_namespace::unmatched_namespace::Class::Method()
  regex_top_level_namespaces = re.compile(
      r"(?<![a-zA-Z0-9_])(?<!::)([a-zA-Z_][a-zA-Z0-9_]*)::(?=[a-zA-Z_])")
  found_namespaces = set()
  for cppsymbol in demangled_symbols:
    m = regex_top_level_namespaces.findall(cppsymbol)
    for ns in m:
      if ns not in found_namespaces:
        found_namespaces.add(ns)
  return found_namespaces