def restore_funql(funql):
  """Recursively parse FunQL string back to original string."""
  # Special constant used for "sea level".
  if funql == "0":
    return "0"

  if funql in UNARY_CONSTANTS:
    return "%s(all)" % funql

  name, arguments = _get_name_and_arguments(funql)
  if name == "answer" or name in RELATION_CONSTANTS or name in ARITY_1:
    if len(arguments) != 1:
      raise ValueError
    argument_0 = arguments[0]
    return "%s(%s)" % (name, restore_funql(argument_0))
  elif name in RELATION_CONSTANTS:
    if len(arguments) != 1:
      raise ValueError
    argument_0 = arguments[0]
    restored_argument_0 = restore_funql(argument_0)
    if not restored_argument_0:
      raise ValueError("Failed to restore: %s" % argument_0)
    return "%s(%s)" % (name, restored_argument_0)
  elif name in ENTITY_FUNCTIONS:
    return funql
  elif name == "intersection":
    if len(arguments) != 2:
      raise ValueError
    argument_0 = arguments[0]
    argument_1 = arguments[1]
    term_a = restore_funql(argument_0)
    term_b = restore_funql(argument_1)
    if argument_0 in UNARY_CONSTANTS:
      return "%s(%s)" % (argument_0, restore_funql(argument_1))
    if argument_1 in UNARY_CONSTANTS:
      raise ValueError
    return "%s(%s,%s)" % (name, term_a, term_b)
  elif name == "exclude":
    if len(arguments) != 2:
      raise ValueError
    argument_0 = arguments[0]
    argument_1 = arguments[1]
    term_a = restore_funql(argument_0)
    term_b = restore_funql(argument_1)
    return "%s(%s,%s)" % (name, term_a, term_b)
  elif name in ARITY_2:
    if len(arguments) != 2:
      raise ValueError("Unexpected number of arguments `%s` for `%s`" %
                       (arguments, name))
    argument_0 = arguments[0]
    argument_1 = arguments[1]
    return "%s(%s(%s))" % (name, argument_0, restore_funql(argument_1))
  elif name in ARITY_3:
    if len(arguments) != 3:
      raise ValueError
    argument_0 = arguments[0]
    argument_1 = arguments[1]
    argument_2 = arguments[2]
    return "%s(%s(%s(%s)))" % (name, argument_0, argument_1,
                               restore_funql(argument_2))
  else:
    raise ValueError("No match for name: %s" % name)
Recursively parse FunQL string back to original string.
language/compgen/nqg/tasks/geoquery/funql_normalization.py