File size: 4,975 Bytes
7ed86c3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
"""Tests for hf_release/processing_char_bert_joint.py's to_ud(): converts the tagger-
parser's native Perseus/AGDT output (Prague-style deprels, single-letter XPOS/UPOS) to
Universal Dependencies. Covers the XPOS->UPOS+FEATS table and the three restructuring
rules (COORD, AuxP, Pnom), including the promoted-node fallback deprel ("dep"/"obl")
established by direct inspection of real training-corpus examples (oga_sota.conllu):
COORD's and AuxP's own outbound deprel is always the literal structural label itself
("COORD"/"AuxP"), never a recoverable functional role, so the promoted first-conjunct/
nominal cannot inherit a meaningful relation and gets UD's generic fallback instead."""
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "hf_release"))

from processing_char_bert_joint import to_ud, xpos_to_upos_feats


def _by_form(words):
    return {w["form"]: w for w in words}


def test_xpos_to_upos_feats_verb_and_noun():
    upos, feats = xpos_to_upos_feats("v3spia---")
    assert upos == "VERB"
    assert feats == {"Person": "3", "Number": "Sing", "Tense": "Pres",
                      "Mood": "Ind", "VerbForm": "Fin", "Voice": "Act"}

    upos, feats = xpos_to_upos_feats("n-s----n-")
    assert upos == "NOUN"
    assert feats == {"Number": "Sing", "Case": "Nom"}


def test_simple_sentence_sbj_pred_atr():
    sent = [
        dict(form="ὁ", xpos="l-s----n-", lemma="ὁ", upos="l", head=2, deprel="ATR"),
        dict(form="ἀνὴρ", xpos="n-s----n-", lemma="ἀνήρ", upos="n", head=3, deprel="SBJ"),
        dict(form="λέγει", xpos="v3spia---", lemma="λέγω", upos="v", head=0, deprel="PRED"),
    ]
    out = _by_form(to_ud(sent))
    assert out["ὁ"]["deprel"] == "det" and out["ὁ"]["upos"] == "DET"
    assert out["ἀνὴρ"]["deprel"] == "nsubj"
    assert out["λέγει"]["deprel"] == "root" and out["λέγει"]["head"] == 0


def test_coord_promotes_first_conjunct_with_generic_fallback():
    # "Παῦλος" is COORD's only child in this construction, so it gets promoted to
    # COORD's external attachment; COORD's own deprel carries no recoverable function,
    # so the fallback is "dep" (not the pre-fix bug of leaking "COORD" through verbatim).
    sent = [
        dict(form="Πέτρος", xpos="n-s----n-", lemma="Πέτρος", upos="n", head=4, deprel="SBJ"),
        dict(form="καὶ", xpos="c--------", lemma="καί", upos="c", head=1, deprel="COORD"),
        dict(form="Παῦλος", xpos="n-s----n-", lemma="Παῦλος", upos="n", head=2, deprel="SBJ"),
        dict(form="ἔρχονται", xpos="v3ppie---", lemma="ἔρχομαι", upos="v", head=0, deprel="PRED"),
    ]
    out = _by_form(to_ud(sent))
    assert out["καὶ"]["deprel"] == "cc" and out["καὶ"]["head"] == 3  # cc attaches to promoted conjunct
    assert out["Παῦλος"]["deprel"] == "dep" and out["Παῦλος"]["head"] == 1
    assert out["ἔρχονται"]["deprel"] == "root"


def test_auxp_promotes_nominal_to_obl():
    # "ἐν τῇ πόλει" (in the city): AuxP's own deprel is always the literal "AuxP",
    # never a recoverable function, so the promoted nominal falls back to "obl".
    sent = [
        dict(form="λέγει", xpos="v3spia---", lemma="λέγω", upos="v", head=0, deprel="PRED"),
        dict(form="ἐν", xpos="r--------", lemma="ἐν", upos="r", head=1, deprel="AuxP"),
        dict(form="τῇ", xpos="l-s----d-", lemma="ὁ", upos="l", head=3, deprel="ATR"),
        dict(form="πόλει", xpos="n-s----d-", lemma="πόλις", upos="n", head=2, deprel="ADV"),
    ]
    out = _by_form(to_ud(sent))
    assert out["πόλει"]["deprel"] == "obl" and out["πόλει"]["head"] == 1  # promoted, attaches to verb
    assert out["ἐν"]["deprel"] == "case" and out["ἐν"]["head"] == 4      # preposition demoted under nominal
    assert out["τῇ"]["deprel"] == "det" and out["τῇ"]["head"] == 3       # article still modifies the noun


def test_pnom_copula_reversal():
    # "ὁ ἀνὴρ ἐστι σοφός" (the man is wise): nominal becomes the head, copula
    # becomes `cop`, subject reattaches from the verb to the nominal.
    sent = [
        dict(form="ὁ", xpos="l-s----n-", lemma="ὁ", upos="l", head=2, deprel="ATR"),
        dict(form="ἀνὴρ", xpos="n-s----n-", lemma="ἀνήρ", upos="n", head=3, deprel="SBJ"),
        dict(form="ἐστι", xpos="v3spia---", lemma="εἰμί", upos="v", head=0, deprel="PRED"),
        dict(form="σοφός", xpos="a-s----n-", lemma="σοφός", upos="a", head=3, deprel="PNOM"),
    ]
    out = _by_form(to_ud(sent))
    assert out["σοφός"]["deprel"] == "root" and out["σοφός"]["head"] == 0
    assert out["ἐστι"]["deprel"] == "cop" and out["ἐστι"]["head"] == 4
    assert out["ἀνὴρ"]["deprel"] == "nsubj" and out["ἀνὴρ"]["head"] == 4  # reattached off the verb


def test_empty_sentence():
    assert to_ud([]) == []