expressionBuilderParser method

Parser<ExpressionNode> expressionBuilderParser()
inherited

Expression builder setup.

Implementation

Parser<ExpressionNode> expressionBuilderParser() {
  final builder = ExpressionBuilder<ExpressionNode>();

  // Primitives
  builder.primitive(ref0(primary));

  // Group 1: Postfix selectors & operators
  builder.group()
    ..postfix(
      ref1(token, '++'),
      (val, _) =>
          UnaryExpressionNode(operator: '++', operand: val, isPrefix: false),
    )
    ..postfix(
      ref1(token, '--'),
      (val, _) =>
          UnaryExpressionNode(operator: '--', operand: val, isPrefix: false),
    )
    ..postfix(
      ref1(token, '!'),
      (val, _) =>
          UnaryExpressionNode(operator: '!', operand: val, isPrefix: false),
    )
    // Property access: .prop or ?.prop (including constructor tear-off .new)
    ..postfix(
      seq2(
        [ref1(token, '?.'), ref1(token, '.')].toChoiceParser(),
        [
          ref0(identifier),
          ref0(newToken).map((t) => t.value),
        ].toChoiceParser(),
      ),
      (target, access) => PropertyAccessNode(
        target: target,
        propertyName: access.$2,
        isNullAware: access.$1.value == '?.',
      ),
    )
    // Method / function invocation: (args) or <typeArgs>(args)
    ..postfix(
      seq2(
        ref0(typeArguments)
            .optional()
            .map((list) => list ?? const <TypeNode>[]),
        ref0(argumentList),
      ),
      (target, inv) => InvocationExpressionNode(
        target: target,
        typeArguments: inv.$1,
        arguments: inv.$2,
      ),
    )
    // Indexing: [index] or ?[index]
    ..postfix(
      seq3(
        [ref1(token, '?['), ref1(token, '[')].toChoiceParser(),
        builder.loopback,
        ref1(token, ']'),
      ),
      (target, index) => IndexExpressionNode(
        target: target,
        index: index.$2,
        isNullAware: index.$1.value == '?[',
      ),
    );

  // Group 2: Prefix operators
  builder.group()
    ..prefix(
      ref1(token, '-'),
      (op, val) => UnaryExpressionNode(operator: '-', operand: val),
    )
    ..prefix(
      ref1(token, '!'),
      (op, val) => UnaryExpressionNode(operator: '!', operand: val),
    )
    ..prefix(
      ref1(token, '~'),
      (op, val) => UnaryExpressionNode(operator: '~', operand: val),
    )
    ..prefix(
      ref1(token, '++'),
      (op, val) => UnaryExpressionNode(operator: '++', operand: val),
    )
    ..prefix(
      ref1(token, '--'),
      (op, val) => UnaryExpressionNode(operator: '--', operand: val),
    )
    ..prefix(ref0(awaitToken), (op, val) => AwaitExpressionNode(val))
    ..prefix(ref0(throwToken), (op, val) => ThrowExpressionNode(val));

  // Group 3: Multiplicative (*, /, ~/, %)
  builder.group()
    ..left(
      ref1(token, '*'),
      (left, op, right) =>
          BinaryExpressionNode(left: left, operator: '*', right: right),
    )
    ..left(
      ref1(token, '/'),
      (left, op, right) =>
          BinaryExpressionNode(left: left, operator: '/', right: right),
    )
    ..left(
      ref1(token, '~/'),
      (left, op, right) =>
          BinaryExpressionNode(left: left, operator: '~/', right: right),
    )
    ..left(
      ref1(token, '%'),
      (left, op, right) =>
          BinaryExpressionNode(left: left, operator: '%', right: right),
    );

  // Group 4: Additive (+, -)
  builder.group()
    ..left(
      ref1(token, '+'),
      (left, op, right) =>
          BinaryExpressionNode(left: left, operator: '+', right: right),
    )
    ..left(
      ref1(token, '-'),
      (left, op, right) =>
          BinaryExpressionNode(left: left, operator: '-', right: right),
    );

  // Group 5: Shift (<<, >>>, >>)
  builder.group()
    ..left(
      ref1(token, '<<'),
      (left, op, right) =>
          BinaryExpressionNode(left: left, operator: '<<', right: right),
    )
    ..left(
      ref1(token, '>>>'),
      (left, op, right) =>
          BinaryExpressionNode(left: left, operator: '>>>', right: right),
    )
    ..left(
      ref1(token, '>>'),
      (left, op, right) =>
          BinaryExpressionNode(left: left, operator: '>>', right: right),
    );

  // Group 6: Relational (<, <=, >, >=, is, is!, as)
  builder.group()
    ..left(
      ref1(token, '<='),
      (left, op, right) =>
          BinaryExpressionNode(left: left, operator: '<=', right: right),
    )
    ..left(
      ref1(token, '>='),
      (left, op, right) =>
          BinaryExpressionNode(left: left, operator: '>=', right: right),
    )
    ..left(
      ref1(token, '<'),
      (left, op, right) =>
          BinaryExpressionNode(left: left, operator: '<', right: right),
    )
    ..left(
      ref1(token, '>'),
      (left, op, right) =>
          BinaryExpressionNode(left: left, operator: '>', right: right),
    )
    ..postfix(
      seq2(
        [ref0(isToken) & ref1(token, '!'), ref0(isToken)].toChoiceParser(),
        ref0(typeTestType),
      ),
      (expr, isTest) {
        final isNegated = isTest.$1 is List;
        return TypeTestExpressionNode(
          expression: expr,
          type: isTest.$2,
          isNegated: isNegated,
        );
      },
    )
    ..postfix(
      seq2(ref0(asToken), ref0(typeTestType)),
      (expr, asCast) =>
          TypeCastExpressionNode(expression: expr, type: asCast.$2),
    );

  // Group 7: Equality (==, !=)
  builder.group()
    ..left(
      ref1(token, '=='),
      (left, op, right) =>
          BinaryExpressionNode(left: left, operator: '==', right: right),
    )
    ..left(
      ref1(token, '!='),
      (left, op, right) =>
          BinaryExpressionNode(left: left, operator: '!=', right: right),
    );

  // Group 8: Bitwise AND (&)
  builder.group().left(
    ref1(token, '&'),
    (left, op, right) =>
        BinaryExpressionNode(left: left, operator: '&', right: right),
  );

  // Group 9: Bitwise XOR (^)
  builder.group().left(
    ref1(token, '^'),
    (left, op, right) =>
        BinaryExpressionNode(left: left, operator: '^', right: right),
  );

  // Group 10: Bitwise OR (|)
  builder.group().left(
    ref1(token, '|'),
    (left, op, right) =>
        BinaryExpressionNode(left: left, operator: '|', right: right),
  );

  // Group 11: Logical AND (&&)
  builder.group().left(
    ref1(token, '&&'),
    (left, op, right) =>
        BinaryExpressionNode(left: left, operator: '&&', right: right),
  );

  // Group 12: Logical OR (||)
  builder.group().left(
    ref1(token, '||'),
    (left, op, right) =>
        BinaryExpressionNode(left: left, operator: '||', right: right),
  );

  // Group 13: If-null (??)
  builder.group().right(
    ref1(token, '??'),
    (left, op, right) => IfNullExpressionNode(left: left, right: right),
  );

  // Group 14: Ternary conditional (c ? t : e)
  builder.group().postfix(
    seq4(
      ref1(token, '?'),
      builder.loopback,
      ref1(token, ':'),
      builder.loopback,
    ),
    (cond, ternary) => ConditionalExpressionNode(
      condition: cond,
      thenExpression: ternary.$2,
      elseExpression: ternary.$4,
    ),
  );

  // Group 15: Cascade (.. or ?..)
  builder.group().postfix(
    seq2(
      [ref1(token, '?..'), ref1(token, '..')].toChoiceParser(),
      ref0(cascadeSection).plus(),
    ),
    (target, cascade) => CascadeExpressionNode(
      target: target,
      cascadeSections: cascade.$2,
      isNullAware: cascade.$1.value == '?..',
    ),
  );

  // Group 16: Assignment & Compound Assignment (=, +=, -=, *=, /=, ~/=, %=, <<=, >>=, >>>=, &=, ^=, |=, ??=)
  builder.group().right(
    [
      ref1(token, '='),
      ref1(token, '+='),
      ref1(token, '-='),
      ref1(token, '*='),
      ref1(token, '/='),
      ref1(token, '~/='),
      ref1(token, '%='),
      ref1(token, '<<='),
      ref1(token, '>>>='),
      ref1(token, '>>='),
      ref1(token, '&='),
      ref1(token, '^='),
      ref1(token, '|='),
      ref1(token, '??='),
    ].toChoiceParser().map((t) => t.value),
    (left, op, right) =>
        BinaryExpressionNode(left: left, operator: op, right: right),
  );

  return builder.build();
}