diff --git a/.gitignore b/.gitignore index badf168d..f65d4b90 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ Makefile /src/cg-mwesplit /src/cg-proc /src/cg-relabel +/src/cg-annotate +/src/cg-merge-annotations /src/CMakeFiles /src/libcg3.1.dylib /src/libcg3.dylib diff --git a/emacs/cg.el b/emacs/cg.el index 03b0d646..d342d953 100644 --- a/emacs/cg.el +++ b/emacs/cg.el @@ -164,7 +164,7 @@ Don't change without re-evaluating `cg-kw-re' (or all of cg.el).") "MAP" "ADD" "UNMAP" "SELECT" "REMOVE" - "SETPARENT" "SETCHILD" "REMPARENT" + "SETPARENT" "SETCHILD" "REMPARENT" "SWITCHPARENT" "ADDRELATION" "REMRELATION" "SETRELATION" "ADDRELATIONS" "REMRELATIONS" "SETRELATIONS" "SETVARIABLE" "REMVARIABLE" diff --git a/manual/dependencies.xml b/manual/dependencies.xml index e0f79f6b..76580102 100644 --- a/manual/dependencies.xml +++ b/manual/dependencies.xml @@ -62,7 +62,7 @@
REMPARENT - SETCHILD + REMPARENT [wordform] REMPARENT <target> [contextual_tests] ; @@ -75,6 +75,44 @@
+
+ SWITCHPARENT + + SWITCHPARENT + + + [wordform] SWITCHPARENT [WITHCHILD <child_set>] <target> [contextual_tests] ; + + + Sets the grandparent of the target as its parent and sets the target as the parent of the previous parent. If WTIHCHILD is present, any siblings of the target which match the set will also become children of the target. + + + "<and>" + "and" CCONJ #1->2 + "<in>" + "in" ADP #2->0 + "<the>" + "the" DET #3->4 + "<house>" + "house" NOUN #4->2 + "<.>" + "." PUNCT #5->2 + + SWITCHPARENT WITHCHILD (*) - (PUNCT) (NOUN) IF (p (ADP)) ; + + "<and>" + "and" CCONJ #1->4 + "<in>" + "in" ADP #2->4 + "<the>" + "the" DET #3->4 + "<house>" + "house" NOUN #4->0 + "<.>" + "." PUNCT #5->2 + +
+
Existing Trees in Input diff --git a/manual/rules.xml b/manual/rules.xml index 92aa27c4..e8214146 100644 --- a/manual/rules.xml +++ b/manual/rules.xml @@ -40,6 +40,7 @@ SETCHILD <target> [contextual_tests] TO|FROM <contextual_target> [contextual_tests] ; REMPARENT <target> [contextual_tests] ; + SWITCHPARENT [WITHCHILD <child_set>] <target> [contextual_tests] ; Relation manipulation: ADDRELATION <name> <target> [contextual_tests] diff --git a/src/GrammarApplicator_runRules.cpp b/src/GrammarApplicator_runRules.cpp index a58392bc..571901b7 100644 --- a/src/GrammarApplicator_runRules.cpp +++ b/src/GrammarApplicator_runRules.cpp @@ -473,7 +473,7 @@ bool GrammarApplicator::runSingleRule(SingleWindow& current, const Rule& rule, R } // If this is REMPARENT and there's no parent, skip it. - if (type == K_REMPARENT && cohort->dep_parent == DEP_NO_PARENT) { + if ((type == K_REMPARENT || type == K_SWITCHPARENT) && cohort->dep_parent == DEP_NO_PARENT) { continue; } @@ -2632,6 +2632,35 @@ uint32_t GrammarApplicator::runRulesOnSingleWindow(SingleWindow& current, const TRACE; get_apply_to().cohort->dep_parent = DEP_NO_PARENT; } + else if (rule->type == K_SWITCHPARENT) { + // this is a per-cohort rule + finish_reading_loop = false; + TRACE; + + // collect cohorts + Cohort* child = get_apply_to().cohort; + Cohort* parent = current.parent->cohort_map[child->dep_parent]; + auto grandparent_number = parent->dep_parent; + CohortSet siblings; + collect_subtree(siblings, parent, rule->childset1); + + // clear dependencies + child->dep_parent = DEP_NO_PARENT; + parent->dep_parent = DEP_NO_PARENT; + for (auto s : siblings) { + s->dep_parent = DEP_NO_PARENT; + } + + // reattach + auto it = current.parent->cohort_map.find(grandparent_number); + if (it != current.parent->cohort_map.end()) { + attachParentChild(*(it->second), *child); + } + attachParentChild(*child, *parent); + for (auto s : siblings) { + attachParentChild(*child, *s); + } + } else if (rule->type == K_MOVE_AFTER || rule->type == K_MOVE_BEFORE || rule->type == K_SWITCH) { // this is a per-cohort rule finish_reading_loop = false; diff --git a/src/Strings.hpp b/src/Strings.hpp index 07c08196..7dce3b8f 100644 --- a/src/Strings.hpp +++ b/src/Strings.hpp @@ -97,6 +97,7 @@ enum KEYWORDS : uint32_t { K_CMDARGS_OVERRIDE, K_COPYCOHORT, K_REMPARENT, + K_SWITCHPARENT, KEYWORD_COUNT, }; @@ -263,6 +264,7 @@ constexpr UStringView keywords[KEYWORD_COUNT] = { u"CMDARGS-OVERRIDE", u"COPYCOHORT", u"REMPARENT", + u"SWITCHPARENT", }; constexpr UStringView stringbits[] = { diff --git a/src/TextualParser.cpp b/src/TextualParser.cpp index 5cab7fde..197d8d50 100644 --- a/src/TextualParser.cpp +++ b/src/TextualParser.cpp @@ -1691,6 +1691,10 @@ bool TextualParser::maybeParseRule(UChar*& p) { else if (IS_ICASE(p, "REMPARENT", "remparent")) { parseRule(p, K_REMPARENT); } + // SWITCHPARENT + else if (IS_ICASE(p, "SWITCHPARENT", "switchparent")) { + parseRule(p, K_SWITCHPARENT); + } // RESTORE else if (IS_ICASE(p, "RESTORE", "restore")) { parseRule(p, K_RESTORE); diff --git a/test/T_SwitchParent/expected.txt b/test/T_SwitchParent/expected.txt new file mode 100644 index 00000000..11b68ddf --- /dev/null +++ b/test/T_SwitchParent/expected.txt @@ -0,0 +1,36 @@ +"" + "and" CCONJ #1->4 +"" + "in" ADP #2->4 +"" + "the" DET #3->4 +"" + "house" NOUN #4->0 +"<.>" + "." PUNCT #5->2 + +"" + "there" PRON #1->0 +"" + "and" CCONJ #2->5 +"" + "in" ADP #3->5 +"" + "the" DET #4->5 +"" + "house" NOUN #5->1 +"<.>" + "." PUNCT #6->3 + +"" + "there" PRON #1->0 +"" + "and" CCONJ #2->5 +"" + "in" ADP #3->5 +"" + "the" DET #4->5 +"" + "house" NOUN #5->5 +"<.>" + "." PUNCT #6->3 diff --git a/test/T_SwitchParent/grammar.cg3 b/test/T_SwitchParent/grammar.cg3 new file mode 100644 index 00000000..15b572ae --- /dev/null +++ b/test/T_SwitchParent/grammar.cg3 @@ -0,0 +1,4 @@ +CMDARGS += -D ; +DELIMITERS = "<.>" ; + +SWITCHPARENT WITHCHILD (*) - (PUNCT) (NOUN) IF (p (ADP)) ; diff --git a/test/T_SwitchParent/input.txt b/test/T_SwitchParent/input.txt new file mode 100644 index 00000000..50839e27 --- /dev/null +++ b/test/T_SwitchParent/input.txt @@ -0,0 +1,36 @@ +"" + "and" CCONJ #1->2 +"" + "in" ADP #2->0 +"" + "the" DET #3->4 +"" + "house" NOUN #4->2 +"<.>" + "." PUNCT #5->2 + +"" + "there" PRON #1->0 +"" + "and" CCONJ #2->3 +"" + "in" ADP #3->1 +"" + "the" DET #4->5 +"" + "house" NOUN #5->3 +"<.>" + "." PUNCT #6->3 + +"" + "there" PRON #1->0 +"" + "and" CCONJ #2->3 +"" + "in" ADP #3->3 +"" + "the" DET #4->5 +"" + "house" NOUN #5->3 +"<.>" + "." PUNCT #6->3