parseGroup method

GreenNode? parseGroup(
  1. String name, {
  2. required bool optional,
  3. int? greediness,
  4. String? breakOnTokenText,
  5. Mode? mode,
  6. bool consumeSpaces = false,
})

parseGroup Return a row if encounters [] or {}. Returns single function node or a single symbol otherwise.

If optional is false or absent, this parses an ordinary group, which is either a single nucleus (like "x") or an expression in braces (like "{x+y}") or an implicit group, a group that starts at the current position, and ends right before a higher explicit group ends, or at EOF. If optional is true, it parses either a bracket-delimited expression (like "x+y") or returns null to indicate the absence of a bracket-enclosed group. If mode is present, switches to that mode while parsing the group, and switches back after.

Implementation

GreenNode? parseGroup(
  String name, {
  required bool optional,
  int? greediness,
  String? breakOnTokenText,
  Mode? mode,
  bool consumeSpaces = false,
}) {
  // Save current mode and restore after completion
  final outerMode = this.mode;
  if (mode != null) {
    this.switchMode(mode);
  }
  // Consume spaces if requested, crucially *after* we switch modes,
  // so that the next non-space token is parsed in the correct mode.
  if (consumeSpaces == true) {
    this.consumeSpaces();
  }
  // Get first token
  final firstToken = this.fetch();
  final text = firstToken.text;
  GreenNode? result;
  // Try to parse an open brace or \begingroup
  if (optional ? text == '[' : text == '{' || text == '\\begingroup') {
    this.consume();
    final groupEnd = endOfGroup[text]!;
    // Start a new group namespace
    this.macroExpander.beginGroup();
    // If we get a brace, parse an expression
    final expression =
        this.parseExpression(breakOnInfix: false, breakOnTokenText: groupEnd);
    // final lastToken = this.fetch();
    // Check that we got a matching closing brace
    this.expect(groupEnd);
    this.macroExpander.endGroup();
    result = expression.wrapWithEquationRow();
  } else if (optional) {
    // Return nothing for an optional group
    result = null;
  } else {
    // If there exists a function with this name, parse the function.
    // Otherwise, just return a nucleus
    result = this.parseFunction(breakOnTokenText, name, greediness) ??
        this._parseSymbol();
    if (result == null &&
        text[0] == '\\' &&
        !implicitCommands.contains(text)) {
      if (this.settings.throwOnError) {
        throw ParseException('Undefined control sequence: $text', firstToken);
      }
      result = this._formatUnsuppotedCmd(text);
      this.consume();
    }
  }
  if (mode != null) {
    this.switchMode(outerMode);
  }
  return result;
}