diff --git a/libwccl/ops/functions/bool/iteration.cpp b/libwccl/ops/functions/bool/iteration.cpp
index e9be9e8e5d18dac3f1fe4622160e6a360e9f5371..c91fc17ebf78efe9c2cf2ff1f387d438876cc6cb 100644
--- a/libwccl/ops/functions/bool/iteration.cpp
+++ b/libwccl/ops/functions/bool/iteration.cpp
@@ -34,25 +34,13 @@ Iteration::BaseRetValPtr Iteration::apply_internal(const FunExecContext& context
 	if (range_left->get_value() != Position::Nowhere) {
 		const boost::shared_ptr<const Position>& range_right =
 										right_pos_expr_->apply(context);
-		if (range_right->get_value() != Position::Nowhere) {
-			// Get absolute values for left and right extremes of the range.
-			int right = sc.get_abs_position(*range_right);
-			int left = sc.get_abs_position(*range_left);
-			// Trim range to sentence boundaries
-			if (left < 0) {
-				left = 0;
-			}
-			if (right >= sc.size()) {
-				right = sc.size() - 1;
-			}
-			// Proceed only if range isn't empty
-			if (left <= right) {
-				// Change range from absolute to relative and iterate
-				left -= sc.get_position();
-				right -= sc.get_position();
-				if (iterate(left, right, *iter_var, context)) {
-					return Predicate::True(context);
-				}
+		int left, right;
+		if (sc.validate_range(*range_left, *range_right, left, right)) {
+			// Change range from absolute to relative and iterate
+			left -= sc.get_position();
+			right -= sc.get_position();
+			if (iterate(left, right, *iter_var, context)) {
+				return Predicate::True(context);
 			}
 		}
 	}
diff --git a/libwccl/ops/functions/bool/predicates/strongagreement.cpp b/libwccl/ops/functions/bool/predicates/strongagreement.cpp
index 8678cf47e67ecef90d033a4c73a175b6c029ef50..908def3ac92bb55a0dcf23116b3f121e9645a38f 100644
--- a/libwccl/ops/functions/bool/predicates/strongagreement.cpp
+++ b/libwccl/ops/functions/bool/predicates/strongagreement.cpp
@@ -33,21 +33,10 @@ StrongAgreement::BaseRetValPtr StrongAgreement::apply_internal(const FunExecCont
 	if (range_right->get_value() == Position::Nowhere) {
 		return Predicate::False(context);
 	}
-	// Get absolute values for left and right extremes of the range.
-	int abs_left = sc.get_abs_position(*range_left);
-	int abs_right = sc.get_abs_position(*range_right);
-	// Trim range to sentence boundaries
-	if (abs_left < 0) {
-		abs_left = 0;
-	}
-	if (abs_right >= sc.size()) {
-		abs_right = sc.size() - 1;
-	}
-	// Proceed only if range isn't empty (range outside of sentence or empty sentence are covered)
-	if (abs_left > abs_right) {
+	int abs_left, abs_right;
+	if (!sc.validate_range(*range_left, *range_right, abs_left, abs_right)) {
 		return Predicate::False(context);
 	}
-
 	const boost::shared_ptr<const TSet>& attribs = attribs_expr_->apply(context);
 
 	int min_card = attribs->categories_count(tagset_);
diff --git a/libwccl/ops/functions/bool/predicates/weakagreement.cpp b/libwccl/ops/functions/bool/predicates/weakagreement.cpp
index 22828122c8565a4b07ea3548528519d0c23ad9f3..b7f4b6689ef3d1180637a8d4250ce869b0843df0 100644
--- a/libwccl/ops/functions/bool/predicates/weakagreement.cpp
+++ b/libwccl/ops/functions/bool/predicates/weakagreement.cpp
@@ -33,21 +33,10 @@ WeakAgreement::BaseRetValPtr WeakAgreement::apply_internal(const FunExecContext&
 	if (range_right->get_value() == Position::Nowhere) {
 		return Predicate::False(context);
 	}
-	// Get absolute values for left and right extremes of the range.
-	int abs_left = sc.get_abs_position(*range_left);
-	int abs_right = sc.get_abs_position(*range_right);
-	// Trim range to sentence boundaries
-	if (abs_left < 0) {
-		abs_left = 0;
-	}
-	if (abs_right >= sc.size()) {
-		abs_right = sc.size() - 1;
-	}
-	// Proceed only if range isn't empty (range outside of sentence or empty sentence are covered)
-	if (abs_left > abs_right) {
+	int abs_left, abs_right;
+	if (!sc.validate_range(*range_left, *range_right, abs_left, abs_right)) {
 		return Predicate::False(context);
 	}
-
 	const boost::shared_ptr<const TSet>& attribs = attribs_expr_->apply(context);
 
 	int min_card = attribs->categories_count(tagset_);
diff --git a/libwccl/ops/functions/tset/agrfilter.cpp b/libwccl/ops/functions/tset/agrfilter.cpp
index 21b6661bfd8fb5c390170e30a624ef2b1dc39869..ef56fa5ad641287903f4e8033b3760e78eab1171 100644
--- a/libwccl/ops/functions/tset/agrfilter.cpp
+++ b/libwccl/ops/functions/tset/agrfilter.cpp
@@ -35,21 +35,10 @@ AgrFilter::BaseRetValPtr AgrFilter::apply_internal(const FunExecContext& context
 	if (range_right->get_value() == Position::Nowhere) {
 		return detail::DefaultFunction<TSet>()->apply(context);
 	}
-	// Get absolute values for left and right extremes of the range.
-	int abs_left = sc.get_abs_position(*range_left);
-	int abs_right = sc.get_abs_position(*range_right);
-	// Trim range to sentence boundaries
-	if (abs_left < 0) {
-		abs_left = 0;
-	}
-	if (abs_right >= sc.size()) {
-		abs_right = sc.size() - 1;
-	}
-	// Proceed only if range isn't empty (range outside of sentence or empty sentence are covered)
-	if (abs_left > abs_right) {
+	int abs_left, abs_right;
+	if (!sc.validate_range(*range_left, *range_right, abs_left, abs_right)) {
 		return detail::DefaultFunction<TSet>()->apply(context);
 	}
-
 	const boost::shared_ptr<const TSet>& attribs = attribs_expr_->apply(context);
 	const boost::shared_ptr<const TSet>& mask = mask_expr_->apply(context);
 
diff --git a/libwccl/ops/functions/tset/getsymbolsinrange.cpp b/libwccl/ops/functions/tset/getsymbolsinrange.cpp
index 13cfce9ec1956c2eaa4bd0a0b42f107919bdf547..2897b69ed63b72bde2d79676fbfc07a52375ec00 100644
--- a/libwccl/ops/functions/tset/getsymbolsinrange.cpp
+++ b/libwccl/ops/functions/tset/getsymbolsinrange.cpp
@@ -26,22 +26,14 @@ std::ostream& GetSymbolsInRange::write_to(std::ostream& os) const
 GetSymbolsInRange::BaseRetValPtr GetSymbolsInRange::apply_internal(const FunExecContext& context) const
 {
 	const boost::shared_ptr<const Position>& range_begin = rbegin_expr_->apply(context);
-	const boost::shared_ptr<const Position>& range_end = rend_expr_->apply(context);
 	const SentenceContext& sc = context.sentence_context();
 
-	int abs_begin = sc.get_abs_position(*range_begin);
-	int abs_end = sc.get_abs_position(*range_end);
-	// Trim range to sentence boundaries
-	if ((abs_begin != Position::Nowhere) && (abs_begin < 0)) {
-		abs_begin = 0;
-	}
-	if ((abs_end != Position::Nowhere) && (abs_end >= sc.size())) {
-		abs_end = sc.size() - 1;
+	if (range_begin->get_value() == Position::Nowhere ) {
+		return detail::DefaultFunction<TSet>()->apply(context);
 	}
-	// If range is empty, return an empty set - note the below also
-	// covers ranges without overlap with actual sentence range
-	// (including an empty sentence).
-	if((abs_begin == Position::Nowhere) || (abs_end == Position::Nowhere) || (abs_begin > abs_end)) {
+	const boost::shared_ptr<const Position>& range_end = rend_expr_->apply(context);
+	int abs_begin, abs_end;
+	if (!sc.validate_range(*range_begin, *range_end, abs_begin, abs_end)) {
 		return detail::DefaultFunction<TSet>()->apply(context);
 	}
 
diff --git a/libwccl/sentencecontext.h b/libwccl/sentencecontext.h
index 1fecb3f84739e3424090afcb684f66d5c7ee2440..0f61c0fe8bc8b85b5c6f40676e2859e8a58e61d4 100644
--- a/libwccl/sentencecontext.h
+++ b/libwccl/sentencecontext.h
@@ -72,6 +72,26 @@ public:
 		return !is_inside(get_abs_position(pos));
 	}
 
+	/**
+	 * Checks if range is valid, i.e. non-empty and not outside of sentence,
+	 * and at the same time finds absolute values of passed Positions
+	 * @param left Position specyfing left extreme of the range
+	 * @param right Position specyfing right extreme of the range
+	 * @param abs_left reference to int value that will hold absolute
+	 * value for left position
+	 * @param abs_right reference to int value that will hold absolute
+	 * value for right position
+	 * @returns true if range is valid; in this case abs_left and abs_right
+	 * are set to absolute positions values for left and right Position.
+	 * False is returned otherwise; in this case abs_left and abs_right
+	 * are set to Nowhere
+	 */
+	bool validate_range(
+			const Position& left,
+			const Position& right,
+			int& abs_left,
+			int& abs_right) const;
+
 	/// Position setter
 	void set_position(int new_position) {
 		position_ = new_position;
@@ -152,6 +172,42 @@ private:
 	int position_;
 };
 
+
+inline
+bool SentenceContext::validate_range(
+	const Position& left,
+	const Position& right,
+	int& abs_left,
+	int& abs_right) const
+{
+	abs_left = get_abs_position(left);
+
+	if (abs_left == Position::Nowhere) {
+		abs_right = Position::Nowhere;
+		return false;
+	}
+	abs_right = get_abs_position(right);
+	if (abs_right == Position::Nowhere) {
+		abs_left = Position::Nowhere;
+		return false;
+	}
+	// Trim range to sentence boundaries
+	if (abs_left < 0) {
+		abs_left = 0;
+	}
+	if (abs_right >= size()) {
+		abs_right = size() - 1;
+	}
+	// is range valid? this covers "crossed" range, an empty sentence,
+	// and range outside boundaries of sentence
+	if (abs_left > abs_right) {
+		abs_left = Position::Nowhere;
+		abs_right = Position::Nowhere;
+		return false;
+	}
+	return true;
+}
+
 // TODO ConstSentenceContext ?
 
 } /* end ns Wccl */