       // consuming possibly significant new lines.
       let backtrackPosition = streamPosition
       if consume(.dot, afterMany: .newline) != nil {
-        // Although it wouldn't make the grammar ambiguous otherwise, notice that we require the
-        // selected identifier to be on the same line.
-        guard peek().kind == .identifier
+        guard peek().kind == .identifier || peek().isPrefixOperator || peek().isInfixOperator
           else { throw parseFailure(.expectedMember) }
-
-        let ident = try parseIdentifier()
+        let ident = try parseIdentifier(allowOperators: true)
+
         expression = SelectExpr(
           owner: expression,
           ownee: ident,


    case .dot:
      consume()
      let ident = try parseIdentifier()
      expression = SelectExpr(
        ownee: ident,
        module: module,

  }

  /// Parses an identifier.
  func parseIdentifier(allowOperators: Bool = false) throws -> Ident {
    let ident: Ident
    if let name = consume(.identifier) {
      ident = Ident(name: name.value!, module: module, range: name.range)
    } else if allowOperators, let op = consume(if: { $0.isPrefixOperator || $0.isInfixOperator }) {
      ident = Ident(name: op.kind.rawValue, module: module, range: op.range)
    } else {
      throw unexpectedToken(expected: "identifier")
    }

    // Attempt to parse the specialization list.
    let backtrackPosition = streamPosition
