Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 50 additions & 1 deletion src/reynir/Greynir.grammar
Original file line number Diff line number Diff line change
Expand Up @@ -1662,7 +1662,7 @@ SetningÁnF_et_p3_hk →

EinSetningÁnF/tala/pers/kyn →
Atviksliður? ÖfugurSagnliður/tala/pers/kyn
LoTengtSögn_nf/tala/kyn? ÖfugtFramhald/tala/pers/kyn*
LoTengtSögn_nf/tala/kyn? SamanburðurNl? ÖfugtFramhald/tala/pers/kyn*
# Lýsingarorð á undan sögn:
# (Ráðherrar taka þær ákvarðanir sem) nauðsynlegar eru/þykja/teljast til rækslu starfa þeirra
| LoTengtSögn_nf/tala/kyn Sögn_0/tala/pers/kyn SagnInnskotAtv?
Expand Down Expand Up @@ -2796,6 +2796,12 @@ SagnarBotn →
| Nl_ef AtvFs? so_subj_nh_ef
# (Anna telur) fólki fækka í landinu
| Nl_þgf AtvFs? so_subj_nh_þgf
# (Hún segir) mig hafa dreymt (vel)
| Nl/aukafall AtvFs? 'hafa:so'_0_nh so_subj_sagnb/aukafall ÓpSagnarBotn?
# (Hún segir) Spáni hafa mistekist (að vernda landamærin)
# (miðmyndarsögn með frumlagi í þágufalli, sbr. finítu regluna
# 'NlFrumlag_þgf ... HjSögnMM so_mm_sagnb MiðmyndarBotn?')
| Nl_þgf AtvFs? 'hafa:so'_0_nh so_mm_sagnb MiðmyndarBotn?
# (Már segir) [í grundvallaratriðum] gæta misskilnings (hjá Hannesi)
| FsAtv? so_subj_nh_ef Nl_ef
# !!! Ekki virðist þörf fyrir öfuga orðaröð í þgf eða þf
Expand Down Expand Up @@ -3743,8 +3749,17 @@ Fyrirbæri_ft/fall/kyn →

Númer →
'númer:hk' Tala_hk_nf
| NúmerTala

# Óbeygð tala í hvorugkyni nefnifalls sem auðkenni á eftir nafnorði:
# '(lögreglu)stöð tvö', 'stofa fimm', 'hlið átta', 'rás eitt'
NúmerTala →
Töluorð_et_nf_hk
| Töluorð_ft_nf_hk

$score(+8) Númer
# Velja frekar sambeygða tölu (Fjöldi) en auðkennistölu, ef báðar koma til greina
$score(-4) NúmerTala

Fjöldi_ft/fall/kyn → to_ft/fall/kyn | töl_ft/fall/kyn

Expand Down Expand Up @@ -3893,6 +3908,7 @@ NlStak_p3/tala/fall/kyn →
NlKjarni/tala/fall/kyn NlStakTagl/tala/fall/kyn?
| NlFornafn/tala/fall/kyn
| Pfn/kyn/tala/fall to/tala/fall/kyn? 'persónulega:ao'? # 'þið tvær', 'hann einn', 'hán eitt'
| Pfn/kyn/tala/fall LoEftirNl/tala/fall/kyn # '(með) hann fremstan (í fararbroddi)', '(ég hitti) hana glaða'
| LoTöluorð_ef 'konar:kk'_ef_et NlKjarni/tala/fall/kyn # 'tvenns/þrenns/ferns konar innstungur'
| Raðnr/fall/kyn NlKjarni/tala/fall/kyn Fornafn/tala/fall/kyn* # 1. verðlaunin öll, 1.-3. sætið, 10. og 12. árið
| NlStakNema/tala/fall/kyn
Expand Down Expand Up @@ -5954,6 +5970,7 @@ FsMeðFallstjórn →
# Fleiryrtar forsetningar sem eru ekki dregnar saman í Phrases.conf
| 'nær:fs'_þgf 'draga:so'_op_gm_et_p3 Nl_þgf # 'þegar nær dró/dregur jólum'
| 'beggja:fn'_hk_ef_ft 'vegna:fs'_ef Nl_ef # 'beggja vegna vegarins'
| FsVegnaEftirNl # 'sýningarinnar vegna', 'mín vegna'
| 'bera:so'_lhþt_sb_hk_nf_et "saman:ao" 'við:fs'_þf Nl_þf # borið saman við (fyrra ár)
| "fyrir:ao" "nú:ao"? 'utan:fs'_þf Nl_þf
| "innan:ao" "sem:st" 'utan:fs'_ef Nl_ef
Expand Down Expand Up @@ -5993,6 +6010,14 @@ FsMeðFallstjórn →

$score(+1) FsMeðFallstjórn

# Eignarfallsliður á undan 'vegna': 'sýningarinnar vegna',
# 'veðursins vegna', 'mín vegna'
FsVegnaEftirNl →
Nl_ef 'vegna:fs'_ef

# Þarf að vinna gegn rangri greiningu á 'vegna' sem lýsingarorði
$score(+4) FsVegnaEftirNl

MiðaðVið →
"miðað:so" 'við:fs'_þf
| 'miðað_við:fs'_þf # Samtals eigið fé m.v. síðustu tölur ...
Expand Down Expand Up @@ -7671,6 +7696,30 @@ VillaEndingIR →
$tag(error) VillaEndingIR
$score(-999) VillaEndingIR

# Regla fyrir villu þar sem lýsingarorð (oft lýsingarháttur þátíðar)
# með fallstýrðu andlagi stendur á eftir nafnlið en sambeygist honum
# ekki í falli, t.d. 'móðurfélag fleiri félaga tengdum rekstri
# Morgunblaðsins' (rétt: 'tengdra'); villan stafar oft af aðlöðun
# að falli andlagsins ('félögum tengdum rekstri')

LoEftirNl/tala/fall/kyn →
> VillaLoEftirNlMeðAndlagi/fall/tala/kyn

VillaLoEftirNlMeðAndlagi_nf/tala/kyn →
LoEftirNlMeðAndlagi/fallxnf/tala/kyn

VillaLoEftirNlMeðAndlagi_þf/tala/kyn →
LoEftirNlMeðAndlagi/fallxþf/tala/kyn

VillaLoEftirNlMeðAndlagi_þgf/tala/kyn →
LoEftirNlMeðAndlagi/fallxþgf/tala/kyn

VillaLoEftirNlMeðAndlagi_ef/tala/kyn →
LoEftirNlMeðAndlagi/fallxef/tala/kyn

$tag(error) VillaLoEftirNlMeðAndlagi/fall/tala/kyn
$score(-999) VillaLoEftirNlMeðAndlagi/fall/tala/kyn

# Orð sem endar á -ana í þolfalli notað í stað eignarfalls:
# 'niðurstaða þingflokkana', 'hattar karlana'

Expand Down
20 changes: 19 additions & 1 deletion src/reynir/bintokenizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1259,6 +1259,24 @@ def _compatible(pn: PersonNameTuple, npn: PersonNameTuple) -> bool:
return True


def _add_uninflected_genitive(gn: List[PersonNameTuple]) -> List[PersonNameTuple]:
"""If a name appears in the same form in the nominative, accusative
and dative cases, it is a non-inflecting (foreign) name. Such names
are also used unmodified in genitive position ('Samtök Paul Watson',
'bók Mary Robinson'), so we add the genitive case to the list of
possible interpretations."""
seen: Dict[Tuple[str, Optional[str]], Set[str]] = defaultdict(set)
for pn in gn:
if pn.case:
seen[(pn.name, pn.gender)].add(pn.case)
additions = [
PersonNameTuple(name=name, gender=gender, case="ef")
for (name, gender), cases in seen.items()
if "ef" not in cases and cases >= {"nf", "þf", "þgf"}
]
return gn + additions if additions else gn


def parse_phrases_2(
token_stream: TokenIterator, token_ctor: TokenConstructor, auto_uppercase: bool
) -> TokenIterator:
Expand Down Expand Up @@ -1604,7 +1622,7 @@ def eat_surnames(
if not weak:
# Return a person token with the accumulated name
# and the intersected set of possible cases
token = token_ctor.Person(w, gn)
token = token_ctor.Person(w, _add_uninflected_genitive(gn))
token.original = namespan

# Yield the current token and advance to the lookahead
Expand Down
2 changes: 1 addition & 1 deletion src/reynir/config/Phrases.conf
Original file line number Diff line number Diff line change
Expand Up @@ -1573,7 +1573,7 @@ meaning = fs frasi -
"láta* slag standa" so kk so
"láta* þess getið" so pfn so
"vísa* málinu" so hk
"vera* bent á" so so ao
"vera* bent á" so so fs/ao
"um síðustu áramót" fs lo hk
"um síðustu mánaðamót" fs lo hk
"um sig" fs *
Expand Down
179 changes: 179 additions & 0 deletions test/test_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -2245,6 +2245,178 @@ def test_aukafall(r):
assert s and s.tree


def test_impersonal_passive_prep(r):
"""The 'vera* bent á' ambiguous phrase must retain the preposition
meaning of 'á', so that 'er bent á' + Nl parses"""
s = r.parse_single("Í skýrslunni er bent á kostina.")
assert s and s.tree
assert (
s.tree.flat_with_all_variants
== "S0 S-MAIN IP PP P fs_þgf /P NP no_et_gr_kvk_þgf /NP /PP "
"VP VP-AUX so_et_fh_gm_nt_p3 /VP-AUX VP so_gm_sagnb /VP "
"PP P fs_þf /P NP no_ft_gr_kk_þf /NP /PP /VP /IP /S-MAIN p /S0"
)
s = r.parse_single("Í skýrslunni er bent á kosti og galla upptöku evru.")
assert s and s.tree
# 'bent á' followed by a subordinate clause must still work
s = r.parse_single("Í skýrslunni er bent á að vandinn sé mikill.")
assert s and s.tree
s = r.parse_single(
"Í nýrri ársskýrslu sjóðsins um Ísland er bent á kosti og galla "
"upptöku evru og varað við því að verðtrygging í íslensku "
"efnahagslífi geti viðhaldið verðbólgu."
)
assert s and s.tree


def test_uninflected_genitive_names(r):
"""Non-inflecting (foreign) person names, i.e. names having identical
forms in nf/þf/þgf, should also be accepted in genitive contexts"""
s = r.parse_single("Samtök Paul Watson mótmæltu hvalveiðum.")
assert s and s.tree
assert (
s.tree.flat_with_all_variants
== "S0 S-MAIN IP NP-SUBJ no_ft_hk_nf NP-POSS person_ef_kk person_ef_kk "
"/NP-POSS /NP-SUBJ VP VP so_1_þgf_fh_ft_gm_p3_þt /VP "
"NP-OBJ no_ft_kvk_þgf /NP-OBJ /VP /IP /S-MAIN p /S0"
)
s = r.parse_single("Ég las bók John Lennon.")
assert s and s.tree
s = r.parse_single(
"Samtök Paul Watson leiða líkur að því að þau hafi með aðgerðum "
"sínum frá því að hvalveiðitímabilið hófst bjargað lífi "
"allt að þrjátíu langreyða."
)
assert s and s.tree
# Inflecting Icelandic names must not gain a genitive interpretation
s = r.parse_single("Samtök Guðmundur Jónsson eru góð.")
assert s.tree is None
# Token-level check of person name cases
from reynir.bintokenizer import tokenize

toks = [t for t in tokenize("Samtök Paul Watson mótmæltu hvalveiðum.")]
pw = next(t for t in toks if t.txt == "Paul Watson")
assert set(pn.case for pn in pw.person_names) == {"nf", "þf", "þgf", "ef"}
toks = [t for t in tokenize("Þarna gengur Jón.")]
jon = next(t for t in toks if t.txt == "Jón")
assert "ef" not in set(pn.case for pn in jon.person_names)


def test_sem_role_relative_clause(r):
"""A 'sem' + Nl_nf role complement ('starfar sem sérfræðingur')
must be allowed inside a subject-gap relative clause"""
s = r.parse_single("Konan, sem starfar sem sérfræðingur hjá bankanum, er glöð.")
assert s and s.tree
assert (
s.tree.flat_with_all_variants
== "S0 S-MAIN IP NP-SUBJ no_et_gr_kvk_nf p CP-REL C stt /C "
"IP VP so_0_et_fh_gm_nt_p3 /VP CP-ADV-CMP C st /C NP no_et_kk_nf "
"PP P fs_þgf /P NP no_et_gr_kk_þgf /NP /PP /NP /CP-ADV-CMP /IP "
"/CP-REL p /NP-SUBJ VP VP-AUX so_et_fh_gm_nt_p3 /VP-AUX "
"NP-PRD lo_et_kvk_nf_sb /NP-PRD /VP /IP /S-MAIN p /S0"
)
s = r.parse_single(
"Doktor Stefán Ólafsson, sem starfar sem sérfræðingur hjá Eflingu, "
"gefur ekki mikið fyrir myljandi hagnað bankanna."
)
assert s and s.tree


def test_oblique_subject_infinitive(r):
"""Oblique subject + perfect infinitive ('hafa' + supine) in the
complement of segja/telja: 'segir Spáni hafa mistekist'"""
s = r.parse_single("Hún segir Spáni hafa mistekist að vernda landamærin.")
assert s and s.tree
assert (
s.tree.flat_with_all_variants
== "S0 S-MAIN IP NP-SUBJ pfn_et_kvk_nf_p3 /NP-SUBJ VP VP "
"so_1_þf_et_fh_gm_nt_p3 /VP IP NP no_et_kk_þgf /NP VP so_0_gm_nh /VP "
"VP so_mm_sagnb /VP IP-INF TO nhm /TO VP VP so_1_þf_gm_nh /VP "
"NP-OBJ no_ft_gr_hk_þf /NP-OBJ /VP /IP-INF /IP /VP /IP /S-MAIN p /S0"
)
s = r.parse_single("Hún segir mig hafa dreymt vel.")
assert s and s.tree
s = r.parse_single("Hún telur Spáni hafa mistekist.")
assert s and s.tree
s = r.parse_single(
"Hún segir Spáni hafa mistekist að vernda ytri landamæri "
"Schengen-svæðisins gegn innrás."
)
assert s and s.tree


def test_postposed_vegna(r):
"""A genitive Nl preceding 'vegna' ('sýningarinnar vegna')
should parse as a prepositional phrase"""
s = r.parse_single("Sýningarinnar vegna ákvað hann þetta.")
assert s and s.tree
assert (
s.tree.flat_with_all_variants
== "S0 S-MAIN IP PP NP no_ef_et_gr_kvk /NP P fs_ef /P /PP "
"VP VP so_1_þf_et_fh_gm_p3_þt /VP NP-SUBJ pfn_et_kk_nf_p3 /NP-SUBJ "
"NP-OBJ fn_et_hk_þf /NP-OBJ /VP /IP /S-MAIN p /S0"
)
s = r.parse_single("Hann gerði þetta mín vegna.")
assert s and s.tree
s = r.parse_single("Hann gerði þetta veðursins vegna.")
assert s and s.tree
# Normal (preposed) order must be unaffected
s = r.parse_single("Hann gerði þetta vegna veðursins.")
assert s and s.tree
s = r.parse_single("Trén standa beggja vegna vegarins.")
assert s and s.tree
s = r.parse_single(
"Umboðsmaður Boy George sagði að sýningarinnar vegna hefði hann "
"ákveðið að söngvarinn yrði ekki með í henni."
)
assert s and s.tree


def test_pronoun_postposed_adjective(r):
"""A personal pronoun followed by an agreeing adjective phrase
should form a noun phrase: '(með) hann fremstan (í fararbroddi)'"""
s = r.parse_single("Með hann fremstan í fararbroddi vann liðið leikinn.")
assert s and s.tree
assert (
s.tree.flat_with_all_variants
== "S0 S-MAIN IP PP P fs_þf /P NP pfn_et_kk_p3_þf lo_esb_et_kk_þf "
"PP P fs_þgf /P NP no_et_kk_þgf /NP /PP /NP /PP "
"VP VP so_1_þf_et_fh_gm_p3_þt /VP NP-SUBJ no_et_gr_hk_nf /NP-SUBJ "
"NP-OBJ no_et_gr_kk_þf /NP-OBJ /VP /IP /S-MAIN p /S0"
)
s = r.parse_single("Ég hitti hana glaða.")
assert s and s.tree
s = r.parse_single(
"Með hann fremstan í fararbroddi tókst liði Levante "
"að bjarga sér frá falli."
)
assert s and s.tree


def test_designation_numeral(r) -> None:
"""An uninflected neuter nominative numeral used as a designation
after a noun: '(lögreglu)stöð tvö', 'stofa fimm'"""
s = r.parse_single("Hann býr í umdæmi lögreglustöðvar tvö.")
assert s and s.tree
assert (
s.tree.flat_with_all_variants
== "S0 S-MAIN IP NP-SUBJ pfn_et_kk_nf_p3 /NP-SUBJ VP VP so_0_et_fh_gm_nt_p3 /VP "
"PP P fs_þgf /P NP no_et_hk_þgf NP-POSS no_ef_et_kvk to_ft_hk_nf "
"/NP-POSS /NP /PP /VP /IP /S-MAIN p /S0"
)
s = r.parse_single("Hann býr í stofu fimm.")
assert s and s.tree
s = r.parse_single(
"Það átti sér stað í umdæmi lögreglustöðvar tvö, "
"sem sér um Hafnarfjörð og Garðabæ."
)
assert s and s.tree
# An agreeing numeral must still be preferred where possible
s = r.parse_single("Ég sá mennina þrjá.")
assert s and s.tree
assert "to_ft_kk_þf" in s.tree.flat_with_all_variants


if __name__ == "__main__":
# When invoked as a main module, do a verbose test
from reynir import Greynir
Expand Down Expand Up @@ -2296,4 +2468,11 @@ def test_aukafall(r):
print(e)
test_foreign(g)
test_aukafall(g)
test_impersonal_passive_prep(g)
test_uninflected_genitive_names(g)
test_sem_role_relative_clause(g)
test_oblique_subject_infinitive(g)
test_postposed_vegna(g)
test_pronoun_postposed_adjective(g)
test_designation_numeral(g)
g.__class__.cleanup()
Loading