From 0f77ea9623b2204c7627310b453797a52219bd6f Mon Sep 17 00:00:00 2001 From: vthorsteinsson Date: Mon, 7 Sep 2026 17:58:35 +0000 Subject: [PATCH] =?UTF-8?q?Parse=20genitive-subject=20kenna,=20fronted=20"?= =?UTF-8?q?er=20X=20a=C3=B0=20finna",=20infinitive=20comma=20lists?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three constructions that failed to parse: - "Í Paradísarskjölunum kennir ýmissa grasa": register 'kenna' as an impersonal verb with a genitive subject (subject = ef in Verbs.conf). While at it, close a pre-existing hole in BIN_Parser.verb_matches: a genitive subject was combined with the verb's ordinary object frames, admitting e.g. "*Í bókinni gætir Páls misskilning". Genitive-subject impersonals are intransitive idioms. - "Þar af leiðandi er tiltölulega fáa Íslendinga að finna í skjölunum": the "X_þf er að finna" rule only allowed the object in first position. Add a variant with a fronted adverbial, prepositional phrase or expletive 'það' (new nonterminal FsAtvEðaLeppur). - "... hæfni til að skilja, nota, meta, ígrunda og ástunda lestur texta": infinitives could share an object only when joined by og/eða. Allow comma-separated verbs in the shared-object chain (OgNhSögn_*) and after modal verbs (OgSögn_nh, Sögn_1_nh), but only when a verb with og/eða closes the list. Also fixes "Hann vill lesa, skrifa og reikna". Heavy parse tests run ~1.5% slower with the new rules. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01Dbj8bT51itpXbsxLjfLuce --- src/reynir/Greynir.grammar | 27 ++++++++++ src/reynir/binparser.py | 7 +++ src/reynir/config/Verbs.conf | 1 + test/test_parse.py | 99 ++++++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+) diff --git a/src/reynir/Greynir.grammar b/src/reynir/Greynir.grammar index 1bee8c8..ae1cce5 100644 --- a/src/reynir/Greynir.grammar +++ b/src/reynir/Greynir.grammar @@ -1474,6 +1474,10 @@ SetningAukafall → # Nöfn ráðherra var [ekki] að finna [í Panamaskjölunum] | NlBeintAndlag_þf 'vera:so'_0_gm_fh_p3_et FsAtv? Nhm 'finna:so'_0_gm_nh FsAtv? + # Þar af leiðandi/Í skjölunum er [ekki] tiltölulega fáa Íslendinga að finna [í skjölunum] + # Það er [ekki] marga Íslendinga að finna í skjölunum + | FsAtvEðaLeppur 'vera:so'_0_gm_fh_p3_et FsAtv? NlBeintAndlag_þf Nhm 'finna:so'_0_gm_nh FsAtv? + # Aukafallssetningar sem eru mjög líklega rétt greindar og fá þar # af leiðandi plús-skor í stað mínuss SetningAukafallForgangur → @@ -1895,6 +1899,9 @@ OgSögn_nh/tala/kyn → | SagnInnskot? ViðurkenningarNh | SagnInnskot? "," Aðaltenging FsAtv? EinSögn_nh/tala/kyn FsAtvKomma? | SagnInnskot? KommaViðurkenningarNh + # Upptalning: (Hann vill) lesa, skrifa og reikna + # Komma er aðeins leyfð ef sögn með aðaltengingu lokar upptalningunni + | "," EinSögn_nh/tala/kyn OgSögn_nh/tala/kyn # Þá segist hún styðja trúfrelsi, þrátt fyrir að vera andsnúin moskubyggingum @@ -2604,6 +2611,8 @@ NlEnginnAndlag/fall → Sögn_1_nh → So_1_nh/fall SagnÖgn? FsRunaInnskot? NlBeintAndlag/fall + # (Hann vill) skilja, nota og meta textann (sagnirnar deila andlagi) + | So_1_nh/fall OgNhSögn/fall+ SagnÖgn? FsRunaInnskot? NlBeintAndlag/fall # sjá/láta/'horfa á' Pál breyta [í snarheitum] sér (í kött) | So_1_þf_nh Nl_þf So_1_nh/fall FsRunaInnskot? Nl/fall @@ -3551,30 +3560,44 @@ $score(+8) NhSögnHafaGetaFá # Samtengingar sagna +# Sagnir í nafnhætti sem deila andlagi: 'að skilja og nota texta'. +# Kommuaðskildar sagnir eru leyfðar í upptalningu, en aðeins ef sögn með +# 'og'/'eða' lokar upptalningunni: 'að skilja, nota, meta og ígrunda texta' OgNhSögn → OgEðaHeldur so_0_nh so_0_gm_vh_p3_et? OgNhSögn_þf → OgEðaHeldur so_1_þf_nh so_0_gm_vh_p3_et? + | "," so_1_þf_nh so_0_gm_vh_p3_et? OgNhSögn_þf OgNhSögn_þgf → OgEðaHeldur so_1_þgf_nh so_0_gm_vh_p3_et? + | "," so_1_þgf_nh so_0_gm_vh_p3_et? OgNhSögn_þgf OgNhSögn_ef → OgEðaHeldur so_1_ef_nh so_0_gm_vh_p3_et? + | "," so_1_ef_nh so_0_gm_vh_p3_et? OgNhSögn_ef OgNhSögn_nf → OgEðaHeldur so_1_nf_nh so_0_gm_vh_p3_et? + | "," so_1_nf_nh so_0_gm_vh_p3_et? OgNhSögn_nf OgNhSögn_þf_þf → OgEðaHeldur so_2_þf_þf_nh so_0_gm_vh_p3_et? + | "," so_2_þf_þf_nh so_0_gm_vh_p3_et? OgNhSögn_þf_þf OgNhSögn_þf_þgf → OgEðaHeldur so_2_þf_þgf_nh so_0_gm_vh_p3_et? + | "," so_2_þf_þgf_nh so_0_gm_vh_p3_et? OgNhSögn_þf_þgf OgNhSögn_þf_ef → OgEðaHeldur so_2_þf_ef_nh so_0_gm_vh_p3_et? + | "," so_2_þf_ef_nh so_0_gm_vh_p3_et? OgNhSögn_þf_ef OgNhSögn_þgf_nf → OgEðaHeldur so_2_þgf_nf_nh so_0_gm_vh_p3_et? + | "," so_2_þgf_nf_nh so_0_gm_vh_p3_et? OgNhSögn_þgf_nf OgNhSögn_þgf_þf → OgEðaHeldur so_2_þgf_þf_nh so_0_gm_vh_p3_et? + | "," so_2_þgf_þf_nh so_0_gm_vh_p3_et? OgNhSögn_þgf_þf OgNhSögn_þgf_þgf → OgEðaHeldur so_2_þgf_þgf_nh so_0_gm_vh_p3_et? + | "," so_2_þgf_þgf_nh so_0_gm_vh_p3_et? OgNhSögn_þgf_þgf OgNhSögn_þgf_ef → OgEðaHeldur so_2_þgf_ef_nh so_0_gm_vh_p3_et? + | "," so_2_þgf_ef_nh so_0_gm_vh_p3_et? OgNhSögn_þgf_ef # Gefa til kynna hvar lesa á upp sagnir til að nota í # tengingu sagna og forsetninga @@ -3604,6 +3627,10 @@ NlFrumlagÞað → 'það:pfn'_hk_nf_et # Hafa sérstakan hnút fyrir frumlagslepp (NP-ES) NlFrumlagLeppur → 'það:pfn'_hk_nf_et +# Setningarfremsti liður sem er annaðhvort atviksliður/forsetningarliður +# eða frumlagsleppur: 'Í skjölunum er ...' / 'Það er ...' +FsAtvEðaLeppur → FsAtv | NlFrumlagLeppur + NlAndlagÞað/fall → 'það:pfn'_hk_et/fall SkýringarsetningFrumlag → NlSkýringarsetning diff --git a/src/reynir/binparser.py b/src/reynir/binparser.py index ed73351..c0bf3ff 100644 --- a/src/reynir/binparser.py +++ b/src/reynir/binparser.py @@ -1041,6 +1041,13 @@ def verb_matches(cls, verb: str, terminal: "BIN_Terminal", form: str) -> bool: assert nargs == 1 if nargs != 1: return False + if terminal.variant(-1) == "ef": + # Verbs with a genitive subject ('misskilnings gætir', + # 'þar kennir ýmissa grasa') are intransitive idioms; + # don't combine the genitive subject with the verb's + # ordinary object frames ('gæta e-s', 'kenna e-ð'), which + # would admit e.g. '*Í bókinni gætir ýmis misskilnings' + return False # Check whether the verb allows a single argument # in the case indicated in the terminal (second variant, # immediately following the nargs) diff --git a/src/reynir/config/Verbs.conf b/src/reynir/config/Verbs.conf index 546a62a..626766b 100644 --- a/src/reynir/config/Verbs.conf +++ b/src/reynir/config/Verbs.conf @@ -15334,6 +15334,7 @@ verkja subject = ef gæta # 'Misskilnings gætir' +kenna # 'Þar kennir ýmissa/margra grasa' # Sagnir sem geta staðið án frumlags # og viðfangs, þ.e. þar sem frumlagið diff --git a/test/test_parse.py b/test/test_parse.py index 705a3a2..1bf39b1 100644 --- a/test/test_parse.py +++ b/test/test_parse.py @@ -2885,3 +2885,102 @@ def test_never_winning_constructions(r) -> None: test_sagdur_hafa(g) test_never_winning_constructions(g) g.__class__.cleanup() + + +def test_genitive_subject_kenna(r): + """'kenna' as an impersonal verb with a genitive subject: + 'Þar kennir ýmissa grasa'""" + s = r.parse_single("Í Paradísarskjölunum kennir ýmissa grasa.") + assert s and s.tree + assert s.tree.flat == ( + "S0 S-MAIN IP PP P fs_þgf /P NP no_ft_þgf_kvk /NP /PP " + "VP VP so_subj_op_ef /VP NP-SUBJ lo_ef_ft_hk no_ft_ef_hk /NP-SUBJ /VP " + "/IP /S-MAIN p /S0" + ) + assert s.tree.verbs == ["kenna"] + s = r.parse_single("Þar kennir margra grasa.") + assert s and s.tree + assert s.tree.verbs == ["kenna"] + assert s.tree.S.IP.VP.NP_SUBJ.text == "margra grasa" + # A genitive subject must not combine with the verb's object frames + # ('kenna e-ð', 'gæta e-s') + s = r.parse_single("Í bókinni kennir Páls grös.") + assert s.tree is None + s = r.parse_single("Í bókinni gætir Páls misskilning.") + assert s.tree is None + s = r.parse_single("Misskilnings gætir í bókinni.") + assert s and s.tree + assert s.tree.verbs == ["gæta"] + # Wrong case or number on the subject + s = r.parse_single("Í bókinni kennir ýmsum grösum.") + assert s.tree is None + s = r.parse_single("Í bókinni kenna ýmissa grasa.") + assert s.tree is None + # Ordinary transitive uses of 'kenna' must be unaffected + s = r.parse_single("Hann kenndi mér íslensku.") + assert s and s.tree + assert s.tree.verbs == ["kenna"] + assert s.tree.S.IP.NP_SUBJ.text == "Hann" + + +def test_er_að_finna(r): + """The 'X_þf er að finna' construction with a fronted adverbial, + prepositional phrase or expletive subject instead of the object""" + s = r.parse_single( + "Þar af leiðandi er tiltölulega fáa Íslendinga að finna í skjölunum." + ) + assert s and s.tree + assert s.tree.flat == ( + "S0 S-MAIN IP ADVP ao ao ao /ADVP VP so_0_gm_fh_p3_et /VP " + "NP-OBJ eo lo_þf_ft_kk no_ft_þf_kk /NP-OBJ TO nhm /TO " + "VP so_0_gm_nh /VP PP P fs_þgf /P NP no_ft_þgf_kvk /NP /PP " + "/IP /S-MAIN p /S0" + ) + assert s.tree.S.IP.NP_OBJ.text == "tiltölulega fáa Íslendinga" + s = r.parse_single("Í skjölunum er marga Íslendinga að finna.") + assert s and s.tree + assert s.tree.S.IP.NP_OBJ.text == "marga Íslendinga" + s = r.parse_single("Það er fáa Íslendinga að finna í skjölunum.") + assert s and s.tree + assert s.tree.S.IP.NP_ES is not None + assert s.tree.S.IP.NP_OBJ.text == "fáa Íslendinga" + # The original object-first order must still work + s = r.parse_single("Nöfn ráðherra var ekki að finna í Panamaskjölunum.") + assert s and s.tree + assert s.tree.S.IP.NP_OBJ.text == "Nöfn ráðherra" + + +def test_infinitive_list_shared_object(r): + """Comma-separated lists of infinitives sharing a single object, + both after 'til að'/'að' and directly after a modal verb""" + s = r.parse_single( + "Lesskilningur er skilgreindur sem hæfni til að skilja, nota, meta, " + "ígrunda og ástunda lestur texta í þeim tilgangi að ná markmiðum, " + "þroska þekkingu og hæfileika og taka þátt í samfélaginu." + ) + assert s and s.tree + inf = s.tree.S.IP.CP_ADV_CMP.NP.PP.IP_INF + assert inf.VP.NP_OBJ.text == "lestur texta" + assert [c.text for c in inf.VP.children if c.tag == "VP"] == [ + "skilja", + "nota", + "meta", + "ígrunda", + "ástunda", + ] + s = r.parse_single("Hann ætlar að skilja, nota og meta texta.") + assert s and s.tree + assert s.tree.S.IP.VP.IP_INF.VP.NP_OBJ.text == "texta" + # Directly after a modal verb + s = r.parse_single("Hann vill lesa, skrifa og reikna.") + assert s and s.tree + assert s.tree.verbs == ["vilja", "lesa", "skrifa", "reikna"] + s = r.parse_single("Hann vill skilja, nota, meta, ígrunda og ástunda lestur texta.") + assert s and s.tree + assert s.tree.S.IP.VP.NP_OBJ.text == "lestur texta" + assert s.tree.verbs == ["vilja", "skilja", "nota", "meta", "ígrunda", "ástunda"] + # A comma list must be closed by a conjunction + s = r.parse_single("Hann ætlar að skilja, nota, meta texta.") + assert s.tree is None + s = r.parse_single("Hann vill lesa, skrifa.") + assert s.tree is None