|
#pragma once |
|
|
|
namespace Moses |
|
{ |
|
namespace Syntax |
|
{ |
|
namespace T2S |
|
{ |
|
|
|
template<typename Callback> |
|
RuleMatcherSCFG<Callback>::RuleMatcherSCFG(const InputTree &inputTree, |
|
const RuleTrie &ruleTrie) |
|
: m_inputTree(inputTree) |
|
, m_ruleTrie(ruleTrie) |
|
{ |
|
} |
|
|
|
template<typename Callback> |
|
void RuleMatcherSCFG<Callback>::EnumerateHyperedges(const InputTree::Node &node, |
|
Callback &callback) |
|
{ |
|
const int start = static_cast<int>(node.pvertex.span.GetStartPos()); |
|
m_hyperedge.head = const_cast<PVertex*>(&node.pvertex); |
|
m_hyperedge.tail.clear(); |
|
Match(node, m_ruleTrie.GetRootNode(), start, callback); |
|
} |
|
|
|
template<typename Callback> |
|
void RuleMatcherSCFG<Callback>::Match(const InputTree::Node &inNode, |
|
const RuleTrie::Node &trieNode, |
|
int start, Callback &callback) |
|
{ |
|
|
|
|
|
const std::vector<InputTree::Node*> &nodes = m_inputTree.nodesAtPos[start]; |
|
for (std::vector<InputTree::Node*>::const_iterator p = nodes.begin(); |
|
p != nodes.end(); ++p) { |
|
InputTree::Node &candidate = **p; |
|
|
|
if (!IsDescendent(candidate, inNode)) { |
|
continue; |
|
} |
|
|
|
|
|
const RuleTrie::Node::SymbolMap *map = NULL; |
|
if (candidate.children.empty()) { |
|
map = &(trieNode.GetTerminalMap()); |
|
} else { |
|
map = &(trieNode.GetNonTerminalMap()); |
|
} |
|
|
|
RuleTrie::Node::SymbolMap::const_iterator q = |
|
map->find(candidate.pvertex.symbol); |
|
if (q == map->end()) { |
|
continue; |
|
} |
|
const RuleTrie::Node &newTrieNode = q->second; |
|
|
|
m_hyperedge.tail.push_back(&candidate.pvertex); |
|
|
|
if (candidate.pvertex.span.GetEndPos() == inNode.pvertex.span.GetEndPos()) { |
|
|
|
const Word &lhs = inNode.pvertex.symbol; |
|
TargetPhraseCollection::shared_ptr tpc = |
|
newTrieNode.GetTargetPhraseCollection(lhs); |
|
if (tpc) { |
|
m_hyperedge.label.translations = tpc; |
|
callback(m_hyperedge); |
|
} |
|
} else { |
|
|
|
int newStart = candidate.pvertex.span.GetEndPos()+1; |
|
Match(inNode, newTrieNode, newStart, callback); |
|
} |
|
m_hyperedge.tail.pop_back(); |
|
} |
|
} |
|
|
|
|
|
template<typename Callback> |
|
bool RuleMatcherSCFG<Callback>::IsDescendent(const InputTree::Node &x, |
|
const InputTree::Node &y) |
|
{ |
|
const std::size_t xStart = x.pvertex.span.GetStartPos(); |
|
const std::size_t yStart = y.pvertex.span.GetStartPos(); |
|
const std::size_t xEnd = x.pvertex.span.GetEndPos(); |
|
const std::size_t yEnd = y.pvertex.span.GetEndPos(); |
|
if (xStart < yStart || xEnd > yEnd) { |
|
return false; |
|
} |
|
if (xStart > yStart || xEnd < yEnd) { |
|
return true; |
|
} |
|
|
|
const InputTree::Node *z = &y; |
|
while (z->children.size() == 1) { |
|
z = z->children[0]; |
|
if (z == &x) { |
|
return true; |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
} |
|
} |
|
} |
|
|