memoryExpr method

MathExpr memoryExpr()

Implementation

MathExpr memoryExpr() {
  MathExpr lhs = literal();
  Token op = peek();

  const memOps = [
    TokenType.kDot,
    TokenType.kColon,
    TokenType.kLBracket,
    TokenType.kLParen,
  ];

  while (memOps.contains(op.type)) {
    lhs = switch (op.type) {
      TokenType.kDot => MemoryAccess.field(op, lhs, advanceAndThen(rawExpr)),
      TokenType.kLBracket => () {
        final arg = advanceAndThen(math);
        consume(TokenType.kRBracket, 'Expecting closing bracket.');
        return MemoryAccess.table(op, lhs, arg);
      }(),
      TokenType.kColon => () {
        advance();
        // Special case: the colon operator forwards the lhs object
        // into a function arg list as the new first argument.
        // Therefore, we need to be sugar that a function expression
        // follows and becomes our rhsExpr node.
        //
        // functioncall ::= prefixexp ':' Name args
        final MathExpr funcName = literal();
        final parenToken = consume(
          TokenType.kLParen,
          'Expected function call after colon ":" operator.',
        );
        final args = argList(terminal: TokenType.kRParen);
        consume(TokenType.kRParen, 'Expecting closing parentheses.');
        final rhsExpr = MemoryAccess.call(parenToken, funcName, args);

        // With the function node packed together, map this to lhs.
        final callee = lhs;
        final colon = op;
        return MemoryAccess.call(colon, callee, [rhsExpr]);
      }(),
      TokenType.kLParen => () {
        advance();
        final args = argList(terminal: TokenType.kRParen);
        consume(TokenType.kRParen, 'Expecting closing parentheses.');
        return MemoryAccess.call(op, lhs, args);
      }(),
      _ => lhs,
    };
    op = peek();
  }
  return lhs;
}