def can_parse(source, target, rules, verbose=False):
  """Return True if source and target can be derived given rules using parser.

  Args:
    source: Source string (cannot contain non-terminals).
    target: Target string (cannot contain non-terminals).
    rules: List of QCFGRule instances.
    verbose: Print debug output if True.

  Returns:
    True if source and target can be derived.
  """

  def node_fn(unused_span_begin, unused_span_end, rule, children):
    """Represent nodes as target strings."""
    return qcfg_rule.apply_target(rule, children)

  def postprocess_cell_fn(nodes):
    """Filter and merge generated nodes."""
    new_nodes = []
    for node in nodes:
      # Discard targets that are not substrings of the gold target.
      if node in target:
        new_nodes.append(node)
    return list(set(new_nodes))

  tokens = source.split(" ")
  outputs = parse(
      tokens,
      rules,
      verbose=verbose,
      node_fn=node_fn,
      postprocess_cell_fn=postprocess_cell_fn)

  if outputs and target in outputs:
    return True
  else:
    return False
Return True if source and target can be derived given rules using parser.

  Args:
    source: Source string (cannot contain non-terminals).
    target: Target string (cannot contain non-terminals).
    rules: List of QCFGRule instances.
    verbose: Print debug output if True.

  Returns:
    True if source and target can be derived.
  
language/compgen/nqg/model/qcfg/qcfg_parser.py