Spaces:
Running on Zero
Running on Zero
Update app.py
Browse files
app.py
CHANGED
|
@@ -1902,14 +1902,30 @@ MODAL_MID = {
|
|
| 1902 |
"certainly", "definitely", "simply", "almost",
|
| 1903 |
}
|
| 1904 |
###############################################################################
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1905 |
|
| 1906 |
###############################################################################
|
| 1907 |
def fix_subject_verb_agreement(sent: str) -> str:
|
| 1908 |
"""
|
| 1909 |
After a split, repair a finite verb / aux that no longer matches
|
| 1910 |
a singular subject.
|
| 1911 |
-
|
| 1912 |
-
(may have,
|
| 1913 |
"""
|
| 1914 |
if not sent or not sent.strip():
|
| 1915 |
return sent
|
|
@@ -1946,33 +1962,53 @@ def fix_subject_verb_agreement(sent: str) -> str:
|
|
| 1946 |
return True
|
| 1947 |
return False
|
| 1948 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1949 |
def in_bare_infinitive_complement(tok) -> bool:
|
| 1950 |
-
|
| 1951 |
-
|
| 1952 |
-
|
| 1953 |
-
|
| 1954 |
-
may not even have
|
| 1955 |
-
didn't want
|
| 1956 |
-
does not go
|
| 1957 |
-
will really be
|
| 1958 |
-
"""
|
| 1959 |
i = tok.i - 1
|
| 1960 |
while i >= 0:
|
| 1961 |
t = doc[i]
|
| 1962 |
-
if
|
| 1963 |
-
return True
|
| 1964 |
-
if t.lemma_ == "do" and t.lower_ in {"do", "does", "did"}:
|
| 1965 |
return True
|
|
|
|
| 1966 |
if (
|
| 1967 |
t.lower_ in MODAL_MID
|
|
|
|
| 1968 |
or t.dep_ in {"neg", "advmod", "punct"}
|
| 1969 |
or t.pos_ in {"ADV", "PART", "PUNCT", "SPACE"}
|
|
|
|
| 1970 |
):
|
| 1971 |
i -= 1
|
| 1972 |
continue
|
| 1973 |
return False
|
| 1974 |
return False
|
| 1975 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1976 |
def to_3sg(word: str) -> str:
|
| 1977 |
low = word.lower()
|
| 1978 |
irregular = {
|
|
@@ -1996,18 +2032,6 @@ def fix_subject_verb_agreement(sent: str) -> str:
|
|
| 1996 |
new = new[0].upper() + new[1:]
|
| 1997 |
return new
|
| 1998 |
|
| 1999 |
-
def skip_target(t) -> bool:
|
| 2000 |
-
if t.tag_ == "MD":
|
| 2001 |
-
return True
|
| 2002 |
-
if is_infinitive(t):
|
| 2003 |
-
return True
|
| 2004 |
-
if in_bare_infinitive_complement(t):
|
| 2005 |
-
return True
|
| 2006 |
-
# infinitival / base be must never get -s
|
| 2007 |
-
if t.lemma_ == "be" and t.lower_ in {"be", "bes", "beses"}:
|
| 2008 |
-
return True
|
| 2009 |
-
return False
|
| 2010 |
-
|
| 2011 |
target = None
|
| 2012 |
for t in doc:
|
| 2013 |
if skip_target(t):
|
|
@@ -2026,13 +2050,41 @@ def fix_subject_verb_agreement(sent: str) -> str:
|
|
| 2026 |
target = t
|
| 2027 |
break
|
| 2028 |
|
| 2029 |
-
|
| 2030 |
-
|
| 2031 |
-
|
| 2032 |
-
|
| 2033 |
|
| 2034 |
-
|
| 2035 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2036 |
###############################################################################
|
| 2037 |
|
| 2038 |
###############################################################################
|
|
|
|
| 1902 |
"certainly", "definitely", "simply", "almost",
|
| 1903 |
}
|
| 1904 |
###############################################################################
|
| 1905 |
+
# do-support / modal on the raw string to the left of the verb
|
| 1906 |
+
_LEFT_BARE_INF = re.compile(
|
| 1907 |
+
r"(?:"
|
| 1908 |
+
r"\b(?:can|could|may|might|must|shall|should|will|would)\b|"
|
| 1909 |
+
r"\b(?:do|does|did)\b|"
|
| 1910 |
+
r"\b(?:don't|doesn't|didn't|don’t|doesn’t|didn’t)\b|"
|
| 1911 |
+
r"\b(?:do|does|did)\s+not\b|"
|
| 1912 |
+
r"\b(?:don|doesn|didn)\s*['’]\s*t\b"
|
| 1913 |
+
r")"
|
| 1914 |
+
r"(?:\s+\b(?:not|even|never|also|really|just|only|still|"
|
| 1915 |
+
r"already|always|actually|probably|possibly|perhaps|"
|
| 1916 |
+
r"certainly|definitely|simply|almost)\b)*"
|
| 1917 |
+
r"\s+$",
|
| 1918 |
+
flags=re.I,
|
| 1919 |
+
)
|
| 1920 |
+
###############################################################################
|
| 1921 |
|
| 1922 |
###############################################################################
|
| 1923 |
def fix_subject_verb_agreement(sent: str) -> str:
|
| 1924 |
"""
|
| 1925 |
After a split, repair a finite verb / aux that no longer matches
|
| 1926 |
a singular subject.
|
| 1927 |
+
Never inflect a bare infinitive after a modal or do-support
|
| 1928 |
+
(may have, didn't want, didn ' t want).
|
| 1929 |
"""
|
| 1930 |
if not sent or not sent.strip():
|
| 1931 |
return sent
|
|
|
|
| 1962 |
return True
|
| 1963 |
return False
|
| 1964 |
|
| 1965 |
+
def is_do_aux(t) -> bool:
|
| 1966 |
+
low = re.sub(r"[^a-z]", "", t.lower_)
|
| 1967 |
+
if t.lemma_ == "do":
|
| 1968 |
+
return True
|
| 1969 |
+
return low in {
|
| 1970 |
+
"do", "does", "did",
|
| 1971 |
+
"dont", "doesnt", "didnt",
|
| 1972 |
+
"don", "doesn", "didn",
|
| 1973 |
+
}
|
| 1974 |
+
|
| 1975 |
+
def is_modal(t) -> bool:
|
| 1976 |
+
return t.tag_ == "MD" or t.lemma_.lower() in MODALS or t.lower_ in MODALS
|
| 1977 |
+
|
| 1978 |
def in_bare_infinitive_complement(tok) -> bool:
|
| 1979 |
+
left = sent[: tok.idx]
|
| 1980 |
+
if _LEFT_BARE_INF.search(left):
|
| 1981 |
+
return True
|
| 1982 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1983 |
i = tok.i - 1
|
| 1984 |
while i >= 0:
|
| 1985 |
t = doc[i]
|
| 1986 |
+
if is_modal(t) or is_do_aux(t):
|
|
|
|
|
|
|
| 1987 |
return True
|
| 1988 |
+
frag = re.sub(r"[^a-z]", "", t.lower_)
|
| 1989 |
if (
|
| 1990 |
t.lower_ in MODAL_MID
|
| 1991 |
+
or frag in {"", "t", "nt", "n"}
|
| 1992 |
or t.dep_ in {"neg", "advmod", "punct"}
|
| 1993 |
or t.pos_ in {"ADV", "PART", "PUNCT", "SPACE"}
|
| 1994 |
+
or t.text in {"'", "’", "‘"}
|
| 1995 |
):
|
| 1996 |
i -= 1
|
| 1997 |
continue
|
| 1998 |
return False
|
| 1999 |
return False
|
| 2000 |
|
| 2001 |
+
def skip_target(t) -> bool:
|
| 2002 |
+
if t.tag_ == "MD":
|
| 2003 |
+
return True
|
| 2004 |
+
if is_infinitive(t):
|
| 2005 |
+
return True
|
| 2006 |
+
if in_bare_infinitive_complement(t):
|
| 2007 |
+
return True
|
| 2008 |
+
if t.lemma_ == "be" and t.lower_ in {"be", "bes", "beses"}:
|
| 2009 |
+
return True
|
| 2010 |
+
return False
|
| 2011 |
+
|
| 2012 |
def to_3sg(word: str) -> str:
|
| 2013 |
low = word.lower()
|
| 2014 |
irregular = {
|
|
|
|
| 2032 |
new = new[0].upper() + new[1:]
|
| 2033 |
return new
|
| 2034 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2035 |
target = None
|
| 2036 |
for t in doc:
|
| 2037 |
if skip_target(t):
|
|
|
|
| 2050 |
target = t
|
| 2051 |
break
|
| 2052 |
|
| 2053 |
+
out = sent
|
| 2054 |
+
if target is not None and target.lower_ not in {"is", "was", "has", "does", "be"}:
|
| 2055 |
+
new = to_3sg(target.text)
|
| 2056 |
+
out = sent[: target.idx] + new + sent[target.idx + len(target.text) :]
|
| 2057 |
|
| 2058 |
+
# Safety net: if a 3sg form still sits after do-support / a modal,
|
| 2059 |
+
# put it back to the lemma (wants→want, has→have, goes→go).
|
| 2060 |
+
doc2 = nlp(out)
|
| 2061 |
+
for t in reversed(list(doc2)):
|
| 2062 |
+
if t.lemma_ == "do" or t.tag_ == "MD":
|
| 2063 |
+
continue
|
| 2064 |
+
left = out[: t.idx]
|
| 2065 |
+
if not _LEFT_BARE_INF.search(left):
|
| 2066 |
+
continue
|
| 2067 |
+
if t.tag_ != "VBZ" and t.lower_ not in {
|
| 2068 |
+
"wants", "goes", "has", "does", "is", "lives",
|
| 2069 |
+
}:
|
| 2070 |
+
continue
|
| 2071 |
+
base = t.lemma_ if t.lemma_ and t.lemma_ != "-PRON-" else t.text
|
| 2072 |
+
if t.lower_ == "has":
|
| 2073 |
+
base = "have"
|
| 2074 |
+
elif t.lower_ == "is":
|
| 2075 |
+
base = "be"
|
| 2076 |
+
elif t.lower_ == "does":
|
| 2077 |
+
base = "do"
|
| 2078 |
+
elif t.lower_ == "goes":
|
| 2079 |
+
base = "go"
|
| 2080 |
+
elif t.lower_.endswith("s") and t.lemma_:
|
| 2081 |
+
base = t.lemma_
|
| 2082 |
+
if base.lower() == t.lower_:
|
| 2083 |
+
continue
|
| 2084 |
+
if t.text[:1].isupper():
|
| 2085 |
+
base = base[0].upper() + base[1:]
|
| 2086 |
+
out = out[: t.idx] + base + out[t.idx + len(t.text) :]
|
| 2087 |
+
return out
|
| 2088 |
###############################################################################
|
| 2089 |
|
| 2090 |
###############################################################################
|