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 */