Przejdź do treści

olski.precedencja

Dominacja rozdzielona od precedencji, wraz z preprocesorem, który je składa.

Produkcja mówi naraz dwie rzeczy: z czego konstytuent się składa i w jakiej kolejności te córki stoją. Polszczyzna stawia je w kilku kolejnościach, więc gramatyka wypisująca każdą osobno rośnie mnożąc się, a miejsce na okolicznik, wypisane w każdym ciele z osobna, bywa w którymś zapomniane. Zdanie wychodzi wtedy jednym czytaniem, bo drugie nie miało gdzie się wyprowadzić, i po werdykcie tego nie widać (docs/parsowanie.md#wyliczone-ciało-myli-się-w-stronę-werdyktu).

Deklaracja niżej mówi te dwie rzeczy osobno. Rozwinięcie niesie to, co jest wspólne całej rodzinie zdaniowej: symbol okolicznika i odpowiedź na pytanie, po której córce on staje. Rozwinięcie.dominacja bierze same córki, obok nich warunek precedencji nad ich kolejnością, i wpisuje do gramatyki każdy szyk, jaki ten warunek dopuszcza, w każdym miejscu na okolicznik, jakie ten szyk ma.

Ciała jednego rozwinięcia konkurują potem o to samo zdanie, więc każde dostaje tu koszt, czyli miejsce w kolejności, w jakiej las wyda te czytania (wyprowadzenia w olski/parse/las.py). Wylicza go rozwinięcie, a nie wypisuje deklaracja: produkcji jest tysiąc kilkaset, z czego siedemset samego orzeczenia, więc koszt wypisany byłby drugą deklaracją tego samego. Dwie pozycje cennika mówią tu to samo — PRZESTAWIENIE i OKOLICZNIK (olski/cennik.py): ciało wypisane w deklaracji jest podstawowe, a odstępstwo od niego stoi niżej.

Preprocesorem jest to dlatego, że rozwinięcie kończy się przed rozbiorem: tablica Earleya dostaje ciała wypisane, takie same jak pisane ręką. Warunek sprawdzany dopiero w lesie zdjąłby rozwinięcie i zmieniłby liczbę czytań, i tam czeka drugi odbiorca takich warunków, czyli luka (docs/parsowanie.md#kierunek-produkcja-się-rozwarstwia-a-podłoże-zostaje).

Warunek = Callable[[tuple[str, ...]], bool] module-attribute

Rozwinięcie

Gdzie w konstytuencie staje okolicznik, i wpisywanie takiego konstytuenta do gramatyki.

Miejsce na okolicznik jest tu wyliczone, a nie wypisane, i wylicza je jedna reguła: okolicznik staje po każdej córce, która jest grupą, oraz na końcu konstytuenta. Pierwsza połowa reguły jest odpowiedzią na przyłączenie, które olski oddaje czytelnikowi: gdzie grupa imienna bierze wyrażenie przyimkowe za sobą, tam musi umieć wziąć je też zdanie, bo inaczej gramatyka wybiera przyłączenie przez przeoczenie (docs/subset.md#przyjąć-koszt-to-znaczy-dać-oba-czytania-wszędzie).

Córki czasownikowej reguła nie wyjmuje, bo polszczyzna stawia okolicznik i tam; co kosztowało wyjmowanie jej, trzyma docs/subset.md#zdanie-deklaruje-córki-a-warunek-deklaruje-szyk.

Miejsca nie dostaje grupa_orzeczenia, bo okolicznik bierze ono samo, przez wypełnienia, więc miejsce obok niego byłoby drugim wyprowadzeniem jednego napisu. Dotyczy to obu miejsc, jakie taka córka ma — tego za nią i tego na końcu konstytuenta — i dlatego pyta o nie jeden zbiór, a nie dwa.

Source code in olski/precedencja.py
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
class Rozwinięcie:
    """Gdzie w konstytuencie staje okolicznik, i wpisywanie takiego konstytuenta do gramatyki.

    Miejsce na okolicznik jest tu wyliczone, a nie wypisane, i wylicza je jedna reguła:
    okolicznik staje po każdej córce, która jest grupą, oraz na końcu konstytuenta.
    Pierwsza połowa reguły jest odpowiedzią na przyłączenie,
    które olski oddaje czytelnikowi: gdzie grupa imienna bierze wyrażenie przyimkowe
    za sobą, tam musi umieć wziąć je też zdanie, bo inaczej gramatyka wybiera
    przyłączenie przez przeoczenie
    (docs/subset.md#przyjąć-koszt-to-znaczy-dać-oba-czytania-wszędzie).

    Córki czasownikowej reguła nie wyjmuje, bo polszczyzna stawia okolicznik i
    tam; co kosztowało wyjmowanie jej, trzyma
    docs/subset.md#zdanie-deklaruje-córki-a-warunek-deklaruje-szyk.

    Miejsca nie dostaje ``grupa_orzeczenia``, bo okolicznik bierze ono samo, przez
    ``wypełnienia``, więc miejsce obok niego byłoby drugim wyprowadzeniem jednego
    napisu. Dotyczy to obu miejsc, jakie taka córka ma — tego za nią i tego na
    końcu konstytuenta — i dlatego pyta o nie jeden zbiór, a nie dwa.
    """

    def __init__(
        self,
        grammar: Grammar,
        okolicznik: Part,
        własny_okolicznik: Iterable[str],
    ) -> None:
        self.grammar = grammar
        self.okolicznik = okolicznik
        self.własny_okolicznik = frozenset(własny_okolicznik)

    def dominacja(
        self,
        symbol: str,
        córki: Sequence[Part | Głowa],
        precedencja: Warunek | None = None,
        koszty: tuple[str, ...] = (),
        **cechy,
    ) -> None:
        """Wpisz ten konstytuent każdym szykiem tych córek i każdym miejscem na okolicznik.

        Warunek precedencji pominięty zostawia szyk jeden, ten wypisany;
        podany przepuszcza te przestawienia córek, na które odpowiada prawdą.
        Cechy są wspólne wszystkim wypisanym ciałom, bo wypuszcza je konstytuent,
        a nie kolejność, w jakiej stoją jego córki.

        Pozycje cennika podane tutaj mówią, czym cała ta rodzina jest nacechowana,
        więc stoi ona w wydruku pod podstawową. Dokładają się do nich dwie pozycje
        wyliczane z deklaracji, bo produkcja niesie jedną listę.
        """
        for szyk_płaci, szyk in self._szyki(córki, precedencja):
            for okolicznik_płaci, ciało in self._miejsca(szyk):
                self.grammar.rule(
                    symbol, ciało, koszty=(*koszty, *szyk_płaci, *okolicznik_płaci), **cechy
                )

    def _szyki(
        self, córki: Sequence[Part | Głowa], precedencja: Warunek | None
    ) -> Iterator[tuple[tuple[str, ...], list[Part | Głowa]]]:
        """Szyki, na które ten warunek pozwala, każdy wraz z tym, czym płaci.

        Odległość Kendalla stoi tu w miejscu pozycji cennika powtórzonej, bo szyk
        odległy o dwie zamiany jest dwa razy dalej od wypisanego niż szyk odległy
        o jedną. Dwa szyki jednego zdania mają córki tej samej rozpiętości, więc
        bez tej pozycji rozstrzygałby o nich alfabet etykiet i `Janek lubi piwo.`
        wychodziłoby czytaniem z `piwo` w podmiocie (``tests/test_morfologia.py``).
        """
        if precedencja is None:
            yield (), list(córki)
            return
        for numery in permutations(range(len(córki))):
            szyk = [córki[numer] for numer in numery]
            if precedencja(tuple(_nazwa(część) for część in szyk)):
                yield (PRZESTAWIENIE,) * _przestawienia(numery), szyk

    def _miejsca(
        self, szyk: Sequence[Part | Głowa]
    ) -> Iterator[tuple[tuple[str, ...], list[Part | Głowa]]]:
        """Ten szyk bez okolicznika, a za nim ten sam szyk z okolicznikiem w każdym miejscu.

        Miejsce jest za każdą córką, która okolicznika nie bierze sama — obok
        takiej córki byłoby ono drugim wyprowadzeniem jednego napisu — i miejsce
        na końcu konstytuenta jest tym za córką ostatnią, a nie regułą obok.

        Miejsca kosztują wszystkie tyle samo: okolicznik postawiony w innym miejscu
        obejmuje inne słowa, więc rozstrzyga o nim cięcie, a nie koszt
        (``_cięcie`` w ``olski/parse/las.py``).
        """
        nazwy = [_nazwa(część) for część in szyk]
        yield (), list(szyk)
        for gdzie, córka in enumerate(nazwy, start=1):
            if córka in self.własny_okolicznik:
                continue
            yield (OKOLICZNIK,), [*szyk[:gdzie], self.okolicznik, *szyk[gdzie:]]

grammar = grammar instance-attribute

okolicznik = okolicznik instance-attribute

własny_okolicznik = frozenset(własny_okolicznik) instance-attribute

__init__(grammar, okolicznik, własny_okolicznik)

Source code in olski/precedencja.py
 92
 93
 94
 95
 96
 97
 98
 99
100
def __init__(
    self,
    grammar: Grammar,
    okolicznik: Part,
    własny_okolicznik: Iterable[str],
) -> None:
    self.grammar = grammar
    self.okolicznik = okolicznik
    self.własny_okolicznik = frozenset(własny_okolicznik)

dominacja(symbol, córki, precedencja=None, koszty=(), **cechy)

Wpisz ten konstytuent każdym szykiem tych córek i każdym miejscem na okolicznik.

Warunek precedencji pominięty zostawia szyk jeden, ten wypisany; podany przepuszcza te przestawienia córek, na które odpowiada prawdą. Cechy są wspólne wszystkim wypisanym ciałom, bo wypuszcza je konstytuent, a nie kolejność, w jakiej stoją jego córki.

Pozycje cennika podane tutaj mówią, czym cała ta rodzina jest nacechowana, więc stoi ona w wydruku pod podstawową. Dokładają się do nich dwie pozycje wyliczane z deklaracji, bo produkcja niesie jedną listę.

Source code in olski/precedencja.py
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
def dominacja(
    self,
    symbol: str,
    córki: Sequence[Part | Głowa],
    precedencja: Warunek | None = None,
    koszty: tuple[str, ...] = (),
    **cechy,
) -> None:
    """Wpisz ten konstytuent każdym szykiem tych córek i każdym miejscem na okolicznik.

    Warunek precedencji pominięty zostawia szyk jeden, ten wypisany;
    podany przepuszcza te przestawienia córek, na które odpowiada prawdą.
    Cechy są wspólne wszystkim wypisanym ciałom, bo wypuszcza je konstytuent,
    a nie kolejność, w jakiej stoją jego córki.

    Pozycje cennika podane tutaj mówią, czym cała ta rodzina jest nacechowana,
    więc stoi ona w wydruku pod podstawową. Dokładają się do nich dwie pozycje
    wyliczane z deklaracji, bo produkcja niesie jedną listę.
    """
    for szyk_płaci, szyk in self._szyki(córki, precedencja):
        for okolicznik_płaci, ciało in self._miejsca(szyk):
            self.grammar.rule(
                symbol, ciało, koszty=(*koszty, *szyk_płaci, *okolicznik_płaci), **cechy
            )