#include <libwccl/values/match.h> #include <libwccl/ops/match/actions/markmatch.h> #include <sstream> namespace Wccl { void MarkMatch::execute(const ActionExecContext& context) const { SentenceContext& sc = context.sentence_context(); boost::shared_ptr<Corpus2::AnnotatedSentence> as; as = boost::dynamic_pointer_cast<Corpus2::AnnotatedSentence>(sc.get_sentence_ptr()); if (!as) { throw InvalidArgument("context", "Operator needs an annotated sentence."); } boost::shared_ptr<const Match> match_from = match_from_->apply(context); boost::shared_ptr<const Match> match_to = (match_from_.get() == match_to_.get()) ? match_from : match_to_->apply(context); boost::shared_ptr<const Match> head_match = (match_from_.get() == head_match_.get()) ? match_from : head_match_->apply(context); int abs_left = match_from->first_token(as).get_value(); if (abs_left < 0) { throw WcclError("Received starting match that points outside sentence."); } int abs_right = match_to->last_token(as).get_value(); if (abs_right >= sc.size()) { throw WcclError("Received ending match that points outside sentence."); } if (abs_left > abs_right) { throw WcclError("Received starting match points after the received ending match."); } int abs_head = head_match->first_token(as).get_value(); if (abs_head < abs_left || abs_head > abs_right) { throw WcclError("Received head match points outside range defined by start and end matches."); } if (!as->has_channel(chan_name_)) { as->create_channel(chan_name_); } Corpus2::AnnotationChannel& channel = as->get_channel(chan_name_); int segment_idx = channel.get_new_segment_index(); for (int i = abs_left; i <= abs_right; ++i) { if (channel.get_segment_at(i) > 0) { throw WcclError("Mark action would overwrite existing annotation"); } } for (int i = abs_left; i <= abs_right; ++i) { channel.set_segment_at(i, segment_idx); channel.set_head_at(i, false); } channel.set_head_at(abs_head, true); } std::string MarkMatch::to_string(const Corpus2::Tagset& tagset) const { std::ostringstream os; os << name() << "(" << match_from_->to_string(tagset) << ", "; if (match_from_.get() != match_to_.get()) { os << match_to_->to_string(tagset) << ", "; } os << "\"" << chan_name_ << "\")"; return os.str(); } std::ostream& MarkMatch::write_to(std::ostream& os) const { os << name() << "(" << *match_from_ << ", "; if (match_from_.get() != match_to_.get()) { os << *match_to_ << ", "; } os << "\"" << chan_name_ << "\")"; return os; } } /* end ns Wccl */