func (b *Builder) ParseMethodCallOrMapLookup(ctx *builderCtx, invocant node.Node) node.Node { // We have already seen identifier followed by a period symbol := b.NextNonSpace(ctx) if symbol.Type() != ItemIdentifier { b.Unexpected(ctx, "Expected identifier for method call or map lookup, got %s", symbol.Type()) } var n node.Node next := b.NextNonSpace(ctx) if next.Type() != ItemOpenParen { // it's a map lookup. Put back that extra token we read b.Backup(ctx) n = node.NewFetchFieldNode(invocant.Pos(), invocant, symbol.Value()) } else { // It's a method call! Parse the list args := b.ParseList(ctx) closeParen := b.NextNonSpace(ctx) if closeParen.Type() != ItemCloseParen { b.Unexpected(ctx, "Expected ')', got %s", closeParen.Type()) } n = node.NewMethodCallNode(invocant.Pos(), invocant, symbol.Value(), args.(*node.ListNode)) } // If we are followed by another period, we are going to have to // check for another level of methodcall / lookup if b.PeekNonSpace(ctx).Type() == ItemPeriod { b.NextNonSpace(ctx) // consume period return b.ParseMethodCallOrMapLookup(ctx, n) } return n }
func (b *Builder) ParseFunCall(ctx *builderCtx, invocant node.Node) node.Node { next := b.NextNonSpace(ctx) if next.Type() != ItemOpenParen { b.Unexpected(ctx, "Expected '(', got %s", next.Type()) } args := b.ParseList(ctx) closeParen := b.NextNonSpace(ctx) if closeParen.Type() != ItemCloseParen { b.Unexpected(ctx, "Expected ')', got %s", closeParen.Type()) } return node.NewFunCallNode(invocant.Pos(), invocant, args.(*node.ListNode)) }