diff --git a/src/lexdcompiler.cc b/src/lexdcompiler.cc index 4f39e67..58e5999 100644 --- a/src/lexdcompiler.cc +++ b/src/lexdcompiler.cc @@ -54,6 +54,24 @@ bool tag_filter_t::try_apply(tags_t &tags) const unionset_inplace(tags, pos()); return true; } +vector> tag_filter_t::distribute_pos(size_t n) const +{ + vector> ret; + ret.resize(1); + ret[0].resize(n); + for (auto& tag : _pos) { + vector> ret2; + for (auto& seq : ret) { + for (size_t i = 0; i < n; i++) { + auto seq2 = seq; + seq2[i].insert(tag); + ret2.push_back(seq2); + } + } + ret.swap(ret2); + } + return ret; +} bool pattern_element_t::compatible(const lex_seg_t &tok) const { return left.name.empty() || right.name.empty() || tag_filter.compatible(tok.tags); @@ -1193,35 +1211,43 @@ LexdCompiler::buildPattern(const pattern_element_t &tok) tempMatch.swap(matchedParts); for(auto &pat_untagged : patterns[tok.left.name]) { - for(unsigned int i = 0; i < pat_untagged.second.size(); i++) - { - auto pat = pat_untagged; - bool taggable = true; - for (unsigned int j = 0; j < pat.second.size(); j++) { - auto& pair = pat.second[j]; - if(!pair.tag_filter.combine(tok.tag_filter.neg())) { + auto pat_line = pat_untagged.first; + auto pat_minus = pat_untagged.second; + bool taggable = true; + for (auto& it : pat_minus) { + if (!it.tag_filter.combine(tok.tag_filter.neg())) { + taggable = false; + if (verbose) { + cerr << "Warning: The tags of " << to_ustring(printPattern(tok)); + cerr << " conflict with " << to_ustring(printPattern(it)); + cerr << " on line " << pat_line << "." << endl; + } + break; + } + } + if (!taggable) continue; + size_t len = pat_minus.size(); + auto pos_tags = tok.tag_filter.distribute_pos(len); + for (auto& pos_tag_seq : pos_tags) { + taggable = true; + auto pat = pat_minus; + for (size_t i = 0; i < len; i++) { + if (!pat[i].tag_filter.combine(pos_tag_seq[i])) { taggable = false; if (verbose) { cerr << "Warning: The tags of " << to_ustring(printPattern(tok)); - cerr << " conflict with " << to_ustring(printPattern(pat_untagged.second[j])); - cerr << " on line " << pat.first << "." << endl; + cerr << " conflict with " << to_ustring(printPattern(pat[i])); + cerr << " on line " << pat_line << "." << endl; } - } - } - if(!pat.second[i].tag_filter.combine(tok.tag_filter.pos())) { - taggable = false; - if (verbose) { - cerr << "Warning: The tags of " << to_ustring(printPattern(tok)); - cerr << " conflict with " << to_ustring(printPattern(pat_untagged.second[i])); - cerr << " on line " << pat.first << "." << endl; + break; } } if (!taggable) continue; matchedParts.clear(); - lineNumber = pat.first; - vector is_free = determineFreedom(pat.second); - buildPattern(t->getInitial(), t, pat.second, is_free, 0); + lineNumber = pat_line; + vector is_free = determineFreedom(pat); + buildPattern(t->getInitial(), t, pat, is_free, 0); } } tempMatch.swap(matchedParts); diff --git a/src/lexdcompiler.h b/src/lexdcompiler.h index a19a02d..fe4314e 100644 --- a/src/lexdcompiler.h +++ b/src/lexdcompiler.h @@ -174,6 +174,8 @@ struct tag_filter_t { return filters; } + vector> distribute_pos(size_t n) const; + private: pos_tag_filter_t _pos; neg_tag_filter_t _neg; diff --git a/tests/feature/Makefile b/tests/feature/Makefile index b3a5b66..9315d61 100644 --- a/tests/feature/Makefile +++ b/tests/feature/Makefile @@ -20,6 +20,7 @@ tests = \ lexname-space \ lextag \ lexnegtag \ + multipos \ nontree \ oneside \ opt \ diff --git a/tests/feature/test-multipos.lexd b/tests/feature/test-multipos.lexd new file mode 100644 index 0000000..37785eb --- /dev/null +++ b/tests/feature/test-multipos.lexd @@ -0,0 +1,19 @@ +PATTERNS +Subject ObjectPrefix VStemBase[tv,cl3] +Subject VStemBase[iv,cl3] + +LEXICON Subject +:ni> + +LEXICON ObjectPrefix +:nech> + +PATTERN VStemBase +VerbRootIV [:[iv]] +VerbRootTV [:[tv]] + +LEXICON VerbRootIV +blah[cl3] + +LEXICON VerbRootTV +ihtoa:{i}htoa[cl3] diff --git a/tests/feature/test-multipos.lexd.txt.strings.gold b/tests/feature/test-multipos.lexd.txt.strings.gold new file mode 100644 index 0000000..26e659e --- /dev/null +++ b/tests/feature/test-multipos.lexd.txt.strings.gold @@ -0,0 +1,2 @@ +ihtoa:ni>nech>{i}htoa +blah:ni>blah