From 640d27c7845499e9c2f01e921807eac323e2dc41 Mon Sep 17 00:00:00 2001
From: Adam Radziszewski <adam.radziszewski@pwr.wroc.pl>
Date: Thu, 4 Aug 2011 12:51:35 +0200
Subject: [PATCH] Change in only semantics: range beg&end may be crossed,
 resulting in True

---
 libwccl/ops/functions/bool/iteration.cpp          |  8 ++++++--
 libwccl/ops/functions/bool/iteration.h            | 14 +++++++++-----
 libwccl/ops/functions/bool/iterations/atleast.h   |  3 ++-
 libwccl/ops/functions/bool/iterations/leftlook.h  |  3 ++-
 libwccl/ops/functions/bool/iterations/only.h      |  6 ++++--
 libwccl/ops/functions/bool/iterations/rightlook.h |  3 ++-
 libwccl/sentencecontext.h                         | 10 +++++++---
 7 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/libwccl/ops/functions/bool/iteration.cpp b/libwccl/ops/functions/bool/iteration.cpp
index c91fc17..cb2034a 100644
--- a/libwccl/ops/functions/bool/iteration.cpp
+++ b/libwccl/ops/functions/bool/iteration.cpp
@@ -25,8 +25,11 @@ std::ostream& Iteration::write_to(std::ostream& os) const
 
 Iteration::BaseRetValPtr Iteration::apply_internal(const FunExecContext& context) const
 {
+	// Set iteration variable to Nowhere
+	// Should be overridden if succeeded
 	const boost::shared_ptr<Position>& iter_var =
 		context.variables()->get_fast(iter_var_acc_);
+	iter_var->set_value(Position::Nowhere);
 	const SentenceContext& sc = context.sentence_context();
 	// Proceed only if range extremes are not "nowhere".
 	const boost::shared_ptr<const Position>& range_left =
@@ -35,7 +38,8 @@ Iteration::BaseRetValPtr Iteration::apply_internal(const FunExecContext& context
 		const boost::shared_ptr<const Position>& range_right =
 										right_pos_expr_->apply(context);
 		int left, right;
-		if (sc.validate_range(*range_left, *range_right, left, right)) {
+		if (sc.validate_range(*range_left, *range_right,
+							  left, right, may_cross)) {
 			// Change range from absolute to relative and iterate
 			left -= sc.get_position();
 			right -= sc.get_position();
@@ -44,7 +48,7 @@ Iteration::BaseRetValPtr Iteration::apply_internal(const FunExecContext& context
 			}
 		}
 	}
-	// In case of failure, set iteration variable to Nowhere and return False
+	// Failure. Make sure iteration variable points Nowhere and return False
 	iter_var->set_value(Position::Nowhere);
 	return Predicate::False(context);
 }
diff --git a/libwccl/ops/functions/bool/iteration.h b/libwccl/ops/functions/bool/iteration.h
index dee6c88..cb96a2e 100644
--- a/libwccl/ops/functions/bool/iteration.h
+++ b/libwccl/ops/functions/bool/iteration.h
@@ -28,16 +28,19 @@ protected:
 	const PosFunctionPtr right_pos_expr_;
 	const VariableAccessor<Position> iter_var_acc_;
 	const BoolFunctionPtr evaluating_expr_;
+	const bool may_cross;
 	
 	Iteration(
 		const PosFunctionPtr& left_pos_expr,
 		const PosFunctionPtr& right_pos_expr,
 		const VariableAccessor<Position>& iter_var_acc,
-		const BoolFunctionPtr& evaluating_expr)
+		const BoolFunctionPtr& evaluating_expr,
+		bool may_cross)
 		: left_pos_expr_(left_pos_expr),
 		  right_pos_expr_(right_pos_expr),
 		  iter_var_acc_(iter_var_acc),
-		  evaluating_expr_(evaluating_expr)
+		  evaluating_expr_(evaluating_expr),
+		  may_cross(may_cross)
 	{
 		BOOST_ASSERT(left_pos_expr_);
 		BOOST_ASSERT(right_pos_expr_);
@@ -50,9 +53,10 @@ protected:
 	 * iteration variable, evaluating positions within the
 	 * range using supplied evaluation function.
 	 * Range is trimmed to sentence boundaries.
-	 * In case of an invalid range (begin and end cross over or
-	 * either of them points Nowhere), False is returned and iteration
-	 * variable set to Nowhere.
+	 * A range is invalid when begin or end point Nowhere. Depending on the
+	 * value of may_cross, a range with begin following end is treated either
+	 * as invalid (may_cross == False) or valid. In case of an invalid range,
+	 * False is returned and iteration variable set to Nowhere.
 	 * If range is correct, return value depends on stopping condition
 	 * that describes how many positions within the range have to evaluate
 	 * to true. Exact details depend on type of iteration, and are
diff --git a/libwccl/ops/functions/bool/iterations/atleast.h b/libwccl/ops/functions/bool/iterations/atleast.h
index 21d5536..a2b756e 100644
--- a/libwccl/ops/functions/bool/iterations/atleast.h
+++ b/libwccl/ops/functions/bool/iterations/atleast.h
@@ -19,7 +19,8 @@ public:
 		const VariableAccessor<Position>& iter_var_acc,
 		const BoolFunctionPtr& evaluating_expr,
 		int min_matches)
-		: Iteration(left_pos_expr, right_pos_expr, iter_var_acc, evaluating_expr),
+		: Iteration(left_pos_expr, right_pos_expr, iter_var_acc,
+					evaluating_expr, false), // false==no crossing ranges
 		  min_matches_(min_matches)
 	{
 		BOOST_ASSERT(min_matches_ > 0);
diff --git a/libwccl/ops/functions/bool/iterations/leftlook.h b/libwccl/ops/functions/bool/iterations/leftlook.h
index 618aa3d..e0776c6 100644
--- a/libwccl/ops/functions/bool/iterations/leftlook.h
+++ b/libwccl/ops/functions/bool/iterations/leftlook.h
@@ -18,7 +18,8 @@ public:
 		const PosFunctionPtr& right_pos_expr,
 		const VariableAccessor<Position>& iter_var_acc,
 		const BoolFunctionPtr& evaluating_expr)
-		: Iteration(left_pos_expr, right_pos_expr, iter_var_acc, evaluating_expr)
+		: Iteration(left_pos_expr, right_pos_expr, iter_var_acc,
+					evaluating_expr, false) // false==no crossing ranges
 	{
 	}
 
diff --git a/libwccl/ops/functions/bool/iterations/only.h b/libwccl/ops/functions/bool/iterations/only.h
index dce58cb..f11d6f5 100644
--- a/libwccl/ops/functions/bool/iterations/only.h
+++ b/libwccl/ops/functions/bool/iterations/only.h
@@ -8,7 +8,8 @@ namespace Wccl {
 /**
  * Iterative operator "only", which mandates that
  * evaluating expression should evaluate to true
- * on all positions in range.
+ * on all positions in range OR the range should
+ * be empty.
  */
 class Only : public Iteration
 {
@@ -18,7 +19,8 @@ public:
 		const PosFunctionPtr& right_pos_expr,
 		const VariableAccessor<Position>& iter_var_acc,
 		const BoolFunctionPtr& evaluating_expr)
-		: Iteration(left_pos_expr, right_pos_expr, iter_var_acc, evaluating_expr)
+		: Iteration(left_pos_expr, right_pos_expr, iter_var_acc,
+					evaluating_expr, true)
 	{
 	}
 
diff --git a/libwccl/ops/functions/bool/iterations/rightlook.h b/libwccl/ops/functions/bool/iterations/rightlook.h
index dcc5e5f..579aea3 100644
--- a/libwccl/ops/functions/bool/iterations/rightlook.h
+++ b/libwccl/ops/functions/bool/iterations/rightlook.h
@@ -18,7 +18,8 @@ public:
 		const PosFunctionPtr& right_pos_expr,
 		const VariableAccessor<Position>& iter_var_acc,
 		const BoolFunctionPtr& evaluating_expr)
-		: Iteration(left_pos_expr, right_pos_expr, iter_var_acc, evaluating_expr)
+		: Iteration(left_pos_expr, right_pos_expr, iter_var_acc,
+					evaluating_expr, false) // false==no crossing ranges
 	{
 	}
 
diff --git a/libwccl/sentencecontext.h b/libwccl/sentencecontext.h
index a857a3f..6775ef8 100644
--- a/libwccl/sentencecontext.h
+++ b/libwccl/sentencecontext.h
@@ -88,6 +88,7 @@ public:
 	 * value for left position
 	 * @param abs_right reference to int value that will hold absolute
 	 * value for right position
+	 * @param may_cross set to true if crossing begin and end is admissible
 	 * @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
@@ -97,7 +98,8 @@ public:
 			const Position& left,
 			const Position& right,
 			int& abs_left,
-			int& abs_right) const;
+			int& abs_right,
+			bool may_cross = false) const;
 
 	/// Position setter
 	void set_position(int new_position) {
@@ -196,7 +198,8 @@ bool SentenceContext::validate_range(
 	const Position& left,
 	const Position& right,
 	int& abs_left,
-	int& abs_right) const
+	int& abs_right,
+	bool may_cross) const
 {
 	abs_left = get_abs_position(left);
 
@@ -216,9 +219,10 @@ bool SentenceContext::validate_range(
 	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) {
+	if (!may_cross && (abs_left > abs_right)) {
 		abs_left = Position::Nowhere;
 		abs_right = Position::Nowhere;
 		return false;
-- 
GitLab