Przejdź do treści

olski.walencja

Co słowo bierze: jeden leksykon dla każdego, kto o ramę pyta.

Rama jest faktem o słowie, a nie o kierunku, w którym się tego słowa używa, więc wszyscy, którzy o nią pytają, czytają ten sam plik. Druga kopia tej wiedzy rozjeżdża się z pierwszą, a rozjazd widać dopiero na zdaniu, którego jeden kierunek nie przyjmuje, a drugi je wypuszcza; wywód trzyma docs/design-notes.md.

Wspólny jest leksykon, a nie odpowiedź, bo pytający pytają o co innego. Parser pyta o klasę: które lematy dzielą ramę, bo z klasy powstaje produkcja, a nie z lematu. Skład pyta o jeden lemat i dostaje zbiór pozycji (rama): które z nich ten czasownik bierze, bo tyle wystarcza, żeby powiedzieć o drzewie, czy on weźmie to, co autor w nim postawił. Warstwa rozstrzygająca pyta o jeden lemat i o jedną pozycję: czy rama tego słowa żąda tego przyimka.

Wspólny jest też plik, a nie każde zdanie, które on mówi. Biernik, celownik i dopełniacz czytają oba kierunki, zdanie podrzędne sam skład, a o bezokoliczniku plik mówi dwoma zdaniami i każdy czyta swoje. Skład czyta węższe, o kontroli podmiotu, bo jest ono po tamtej stronie jedyną obroną przed drzewem żądającym bezokolicznika od czasownika, który go nie bierze. Parser czyta szersze i czyta je przy czasowniku zwrotnym: tam pozycja bezokolicznikowa dokłada odczytanie drugie zdaniu, w którym cząstka stoi między dwoma czasownikami, więc zawężenie kupuje jednoznaczność, zamiast kosztować zdanie. Po stronie niezwrotnej zmierzono je i nie kupiło ani jednej; liczby trzyma docs/subset.md. Pozycję zdania podrzędnego gramatyka podzbioru ma, więc jest to ta sama decyzja co przy bezokoliczniku niezwrotnym, a nie brak pozycji.

Przyimki czyta trzeci odbiorca i żadnej produkcji nie rusza: świadek ramowy w olski/rozstrzyganie.py pyta o nie po obu stronach spornego wyrażenia przyimkowego. Gramatyka ich nie czyta, bo wyrażenie przyimkowe przyłącza się u olskiego wszędzie, gdzie polszczyzna je stawia, a wybór miejsca należy do czytelnika (docs/subset.md#przyjąć-koszt-to-znaczy-dać-oba-czytania-wszędzie).

Ręcznie stoi w tym leksykonie jeden wpis i jest nim kopula (KOPULA). Walenty mówi o być to samo, co o każdym innym lemacie, a rama kopuli mówi o narzędniku, którego rama domyślna nie ma, więc kierunek biorący ten plik bez odjęcia kopuli wypuszczałby Program jest ustawienia. Odjęcie stoi tutaj i dlatego stoi raz, a nie po jednym na kierunek; czym rama kopuli jest dla gramatyki, mówi olski/subset/rama.py.

Wpisy rozdziela klasa słowa, bo jeden lemat bywa kilkoma słowami naraz. Forma z cząstką się jest innym czasownikiem — otwierać bierze dopełnienie w bierniku, a otwierać się go nie bierze, i Morfeusz daje obu ten sam lemat — a rzeczownik jest trzecim słowem i ma własną ramę. Leksykon trzymany pod samym lematem zlewałby te słowa w jedno i kłamał o każdym z nich.

Plik jest generowany z Walentego przez harness/walenty.py, który mówi, co stamtąd bierze, a czego nie, a docs/subset.md wywodzi, czym taki leksykon jest, a czym nie jest.

LEKSYKON = Path(__file__).parent / 'leksykon.txt' module-attribute

NIE_BIERZE_BIERNIKA = 'nie_bierze_biernika' module-attribute

BIERZE_BEZOKOLICZNIK = 'bierze_bezokolicznik' module-attribute

BIERZE_BEZOKOLICZNIK_PODMIOTU = 'bierze_bezokolicznik_podmiotu' module-attribute

BIERZE_ZDANIE = 'bierze_zdanie' module-attribute

BIERZE_CELOWNIK = 'bierze_celownik' module-attribute

BIERZE_DOPEŁNIACZ = 'bierze_dopełniacz' module-attribute

BIERZE_CELOWNIK_PRZY_WYPEŁNIENIU = 'bierze_celownik_przy_wypełnieniu' module-attribute

CZASOWNIK = 'czasownik' module-attribute

CZASOWNIK_ZWROTNY = 'czasownik się' module-attribute

RZECZOWNIK = 'rzeczownik' module-attribute

KOPULA = frozenset({'być', 'bywać', 'zostać', 'zostawać', 'pozostać', 'pozostawać'}) module-attribute

BIERNIK = 'acc' module-attribute

CELOWNIK = 'dat' module-attribute

DOPEŁNIACZ = 'gen' module-attribute

ORZECZNIK = 'inst' module-attribute

BEZOKOLICZNIK = 'inf' module-attribute

ZDANIE_PODRZĘDNE = 'comp' module-attribute

PYTANIE_ZALEŻNE = 'int' module-attribute

PODMIOT = 'subj' module-attribute

BEZ_BIERNIKA = _lematy(NIE_BIERZE_BIERNIKA, CZASOWNIK) module-attribute

BEZ_BIERNIKA_ZWROTNE = _lematy(NIE_BIERZE_BIERNIKA, CZASOWNIK_ZWROTNY) module-attribute

Z_CELOWNIKIEM = _lematy(BIERZE_CELOWNIK, CZASOWNIK) module-attribute

Z_CELOWNIKIEM_ZWROTNE = _lematy(BIERZE_CELOWNIK, CZASOWNIK_ZWROTNY) module-attribute

Z_DOPEŁNIACZEM = _lematy(BIERZE_DOPEŁNIACZ, CZASOWNIK) module-attribute

Z_DOPEŁNIACZEM_ZWROTNE = _lematy(BIERZE_DOPEŁNIACZ, CZASOWNIK_ZWROTNY) module-attribute

Z_CELOWNIKIEM_PRZY_WYPEŁNIENIU = _lematy(BIERZE_CELOWNIK_PRZY_WYPEŁNIENIU, CZASOWNIK) module-attribute

Z_CELOWNIKIEM_PRZY_WYPEŁNIENIU_ZWROTNE = _lematy(BIERZE_CELOWNIK_PRZY_WYPEŁNIENIU, CZASOWNIK_ZWROTNY) module-attribute

Z_BEZOKOLICZNIKIEM_ZWROTNE = _lematy(BIERZE_BEZOKOLICZNIK, CZASOWNIK_ZWROTNY) module-attribute

Z_BEZOKOLICZNIKIEM_PODMIOTU = _lematy(BIERZE_BEZOKOLICZNIK_PODMIOTU, CZASOWNIK) module-attribute

ZE_ZDANIEM = _lematy(BIERZE_ZDANIE, CZASOWNIK) module-attribute

RAMA_KOPULI = frozenset({ORZECZNIK}) module-attribute

POZYCJE_LEKSYKONU = ((CELOWNIK, Z_CELOWNIKIEM), (DOPEŁNIACZ, Z_DOPEŁNIACZEM), (BEZOKOLICZNIK, Z_BEZOKOLICZNIKIEM_PODMIOTU), (ZDANIE_PODRZĘDNE, ZE_ZDANIEM)) module-attribute

Wpis

Bases: NamedTuple

Co leksykon mówi o jednym słowie.

Source code in olski/walencja.py
124
125
126
127
128
129
130
class Wpis(NamedTuple):
    """Co leksykon mówi o jednym słowie."""

    #: Zdania orzeczone o tym słowie, każde napisem wypisanym wyżej.
    zdania: frozenset[str]
    #: Przyimki, których żąda rama tego słowa.
    przyimki: frozenset[str]

zdania instance-attribute

przyimki instance-attribute

przyimki_rzeczownika(lemat)

Przyimki, których żąda rama rzeczownika o tym lemacie.

Zbiór pusty znaczy dwie rzeczy naraz, a świadek ramowy obu daje tę samą odpowiedź, czyli milczenie: albo Walenty daje temu rzeczownikowi ramę bez pozycji przyimkowej, albo nie daje mu ramy wcale. Plik rzeczownikowy Walentego wylicza dwa tysiące lematów, więc drugie zdarza się częściej, i to ono ogranicza zasięg tego świadka; docs/rozstrzyganie.md liczy, ile z tego wychodzi.

Source code in olski/walencja.py
209
210
211
212
213
214
215
216
217
218
219
220
221
def przyimki_rzeczownika(lemat: str) -> frozenset[str]:
    """Przyimki, których żąda rama rzeczownika o tym lemacie.

    Zbiór pusty znaczy dwie rzeczy naraz,
    a świadek ramowy obu daje tę samą odpowiedź, czyli milczenie:
    albo Walenty daje temu rzeczownikowi ramę bez pozycji przyimkowej,
    albo nie daje mu ramy wcale.
    Plik rzeczownikowy Walentego wylicza dwa tysiące lematów,
    więc drugie zdarza się częściej,
    i to ono ogranicza zasięg tego świadka;
    docs/rozstrzyganie.md liczy, ile z tego wychodzi.
    """
    return _przyimki(lemat, RZECZOWNIK)

przyimki_czasownika(lemat)

Przyimki, których żąda rama czasownika o tym lemacie, z cząstką się i bez niej.

Obie klasy naraz, bo pytający ma formę czasownikową, a nie zdanie o tym, czy cząstka przy niej stoi: Przyłączenie w olski/parse/podsumowanie.py niesie same głowy gospodarzy. Suma jest tu stroną bezpieczną, bo tego zbioru świadek ramowy używa jako weta: przyimek żądany przez którekolwiek z tych dwóch słów kończy się milczeniem, a nie wskazaniem.

Source code in olski/walencja.py
224
225
226
227
228
229
230
231
232
233
234
def przyimki_czasownika(lemat: str) -> frozenset[str]:
    """Przyimki, których żąda rama czasownika o tym lemacie, z cząstką ``się`` i bez niej.

    Obie klasy naraz, bo pytający ma formę czasownikową,
    a nie zdanie o tym, czy cząstka przy niej stoi:
    ``Przyłączenie`` w ``olski/parse/podsumowanie.py`` niesie same głowy gospodarzy.
    Suma jest tu stroną bezpieczną, bo tego zbioru świadek ramowy używa jako weta:
    przyimek żądany przez którekolwiek z tych dwóch słów
    kończy się milczeniem, a nie wskazaniem.
    """
    return _przyimki(lemat, CZASOWNIK) | _przyimki(lemat, CZASOWNIK_ZWROTNY)

rama(lemat)

Pozycje, które ten czasownik bierze, czyli rama widziana przez skład.

Zbiorem, a nie pytaniem na pozycję, bo drzewo żąda tylu pozycji, ile w nim stanęło: pytań byłoby po jednym na pozycję, a każde z nich stoi u pytającego osobną gałęzią, więc lista rośnie wtedy w dwóch miejscach naraz. Zbiór porównuje się raz i tak go czyta Robi w olski/skład/składnia.py.

Pyta się o formę bez cząstki się, bo taką stawia składnia; formy z cząstką nie ma ona czym zapisać, więc zbiory zwrotne czyta po tej stronie nikt.

Kopula ma ramę wypisaną (RAMA_KOPULI), a nie liczoną z pliku, i mówi o tym docstring tego modułu. Odjęcie to jest przy tym całą odmową, jaką skład kopuli wydaje: czasownik, który orzeka orzecznikiem, nie orzeka czynnością.

Bezokolicznik wchodzi tu zdaniem węższym, o kontroli podmiotu, bo drzewo wykonawcę stawia i musi wiedzieć, czy jest nim ten sam, o kim orzeka czasownik nad nim: kazać bierze w polszczyźnie bezokolicznik, a wykonawcą jest ten, komu kazano, i tego ten zapis nie ma czym powiedzieć.

Source code in olski/walencja.py
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
def rama(lemat: str) -> frozenset[str]:
    """Pozycje, które ten czasownik bierze, czyli rama widziana przez skład.

    Zbiorem, a nie pytaniem na pozycję, bo drzewo żąda tylu pozycji, ile w nim
    stanęło: pytań byłoby po jednym na pozycję, a każde z nich stoi u pytającego
    osobną gałęzią, więc lista rośnie wtedy w dwóch miejscach naraz.
    Zbiór porównuje się raz i tak go czyta ``Robi`` w ``olski/skład/składnia.py``.

    Pyta się o formę bez cząstki ``się``, bo taką stawia składnia; formy z cząstką
    nie ma ona czym zapisać, więc zbiory zwrotne czyta po tej stronie nikt.

    Kopula ma ramę wypisaną (:data:`RAMA_KOPULI`), a nie liczoną z pliku, i mówi o
    tym docstring tego modułu. Odjęcie to jest przy tym całą odmową, jaką skład
    kopuli wydaje: czasownik, który orzeka orzecznikiem, nie orzeka czynnością.

    Bezokolicznik wchodzi tu zdaniem węższym, o kontroli podmiotu, bo drzewo
    wykonawcę stawia i musi wiedzieć, czy jest nim ten sam, o kim orzeka czasownik
    nad nim: ``kazać`` bierze w polszczyźnie bezokolicznik, a wykonawcą jest ten,
    komu kazano, i tego ten zapis nie ma czym powiedzieć.
    """
    if lemat in KOPULA:
        return RAMA_KOPULI
    domyślna = frozenset() if lemat in BEZ_BIERNIKA else {BIERNIK}
    return frozenset(domyślna) | {
        pozycja for pozycja, lematy in POZYCJE_LEKSYKONU if lemat in lematy
    }