Przejdź do treści

olski.parse.streszczenie

Streszczenie czytania: jeden wiersz, którym werdykt nazywa, co zdanie mówi.

Czego ten napis nie odróżnia, mówi Rozbieżność (olski/parse/podsumowanie.py).

PRZYŁĄCZONY_DO = ' → ' module-attribute

OBOK = ' + ' module-attribute

PRZYLEGAJĄCE = frozenset({','}) module-attribute

liście(drzewo)

Liście tego drzewa, w porządku zdania.

Pyta o nie werdykt, bo odczytania formy niesie liść (Leaf.odczytania), a nie węzeł nad nim.

Source code in olski/parse/streszczenie.py
31
32
33
34
35
36
37
38
39
40
41
def liście(drzewo: Tree) -> Iterator[Leaf]:
    """Liście tego drzewa, w porządku zdania.

    Pyta o nie werdykt, bo odczytania formy niesie liść
    (:attr:`Leaf.odczytania`), a nie węzeł nad nim.
    """
    if isinstance(drzewo, Leaf):
        yield drzewo
        return
    for dziecko in drzewo.children:
        yield from liście(dziecko)

sklej_formy(formy)

Formy jako jeden napis, tak jak stoją w zdaniu.

Przecinek jest osobnym segmentem, więc sklejenie przez sam odstęp daje wolni , równi, czego autor w swoim zdaniu nie napisał.

Source code in olski/parse/streszczenie.py
44
45
46
47
48
49
50
51
52
53
54
55
def sklej_formy(formy: Iterable[str]) -> str:
    """Formy jako jeden napis, tak jak stoją w zdaniu.

    Przecinek jest osobnym segmentem, więc sklejenie przez sam odstęp
    daje ``wolni , równi``, czego autor w swoim zdaniu nie napisał.
    """
    napis = ""
    for forma in formy:
        if napis and forma not in PRZYLEGAJĄCE:
            napis += " "
        napis += forma
    return napis

describe(node, deklaracja)

Streszczenie czytania: co stoi w której roli i do czego doszedł modyfikator.

Streszczeń jest tyle, ile zdanie ma zdań składowych, po jednym na składowe, bo każde z nich obsadza role własnym materiałem (zakresy dzieli między nie zdanie), i widać w nich przez to całe zdanie współrzędne. Czemu nie jedno na zdanie i co ten podział kosztuje, mówi docs/parsowanie.md#werdykt-jest-zapytaniem-o-las-a-nie-listą-czytań.

Dwa czytania jednego zdania gdzieś się różnią, a streszczenie pokazuje tę różnicę temu, kto ma zdanie poprawić. Same role tego nie pokazują, bo grupa przyimkowa dochodzi raz do jednej głowy, a raz do drugiej, i formy stojące nad nią zostają wtedy te same: koszt szynki z dodatkami jest tym samym dopełnieniem niezależnie od tego, czy z dodatkami doszło do koszt, czy do szynki. Rola przyłączana dostaje więc obok wypełnienia to, co modyfikator określa.

Drugim takim miejscem jest granica członu w ciągu współrzędnym, i tam odpowiada nawias, a nie nazwa obok: granica biegnie wewnątrz wypełnienia, więc widać ją tylko w samym napisie. Co dostaje nawias, a co nie, mówi _nawiasuj.

Żądają tego role przyłączane, bo ich gospodarza gramatyka zostawia nierozstrzygniętego rozmyślnie: podmiot i dopełnienie rozstrzyga przypadek, a pozycje przyłączeniowe stoją po to, żeby dać oba czytania (docs/subset.md#przyjąć-koszt-to-znaczy-dać-oba-czytania-wszędzie). Dopisane jest wypełnienie, a nie pozycja obok niego, więc Deklaracja.role zostaje listą ról.

Rola przyłączana jest nazwana pierwszym wystąpieniem w składowym (_streszcz), więc dwa czytania różne miejscem drugiego okolicznika tej samej roli wychodzą stąd jednym napisem. Streszczeń wychodzi przez to nie więcej niż czytań, bo powtórzone na listę nie wchodzi (Verdict.readings w olski/werdykt.py); zdanie, którego to nie rozstrzyga, rozstrzyga Las.przyłączenia, gdzie wpisów jest tyle, ile nierozstrzygniętych wyborów.

Zdanie podrzędne jest z tego wyszukiwania wyjęte (Deklaracja.podrzędne), bo streszczane jest zdanie zewnętrzne. Zdanie współrzędne wyjęte nie jest, bo jego role są rolami tego samego zdania; osobne jest tylko streszczenie, w którym one stoją.

Source code in olski/parse/streszczenie.py
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 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
def describe(node: Node, deklaracja: Deklaracja) -> tuple[dict[str, str], ...]:
    """Streszczenie czytania: co stoi w której roli i do czego doszedł modyfikator.

    Streszczeń jest tyle, ile zdanie ma zdań składowych, po jednym na składowe,
    bo każde z nich obsadza role własnym materiałem
    (:func:`zakresy` dzieli między nie zdanie),
    i widać w nich przez to całe zdanie współrzędne.
    Czemu nie jedno na zdanie i co ten podział kosztuje, mówi
    docs/parsowanie.md#werdykt-jest-zapytaniem-o-las-a-nie-listą-czytań.

    Dwa czytania jednego zdania gdzieś się różnią,
    a streszczenie pokazuje tę różnicę temu, kto ma zdanie poprawić.
    Same role tego nie pokazują,
    bo grupa przyimkowa dochodzi raz do jednej głowy, a raz do drugiej,
    i formy stojące nad nią zostają wtedy te same:
    ``koszt szynki z dodatkami`` jest tym samym dopełnieniem niezależnie od tego,
    czy ``z dodatkami`` doszło do ``koszt``, czy do ``szynki``.
    Rola przyłączana dostaje więc obok wypełnienia to, co modyfikator określa.

    Drugim takim miejscem jest granica członu w ciągu współrzędnym,
    i tam odpowiada nawias, a nie nazwa obok:
    granica biegnie wewnątrz wypełnienia, więc widać ją tylko w samym napisie.
    Co dostaje nawias, a co nie, mówi :func:`_nawiasuj`.

    Żądają tego role przyłączane,
    bo ich gospodarza gramatyka zostawia nierozstrzygniętego rozmyślnie:
    podmiot i dopełnienie rozstrzyga przypadek,
    a pozycje przyłączeniowe stoją po to, żeby dać oba czytania
    (docs/subset.md#przyjąć-koszt-to-znaczy-dać-oba-czytania-wszędzie).
    Dopisane jest wypełnienie, a nie pozycja obok niego,
    więc :attr:`Deklaracja.role` zostaje listą ról.

    Rola przyłączana jest nazwana pierwszym wystąpieniem w składowym
    (:func:`_streszcz`), więc dwa czytania różne miejscem drugiego okolicznika
    tej samej roli wychodzą stąd jednym napisem.
    Streszczeń wychodzi przez to nie więcej niż czytań, bo powtórzone na listę
    nie wchodzi (``Verdict.readings`` w ``olski/werdykt.py``);
    zdanie, którego to nie rozstrzyga, rozstrzyga :meth:`Las.przyłączenia`,
    gdzie wpisów jest tyle, ile nierozstrzygniętych wyborów.

    Zdanie podrzędne jest z tego wyszukiwania wyjęte
    (:attr:`Deklaracja.podrzędne`), bo streszczane jest zdanie zewnętrzne.
    Zdanie współrzędne wyjęte nie jest, bo jego role są rolami tego samego
    zdania; osobne jest tylko streszczenie, w którym one stoją.
    """
    return tuple(
        _streszcz(node, deklaracja, zakres) for zakres in zakresy(node, deklaracja.składowe)
    )

streszczenia(drzewa, deklaracja)

Streszczenia tych drzew, każde raz i w kolejności pierwszego wystąpienia.

Dwa drzewa różne poza zasięgiem describe wychodzą z niego jednym napisem, a napis wypisany drugi raz nie mówi nic ponad ten nad sobą. Wołają to dwa miejsca — odczytania zdania i kształty konstytuentu — i pierwsze z nich pokazuje, ile powtórzeń bywa: zdanie o siedmiu wyrażeniach przyimkowych ma odczytań ponad sto, a napisów różnych kilka.

Source code in olski/parse/streszczenie.py
137
138
139
140
141
142
143
144
145
146
147
148
def streszczenia(
    drzewa: Iterable[Node], deklaracja: Deklaracja
) -> list[tuple[dict[str, str], ...]]:
    """Streszczenia tych drzew, każde raz i w kolejności pierwszego wystąpienia.

    Dwa drzewa różne poza zasięgiem :func:`describe` wychodzą z niego jednym
    napisem, a napis wypisany drugi raz nie mówi nic ponad ten nad sobą.
    Wołają to dwa miejsca — odczytania zdania i kształty konstytuentu — i pierwsze
    z nich pokazuje, ile powtórzeń bywa: zdanie o siedmiu wyrażeniach
    przyimkowych ma odczytań ponad sto, a napisów różnych kilka.
    """
    return [streszczenie for streszczenie, _drzewa in streszczone(drzewa, deklaracja)]

streszczone(drzewa, deklaracja)

Te drzewa pogrupowane po streszczeniu, w kolejności pierwszego wystąpienia.

Odsiew ze streszczenia jest tu jeden na oba pytania, bo werdykt pyta o jedno i drugie: o same streszczenia i o to, czym forma stoi pod każdym z nich (Verdict.morfologia w olski/werdykt.py). Napisany dwa razy rozjechałby się po cichu i wtedy morfologia opisywałaby inne streszczenie niż to, które nad nią wypisano.

Grupa ma pod sobą drzewa, a nie jedno z nich, bo streszczenie zbiera czasem kilka kształtów, a odczytania formy nie muszą być w nich te same.

Source code in olski/parse/streszczenie.py
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
def streszczone(
    drzewa: Iterable[Node], deklaracja: Deklaracja
) -> list[tuple[tuple[dict[str, str], ...], list[Node]]]:
    """Te drzewa pogrupowane po streszczeniu, w kolejności pierwszego wystąpienia.

    Odsiew ze :func:`streszczenia` jest tu jeden na oba pytania, bo werdykt pyta
    o jedno i drugie: o same streszczenia i o to, czym forma stoi pod każdym z
    nich (``Verdict.morfologia`` w ``olski/werdykt.py``). Napisany dwa razy
    rozjechałby się po cichu i wtedy morfologia opisywałaby inne streszczenie
    niż to, które nad nią wypisano.

    Grupa ma pod sobą drzewa, a nie jedno z nich, bo streszczenie zbiera czasem
    kilka kształtów, a odczytania formy nie muszą być w nich te same.
    """
    wynik: list[tuple[tuple[dict[str, str], ...], list[Node]]] = []
    for drzewo in drzewa:
        streszczenie = describe(drzewo, deklaracja)
        for gotowe, pod_nim in wynik:
            if gotowe == streszczenie:
                pod_nim.append(drzewo)
                break
        else:
            wynik.append((streszczenie, [drzewo]))
    return wynik

w_zakresie(node, rola, podrzędne, zakres)

Węzły tej roli, które należą do tej części zdania, w porządku zdania.

Rolę przypisuje zakresowi jej początek, a nie cała rozpiętość, i mówi to _streszcz. Pytają o to dwa podsumowania — streszczenie oraz wiersz żądania (olski/werdykt.py) — więc kryterium jest jedno: oba mówią o tym samym zdaniu składowym i wiersz jednego ma stać obok wiersza drugiego.

Source code in olski/parse/streszczenie.py
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
def w_zakresie(
    node: Node, rola: str, podrzędne: Sequence[str], zakres: tuple[int, int]
) -> list[Node]:
    """Węzły tej roli, które należą do tej części zdania, w porządku zdania.

    Rolę przypisuje zakresowi jej początek, a nie cała rozpiętość, i mówi to
    :func:`_streszcz`. Pytają o to dwa podsumowania — streszczenie oraz wiersz
    żądania (``olski/werdykt.py``) — więc kryterium jest jedno: oba mówią o tym
    samym zdaniu składowym i wiersz jednego ma stać obok wiersza drugiego.
    """
    return [
        węzeł
        for węzeł in node.find(rola, podrzędne)
        if zakres[0] <= węzeł.span[0] < zakres[1]
    ]

zakresy(node, symbole)

Zdanie podzielone na tyle części, ile ma zdań składowych, po jednej na składowe.

Granicą jest początek składowego następnego, a nie koniec poprzedniego, więc każde słowo zdania wpada dokładnie do jednej części i nie ginie z niej to, co między składowymi stoi: spójnik, przecinek, a za ostatnim składowym dopowiedzenie i kropka. Zdanie o jednym składowym wychodzi stąd całe i jedną częścią, tak samo jak konstytuent, który składowego nie ma pod sobą wcale.

Source code in olski/parse/streszczenie.py
194
195
196
197
198
199
200
201
202
203
204
205
206
def zakresy(node: Node, symbole: Sequence[str]) -> list[tuple[int, int]]:
    """Zdanie podzielone na tyle części, ile ma zdań składowych, po jednej na składowe.

    Granicą jest początek składowego następnego, a nie koniec poprzedniego,
    więc każde słowo zdania wpada dokładnie do jednej części
    i nie ginie z niej to, co między składowymi stoi: spójnik, przecinek,
    a za ostatnim składowym dopowiedzenie i kropka.
    Zdanie o jednym składowym wychodzi stąd całe i jedną częścią,
    tak samo jak konstytuent, który składowego nie ma pod sobą wcale.
    """
    początki = _początki_składowych(node, symbole)
    granice = [node.span[0], *początki[1:], node.span[1]]
    return [(granice[i], granice[i + 1]) for i in range(len(granice) - 1)]

ciało_koordynuje(etykieta, córki)

Czy ciało o tych córkach koordynuje: etykieta powtórzona wśród nich, a znak obok.

Ciąg współrzędny jest resztą ciągu po odjęciu członu, więc symbol koordynacji stoi wśród własnych córek. Liczba córek-konstytuentów tego nie mówi: grupa_imienna → człon_imienny zdanie_względne ma je dwie i koordynacją nie jest. Samo powtórzenie symbolu też go nie mówi, bo nad ciągiem stoi jeszcze okolicznik zdaniowy dochodzący do całego ciągu, który powtarza go tak samo. Rozdziela je znak: koordynacja spina członów słowem, a przecinek okolicznika należy do konstytuentu, który spójnik tworzy, więc słowem w tym ciele nie stoi. Znak wchodzi tu pustą nazwą, bo Pozycja liścia etykiety nie ma, i po tym samym poznają go pozostałe dwa wejścia.

Pytają o to kryterium trzy miejsca: nawias w napisie roli (_koordynuje), wybór przemilczany wśród rozbieżności (Las._nazwany_gdzie_indziej) i pomiar różnicowy (koordynuje w harness/ruch.py). Stoi w jednym, bo rozejście tych trzech widać dopiero w liczbach, a niezmiennik, na którym ono stoi, pilnuje tests/test_subset.py.

Source code in olski/parse/streszczenie.py
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
def ciało_koordynuje(etykieta: str | None, córki: Iterable[str | None]) -> bool:
    """Czy ciało o tych córkach koordynuje: etykieta powtórzona wśród nich, a znak obok.

    Ciąg współrzędny jest resztą ciągu po odjęciu członu,
    więc symbol koordynacji stoi wśród własnych córek.
    Liczba córek-konstytuentów tego nie mówi:
    `grupa_imienna → człon_imienny zdanie_względne` ma je dwie i koordynacją nie jest.
    Samo powtórzenie symbolu też go nie mówi,
    bo nad ciągiem stoi jeszcze okolicznik zdaniowy dochodzący do całego ciągu,
    który powtarza go tak samo.
    Rozdziela je znak: koordynacja spina członów słowem,
    a przecinek okolicznika należy do konstytuentu, który spójnik tworzy,
    więc słowem w tym ciele nie stoi.
    Znak wchodzi tu pustą nazwą, bo :class:`Pozycja` liścia etykiety nie ma,
    i po tym samym poznają go pozostałe dwa wejścia.

    Pytają o to kryterium trzy miejsca:
    nawias w napisie roli (:func:`_koordynuje`),
    wybór przemilczany wśród rozbieżności (:meth:`Las._nazwany_gdzie_indziej`)
    i pomiar różnicowy (``koordynuje`` w ``harness/ruch.py``).
    Stoi w jednym, bo rozejście tych trzech widać dopiero w liczbach,
    a niezmiennik, na którym ono stoi, pilnuje ``tests/test_subset.py``.
    """
    nazwy = list(córki)
    return etykieta in nazwy and None in nazwy