pyebnf/primitive.py
def _get_concatenation(extractors, text, *, ignore_whitespace=True):
  """Returns a concatenation ParseNode whose children are the nodes returned by each of the
  methods in the extractors enumerable.

  If ignore_whitespace is True, whitespace will be ignored and then attached to the child it
  preceeded.
  """
  ignored_ws, use_text = _split_ignored(text, ignore_whitespace)

  extractor, *remaining = extractors

  child = _call_extractor(extractor, use_text)
  child.add_ignored(ignored_ws)

  # TODO: Should I set node.position = -len(text) for the case that ignored whitespace will cause
  #       the first child's position to not be the whitespace, and therefore the concatenation's
  #       position will be the first non-whitespace? I think not, but I'm adding this note in
  #       case that causes an issue I'm not seeing at the moment.
  node = ParseNode(ParseNodeType.concatenation, children=[child])

  if remaining:
    # child.consumed will include ignored whitespace, so we base the text we pass on on text rather
    # than use_text.
    return node.merged(_get_concatenation(remaining,
                                          text[child.consumed:],
                                          ignore_whitespace=ignore_whitespace))
  else:
    return node
def _get_concatenation(extractors, text, *, ignore_whitespace=True):
  """Returns a concatenation ParseNode whose children are the nodes returned by each of the
  methods in the extractors enumerable.

  If ignore_whitespace is True, whitespace will be ignored and then attached to the child it
  preceeded.
  """
  ignored_ws, use_text = _split_ignored(text, ignore_whitespace)

  extractor, *remaining = extractors

  child = _call_extractor(extractor, use_text)
  child.add_ignored(ignored_ws)

  # TODO: Should I set node.position = -len(text) for the case that ignored whitespace will cause
  #       the first child's position to not be the whitespace, and therefore the concatenation's
  #       position will be the first non-whitespace? I think not, but I'm adding this note in
  #       case that causes an issue I'm not seeing at the moment.
  node = ParseNode(ParseNodeType.concatenation, children=[child])

  if remaining:
    # child.consumed will include ignored whitespace, so we base the text we pass on on text rather
    # than use_text.
    return node.merged(_get_concatenation(remaining,
                                          text[child.consumed:],
                                          ignore_whitespace=ignore_whitespace))
  else:
    return node
Returns a concatenation ParseNode whose children are the nodes returned by each of the
  methods in the extractors enumerable.

  If ignore_whitespace is True, whitespace will be ignored and then attached to the child it
  preceeded.