diff --git a/libwccl/ops/match/actions/markmatch.cpp b/libwccl/ops/match/actions/markmatch.cpp index 9c987a2f9144198e4b88ca959ebb26d9a6226183..27933f151ae8afd92ce0985565df49a3043ac4ca 100644 --- a/libwccl/ops/match/actions/markmatch.cpp +++ b/libwccl/ops/match/actions/markmatch.cpp @@ -18,20 +18,26 @@ void MarkMatch::execute(const ActionExecContext& context) const 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(); - int abs_right = match_to->last_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."); } - // TODO: what about head in this mark from match actions? Mark from tag actions does have it. - int abs_head = abs_left; + + 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_); diff --git a/libwccl/ops/match/actions/markmatch.h b/libwccl/ops/match/actions/markmatch.h index 9f5b6e51377854d08181154898cfc7d3c0a3971e..024af6decd0188bdf5016901c61c75ce3b2a407a 100644 --- a/libwccl/ops/match/actions/markmatch.h +++ b/libwccl/ops/match/actions/markmatch.h @@ -12,13 +12,30 @@ public: MarkMatch( const boost::shared_ptr<Function<Match> >& match_from, const boost::shared_ptr<Function<Match> >& match_to, + const boost::shared_ptr<Function<Match> >& head_match, const std::string& annotation_name) : match_from_(match_from), match_to_(match_to), + head_match_(head_match), chan_name_(annotation_name) { BOOST_ASSERT(match_from_); BOOST_ASSERT(match_to_); + BOOST_ASSERT(head_match_); + } + + MarkMatch( + const boost::shared_ptr<Function<Match> >& match_from, + const boost::shared_ptr<Function<Match> >& match_to, + const std::string& annotation_name) + : match_from_(match_from), + match_to_(match_to), + head_match_(match_from), + chan_name_(annotation_name) + { + BOOST_ASSERT(match_from_); + BOOST_ASSERT(match_to_); + BOOST_ASSERT(head_match_); } MarkMatch( @@ -26,10 +43,12 @@ public: const std::string& annotation_name) : match_from_(match_from_to), match_to_(match_from_to), + head_match_(match_from_to), chan_name_(annotation_name) { BOOST_ASSERT(match_from_); BOOST_ASSERT(match_to_); + BOOST_ASSERT(head_match_); } /** * @returns Name of the action. @@ -59,6 +78,7 @@ protected: private: const boost::shared_ptr<Function<Match> >& match_from_; const boost::shared_ptr<Function<Match> >& match_to_; + const boost::shared_ptr<Function<Match> >& head_match_; const std::string chan_name_; }; diff --git a/libwccl/parser/grammar.g b/libwccl/parser/grammar.g index ba4f99c0fdb5fba5a1f0acfe110e574891085b6a..9bea7459323dd907b6dd87c11b3c0ec026a1e118 100644 --- a/libwccl/parser/grammar.g +++ b/libwccl/parser/grammar.g @@ -1947,10 +1947,13 @@ match_mark_action { boost::shared_ptr<Function<Match> > match_to; boost::shared_ptr<Function<Match> > match_from; + boost::shared_ptr<Function<Match> > head_match; } : "mark" LPAREN match_from = match_fit[tagset, vars] COMMA - (match_to = match_fit[tagset, vars] COMMA) ? + ( match_to = match_fit[tagset, vars] COMMA + ( head_match = match_fit[tagset, vars] COMMA )? + )? annotation_name : STRING RPAREN { if (!match_to) { @@ -1959,11 +1962,20 @@ match_mark_action match_from, ((antlr::Token*)annotation_name)->getText())); } else { - m_act.reset( - new MarkMatch( - match_from, - match_to, - ((antlr::Token*)annotation_name)->getText())); + if (!head_match) { + m_act.reset( + new MarkMatch( + match_from, + match_to, + ((antlr::Token*)annotation_name)->getText())); + } else { + m_act.reset( + new MarkMatch( + match_from, + match_to, + head_match, + ((antlr::Token*)annotation_name)->getText())); + } } } ;