mergeRoot static method

Handle case where at least one of a or b is {@link #EMPTY}. In the following diagrams, the symbol {@code $} is used to represent {@link #EMPTY}.

Local-Context Merges

These local-context merge operations are used when [rootIsWildcard] is true.

{@link #EMPTY} is superset of any graph; return {@link #EMPTY}.

{@link #EMPTY} and anything is {@code #EMPTY}, so merged parent is {@code #EMPTY}; return left graph.

Special case of last merge if local context.

Full-Context Merges

These full-context merge operations are used when [rootIsWildcard] is false.

Must keep all contexts; {@link #EMPTY} in array is a special value (and null parent).

@param a the first SingletonPredictionContext @param b the second SingletonPredictionContext @param rootIsWildcard true if this is a local-context merge, otherwise false to indicate a full-context merge

Implementation

static PredictionContext? mergeRoot(
  SingletonPredictionContext a,
  SingletonPredictionContext b,
  bool rootIsWildcard,
) {
  if (rootIsWildcard) {
    if (a == EmptyPredictionContext.Instance) return EmptyPredictionContext.Instance; // * + b = *
    if (b == EmptyPredictionContext.Instance) return EmptyPredictionContext.Instance; // a + * = *
  } else {
    if (a == EmptyPredictionContext.Instance && b == EmptyPredictionContext.Instance) return EmptyPredictionContext.Instance; // $ + $ = $
    if (a == EmptyPredictionContext.Instance) {
      // $ + x = [x,$]
      final payloads = <int>[b.returnState, EMPTY_RETURN_STATE];
      final parents = <PredictionContext?>[b.parent, null];
      PredictionContext joined = ArrayPredictionContext(parents, payloads);
      return joined;
    }
    if (b == EmptyPredictionContext.Instance) {
      // x + $ = [x,$] ($ is always last if present)
      final payloads = <int>[a.returnState, EMPTY_RETURN_STATE];
      final parents = [a.parent, null];
      PredictionContext joined = ArrayPredictionContext(parents, payloads);
      return joined;
    }
  }
  return null;
}