Przejdź do treści

olski.skład

Skład: struktura wchodzi, polski tekst wychodzi.

Kalambur nazywa cały ten tor: skład jest łamaniem tekstu, składnia jest budową zdania, więc łamacz sprawdzający składnię mieści się w jednym słowie. Wywód, po co ten kierunek stoi obok parsera, trzyma docs/design-notes.md.

Podział na warstwy jest tu decyzją. olski.skład.składnia trzyma kategorie i konstruktory, czyli to, co da się powiedzieć, i nie ma w sobie ani przypadka, ani rodzaju, ani szyku. olski.skład.morfologia trzyma formy, które z tego wychodzą. olski.skład.opowieść trzyma to, co widać dopiero nad kilkoma zdaniami naraz: czas opowiadania i tożsamość tego, o kim mowa. Autor pisze drzewo, a zgodność jest liczona po drodze, a nie sprawdzana po niej. Liczona jest zgodność, a nie wszystko: rama czasownika przychodzi z leksykonu, więc drzewo, które żąda dopełnienia od czasownika biorącego co innego, zgłasza się przez PozaRamą, zamiast powstać. Rekcja przyimka przychodzi tak samo, z olski.skład.przyimki, a który leksem stoi pod nazwą, mówi olski.skład.leksemy, bo lemat go nie wskazuje, a od wyboru zależy znaczenie zdania.

LEKSEMY = {'Włochy': 'Włochy:Sn_pt~szech', 'oko': 'oko:Sn_col', 'oko_w_rosole': 'oko:Sn_ncol'} module-attribute

PRZYIMKI = {('', 'czas'): 'inst', ('', 'narzędzie'): 'inst', ('do', 'cel'): 'gen', ('na', 'cel'): 'acc', ('na', 'miejsce'): 'loc', ('od', 'źródło'): 'gen', ('po', 'droga'): 'loc', ('pod', 'cel'): 'acc', ('pod', 'miejsce'): 'inst', ('przed', 'miejsce'): 'inst', ('w', 'cel'): 'acc', ('w', 'czas'): 'loc', ('w', 'miejsce'): 'loc', ('wśród', 'miejsce'): 'gen', ('z', 'źródło'): 'gen'} module-attribute

SPÓJNIKI = {('bo', 'przyczyna'): False, ('gdy', 'czas'): True, ('kiedy', 'czas'): True, ('ponieważ', 'przyczyna'): True, ('więc', 'skutek'): False, ('zanim', 'czas'): True} module-attribute

__all__ = ['LEKSEMY', 'PRZYIMKI', 'Akapit', 'BrakFormy', 'Byt', 'Ciąg', 'Czyj', 'Jaki', 'Jest', 'Kawałek', 'Kolizja', 'Komu', 'Kontekst', 'Koordynacja', 'Nominalne', 'Okolicznik', 'Opis', 'Opowieść', 'Postać', 'PozaRamą', 'Przysłówek', 'Robi', 'Rola', 'Rzecz', 'SPÓJNIKI', 'Treść', 'WieleLeksemów', 'Wyróżnienie', 'Zdanie', 'byt', 'kompiluj', 'leksem', 'nie', 'odmień', 'po_poprzednim', 'pomijalny', 'przejrzyj', 'przypadek', 'rodzaj_rzeczownika', 'staje_na_czele', 'wprowadza', 'zdarzenie'] module-attribute

BrakFormy

Bases: Exception

Morfologia takiej formy nie ma.

Wyjątek, a nie forma zgadnięta albo pominięta, bo to jest błąd kompilacji: drzewo żąda czegoś, czego polszczyzna nie odmienia.

Source code in olski/skład/morfologia.py
35
36
37
38
39
40
class BrakFormy(Exception):
    """Morfologia takiej formy nie ma.

    Wyjątek, a nie forma zgadnięta albo pominięta,
    bo to jest błąd kompilacji: drzewo żąda czegoś, czego polszczyzna nie odmienia.
    """

WieleLeksemów

Bases: Exception

Pod tą nazwą stoi kilka leksemów i nie zgadzają się one co do odpowiedzi.

Usterka odwrotna do BrakFormy i zgłaszana z tego samego powodu: kompilator ma tu do wyboru dwie poprawne polszczyzny o różnym znaczeniu, a wybór między znaczeniami należy do autora drzewa.

Treść zgłoszenia stoi tutaj, bo pytają o nią dwa miejsca naraz, a odpowiedź jest w obu ta sama: leksem wraz z tym, co z niego wychodzi. Tyle wystarcza, żeby wpisać rozstrzygnięcie do olski/skład/leksemy.py, i to jest jedyne, po co to zgłoszenie jest czytane.

Source code in olski/skład/morfologia.py
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
class WieleLeksemów(Exception):
    """Pod tą nazwą stoi kilka leksemów i nie zgadzają się one co do odpowiedzi.

    Usterka odwrotna do ``BrakFormy`` i zgłaszana z tego samego powodu:
    kompilator ma tu do wyboru dwie poprawne polszczyzny o różnym znaczeniu,
    a wybór między znaczeniami należy do autora drzewa.

    Treść zgłoszenia stoi tutaj, bo pytają o nią dwa miejsca naraz,
    a odpowiedź jest w obu ta sama: leksem wraz z tym, co z niego wychodzi.
    Tyle wystarcza, żeby wpisać rozstrzygnięcie do ``olski/skład/leksemy.py``,
    i to jest jedyne, po co to zgłoszenie jest czytane.
    """

    def __init__(self, pytanie: str, wedle_leksemu: dict[str, set[str]]) -> None:
        super().__init__(
            f"{pytanie}: leksemy się nie zgadzają, bo "
            + ", ".join(
                f"{identyfikator} daje {', '.join(sorted(dane))}"
                for identyfikator, dane in wedle_leksemu.items()
            )
            + "; który z nich, mówi olski/skład/leksemy.py"
        )

__init__(pytanie, wedle_leksemu)

Source code in olski/skład/morfologia.py
56
57
58
59
60
61
62
63
64
def __init__(self, pytanie: str, wedle_leksemu: dict[str, set[str]]) -> None:
    super().__init__(
        f"{pytanie}: leksemy się nie zgadzają, bo "
        + ", ".join(
            f"{identyfikator} daje {', '.join(sorted(dane))}"
            for identyfikator, dane in wedle_leksemu.items()
        )
        + "; który z nich, mówi olski/skład/leksemy.py"
    )

Akapit

Ciąg zdarzeń opowiedzianych jedno po drugim.

Akapit jest jednostką, w której podmiot da się opuścić, bo jest jednostką, w której czytelnik trzyma jeden wątek. Pierwsze zdanie akapitu wypisuje podmiot zawsze, także wtedy, gdy akapit poprzedni skończył się na tej samej postaci, i tyle akapit o opuszczeniu rozstrzyga: resztę warunków stawia pomijalny w olski/skład/składnia.py.

Source code in olski/skład/opowieść.py
 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
class Akapit:
    """Ciąg zdarzeń opowiedzianych jedno po drugim.

    Akapit jest jednostką, w której podmiot da się opuścić,
    bo jest jednostką, w której czytelnik trzyma jeden wątek.
    Pierwsze zdanie akapitu wypisuje podmiot zawsze,
    także wtedy, gdy akapit poprzedni skończył się na tej samej postaci,
    i tyle akapit o opuszczeniu rozstrzyga:
    resztę warunków stawia ``pomijalny`` w ``olski/skład/składnia.py``.
    """

    def __init__(self, *zdania) -> None:
        self.zdania = tuple(_rozwiń(zdania))

    def konteksty(self, czas: str):
        """Zdania akapitu, każde wraz z kontekstem, w którym akapit je wypisuje.

        Wydawane osobno od napisu, bo o ten sam kontekst pyta każdy,
        kto chce zdanie tego akapitu obejrzeć, a nie tylko wypisać:
        ``olski/skład/przegląd.py`` jest pierwszym takim pytającym,
        a kopia tej pętli u niego mierzyłaby akapit, którego ten plik już nie składa.

        Wydaje same zdania akapitu, a nie te, które stoją pod nimi;
        po tamte schodzi ``Zdanie.konteksty``, biorąc kontekst wydany tutaj.
        """
        kontekst = Kontekst(czas=czas)
        poprzednie = None
        for zdanie in self.zdania:
            yield zdanie, po_poprzednim(zdanie, poprzednie, kontekst)
            poprzednie = zdanie

    def kompiluj(self, czas: str) -> str:
        return " ".join(kompiluj(zdanie, kontekst) for zdanie, kontekst in self.konteksty(czas))

zdania = tuple(_rozwiń(zdania)) instance-attribute

__init__(*zdania)

Source code in olski/skład/opowieść.py
 99
100
def __init__(self, *zdania) -> None:
    self.zdania = tuple(_rozwiń(zdania))

konteksty(czas)

Zdania akapitu, każde wraz z kontekstem, w którym akapit je wypisuje.

Wydawane osobno od napisu, bo o ten sam kontekst pyta każdy, kto chce zdanie tego akapitu obejrzeć, a nie tylko wypisać: olski/skład/przegląd.py jest pierwszym takim pytającym, a kopia tej pętli u niego mierzyłaby akapit, którego ten plik już nie składa.

Wydaje same zdania akapitu, a nie te, które stoją pod nimi; po tamte schodzi Zdanie.konteksty, biorąc kontekst wydany tutaj.

Source code in olski/skład/opowieść.py
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
def konteksty(self, czas: str):
    """Zdania akapitu, każde wraz z kontekstem, w którym akapit je wypisuje.

    Wydawane osobno od napisu, bo o ten sam kontekst pyta każdy,
    kto chce zdanie tego akapitu obejrzeć, a nie tylko wypisać:
    ``olski/skład/przegląd.py`` jest pierwszym takim pytającym,
    a kopia tej pętli u niego mierzyłaby akapit, którego ten plik już nie składa.

    Wydaje same zdania akapitu, a nie te, które stoją pod nimi;
    po tamte schodzi ``Zdanie.konteksty``, biorąc kontekst wydany tutaj.
    """
    kontekst = Kontekst(czas=czas)
    poprzednie = None
    for zdanie in self.zdania:
        yield zdanie, po_poprzednim(zdanie, poprzednie, kontekst)
        poprzednie = zdanie

kompiluj(czas)

Source code in olski/skład/opowieść.py
119
120
def kompiluj(self, czas: str) -> str:
    return " ".join(kompiluj(zdanie, kontekst) for zdanie, kontekst in self.konteksty(czas))

Opowieść

Akapity o tym, co się stało.

Czasu ten konstruktor nie przyjmuje i nie ma przyjmować. Opowieść jest z definicji mówieniem o tym, co już było, więc czas przeszły jest tu znaczeniem słowa, a nie ustawieniem; tekst o tym, co się dzieje, jest inną rzeczą i doczeka się innego konstruktora.

Source code in olski/skład/opowieść.py
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
class Opowieść:
    """Akapity o tym, co się stało.

    Czasu ten konstruktor nie przyjmuje i nie ma przyjmować.
    Opowieść jest z definicji mówieniem o tym, co już było,
    więc czas przeszły jest tu znaczeniem słowa, a nie ustawieniem;
    tekst o tym, co się dzieje, jest inną rzeczą i doczeka się innego konstruktora.
    """

    #: Czym opowieść jest wobec chwili, w której się ją opowiada.
    CZAS = "kiedyś"

    def __init__(self, *akapity: Akapit) -> None:
        self.akapity = akapity

    def kompiluj(self) -> str:
        return "\n\n".join(akapit.kompiluj(self.CZAS) for akapit in self.akapity)

CZAS = 'kiedyś' class-attribute instance-attribute

akapity = akapity instance-attribute

__init__(*akapity)

Source code in olski/skład/opowieść.py
135
136
def __init__(self, *akapity: Akapit) -> None:
    self.akapity = akapity

kompiluj()

Source code in olski/skład/opowieść.py
138
139
def kompiluj(self) -> str:
    return "\n\n".join(akapit.kompiluj(self.CZAS) for akapit in self.akapity)

Postać

Bases: Rola

Rzecz, do której tekst wraca, wraz z tożsamością, której lemat nie daje.

Postacią jest to, co opowieść wymienia więcej niż raz. Rzecz wspomniana raz postaci nie potrzebuje i zostaje zwykłym bytem, więc ten konstruktor jest deklaracją autora, a nie kosztem płaconym wszędzie.

Tożsamość jest tożsamością obiektu, bo taką daje zmienna w Pythonie, i to jest cały mechanizm: postać przypisana do nazwy i użyta pod tą nazwą dwa razy jest w obu miejscach tą samą. Dwie postaci o tym samym lemacie są dwiema różnymi rzeczami, i to też jest zamierzone: opowieść bywa o dwóch braciach.

Czego to nie obejmuje, jest widać na drugim określeniu: bazyliszek i potwór są dla tego kompilatora dwiema rzeczami, bo tożsamość deklaruje autor, a nie słownik synonimów.

Source code in olski/skład/opowieść.py
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
class Postać(Rola):
    """Rzecz, do której tekst wraca, wraz z tożsamością, której lemat nie daje.

    Postacią jest to, co opowieść wymienia więcej niż raz.
    Rzecz wspomniana raz postaci nie potrzebuje i zostaje zwykłym bytem,
    więc ten konstruktor jest deklaracją autora, a nie kosztem płaconym wszędzie.

    Tożsamość jest tożsamością obiektu, bo taką daje zmienna w Pythonie,
    i to jest cały mechanizm: postać przypisana do nazwy
    i użyta pod tą nazwą dwa razy jest w obu miejscach tą samą.
    Dwie postaci o tym samym lemacie są dwiema różnymi rzeczami,
    i to też jest zamierzone: opowieść bywa o dwóch braciach.

    Czego to nie obejmuje, jest widać na drugim określeniu:
    ``bazyliszek`` i ``potwór`` są dla tego kompilatora dwiema rzeczami,
    bo tożsamość deklaruje autor, a nie słownik synonimów.
    """

    def __init__(self, kto) -> None:
        self.kto = byt(kto)

    @property
    def number(self) -> str:
        return self.kto.number

    @property
    def rodzaj(self) -> str:
        return self.kto.rodzaj

    @property
    def tożsamość(self) -> Postać:
        return self

    def linearyzuj(self, case: str, kontekst: Kontekst = TERAZ) -> str:
        return self.kto.linearyzuj(case, kontekst)

kto = byt(kto) instance-attribute

number property

rodzaj property

tożsamość property

__init__(kto)

Source code in olski/skład/opowieść.py
55
56
def __init__(self, kto) -> None:
    self.kto = byt(kto)

linearyzuj(case, kontekst=TERAZ)

Source code in olski/skład/opowieść.py
70
71
def linearyzuj(self, case: str, kontekst: Kontekst = TERAZ) -> str:
    return self.kto.linearyzuj(case, kontekst)

Kolizja dataclass

Dwie role jednego zdarzenia, których czytelnik od siebie nie odróżni.

Klasy to zgłoszenie nie niesie, bo klasa jest jedna, a pole o jednej wartości mówi, że druga zaraz dojdzie, i mówi to niezależnie od tego, czy dojdzie.

Source code in olski/skład/przegląd.py
56
57
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
@dataclass(frozen=True)
class Kolizja:
    """Dwie role jednego zdarzenia, których czytelnik od siebie nie odróżni.

    Klasy to zgłoszenie nie niesie, bo klasa jest jedna,
    a pole o jednej wartości mówi, że druga zaraz dojdzie,
    i mówi to niezależnie od tego, czy dojdzie.
    """

    #: Napisy, którymi te role w tekście stanęły, w kolejności, w której stoją.
    #: Bez nich zgłoszenie nie ma czym się wytłumaczyć,
    #: bo zdanie o dwóch zdarzeniach niesie dwa zarzuty naraz.
    #: Napis jest jeden tam, gdzie podmiot z tekstu wypadł,
    #: bo forma, której nie widać, nie jest tym, na co autor ma spojrzeć.
    formy: tuple[str, ...]

    def opisz(self) -> str:
        """Zdanie, które autor ma przeczytać, wraz z tym, na czym zarzut stoi."""
        if len(self.formy) == 1:
            return (
                f"„{self.formy[0]}” stoi w formie, którą polszczyzna czyta "
                "i w jednej roli, i w drugiej, a podmiotu to zdanie nie wypisuje, "
                "więc czytelnik nie ma z czego odzyskać, która rola jest którą"
            )
        stoją = " i ".join(f"„{forma}”" for forma in self.formy)
        return (
            f"{stoją} stoją w formach, które polszczyzna czyta i w jednej roli, "
            "i w drugiej, a czasownik ich nie rozróżnia, "
            "więc zdanie czyta się i jako SVO, i jako OVS"
        )

formy instance-attribute

opisz()

Zdanie, które autor ma przeczytać, wraz z tym, na czym zarzut stoi.

Source code in olski/skład/przegląd.py
72
73
74
75
76
77
78
79
80
81
82
83
84
85
def opisz(self) -> str:
    """Zdanie, które autor ma przeczytać, wraz z tym, na czym zarzut stoi."""
    if len(self.formy) == 1:
        return (
            f"„{self.formy[0]}” stoi w formie, którą polszczyzna czyta "
            "i w jednej roli, i w drugiej, a podmiotu to zdanie nie wypisuje, "
            "więc czytelnik nie ma z czego odzyskać, która rola jest którą"
        )
    stoją = " i ".join(f"„{forma}”" for forma in self.formy)
    return (
        f"{stoją} stoją w formach, które polszczyzna czyta i w jednej roli, "
        "i w drugiej, a czasownik ich nie rozróżnia, "
        "więc zdanie czyta się i jako SVO, i jako OVS"
    )

__init__(formy)

Byt dataclass

Bases: Rola

Rzecz wraz z liczbą.

Liczba stoi w drzewie, bo jest znaczeniem: jeden plik i wiele plików to dwie różne rzeczy do powiedzenia, a nie dwie formy jednej.

Source code in olski/skład/składnia.py
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
@dataclass(frozen=True)
class Byt(Rola):
    """Rzecz wraz z liczbą.

    Liczba stoi w drzewie, bo jest znaczeniem: jeden plik i wiele plików
    to dwie różne rzeczy do powiedzenia, a nie dwie formy jednej.
    """

    rzecz: Nominalne
    number: str = "sg"

    @property
    def rodzaj(self) -> str:
        return self.rzecz.rodzaj

    def linearyzuj(self, case: str, kontekst: Kontekst = TERAZ) -> Kawałek:
        return self.rzecz.linearyzuj(case, self.number, kontekst)

rzecz instance-attribute

number = 'sg' class-attribute instance-attribute

rodzaj property

linearyzuj(case, kontekst=TERAZ)

Source code in olski/skład/składnia.py
482
483
def linearyzuj(self, case: str, kontekst: Kontekst = TERAZ) -> Kawałek:
    return self.rzecz.linearyzuj(case, self.number, kontekst)

__init__(rzecz, number='sg')

Ciąg dataclass

Bases: Zdanie

Kilka zdarzeń opowiedzianych jednym zdaniem: podniósł deskę i zszedł.

Kategorią dziedziny jest tu następstwo, a nie spójnik. Autor mówi, że jedno stało się po drugim i że jest to jedna rzecz do opowiedzenia, a to, że wychodzi z tego i, rozstrzyga linearyzacja, tak samo jak rozstrzyga przypadek. Węższe to jest niż polskie i, które łączy także zdarzenia równoczesne, i węższe z rozmysłu: kolejność zdarzeń niesie tu kolejność zapisu, więc kategoria, która by o niej nie mówiła, kłamałaby o połowie swoich zdań.

Od koordynacji bytów różni się tym, czego żąda opuszczenie podmiotu. Byty stoją w jednej roli i żaden z nich nie ma czasownika, a zdarzenia mają go po jednym, więc drugie z nich mówi o tym samym, o kim mówiło pierwsze, i podmiotu nie powtarza. Rozstrzyga o tym pomijalny niżej, czyli ten sam warunek, z którego korzysta akapit, bo pytanie jest jedno: czy czytelnik odzyska podmiot, którego nie ma.

Source code in olski/skład/składnia.py
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
@dataclass(frozen=True)
class Ciąg(Zdanie):
    """Kilka zdarzeń opowiedzianych jednym zdaniem: podniósł deskę i zszedł.

    Kategorią dziedziny jest tu następstwo, a nie spójnik.
    Autor mówi, że jedno stało się po drugim i że jest to jedna rzecz do opowiedzenia,
    a to, że wychodzi z tego ``i``, rozstrzyga linearyzacja,
    tak samo jak rozstrzyga przypadek.
    Węższe to jest niż polskie ``i``, które łączy także zdarzenia równoczesne,
    i węższe z rozmysłu: kolejność zdarzeń niesie tu kolejność zapisu,
    więc kategoria, która by o niej nie mówiła, kłamałaby o połowie swoich zdań.

    Od koordynacji bytów różni się tym, czego żąda opuszczenie podmiotu.
    Byty stoją w jednej roli i żaden z nich nie ma czasownika,
    a zdarzenia mają go po jednym, więc drugie z nich mówi o tym samym,
    o kim mówiło pierwsze, i podmiotu nie powtarza.
    Rozstrzyga o tym ``pomijalny`` niżej, czyli ten sam warunek,
    z którego korzysta akapit, bo pytanie jest jedno:
    czy czytelnik odzyska podmiot, którego nie ma.
    """

    zdarzenia: tuple

    @property
    def podmiot(self) -> Rola:
        return self.zdarzenia[0].podmiot

    @property
    def czasownik(self) -> str:
        return self.zdarzenia[0].czasownik

    @property
    def konstytuenty(self) -> tuple:
        return tuple(część for zdarzenie in self.zdarzenia for część in zdarzenie.konstytuenty)

    @property
    def podmioty(self) -> tuple[Rola, ...]:
        """Podmioty wszystkich zdarzeń, a nie samego pierwszego.

        Domyślne liczenie schodzi pod konstytuenty, a te ciąg ma sklejone,
        więc znalazłoby zdania pod zdarzeniami i minęłoby same zdarzenia.
        """
        return tuple(rola for zdarzenie in self.zdarzenia for rola in zdarzenie.podmioty)

    @property
    def sprawcy(self) -> tuple:
        """Sprawca każdego zdarzenia, bo bezokolicznik wyjdzie z każdego osobno.

        Zdania pod zdarzeniami tu nie wchodzą, w odróżnieniu od ``podmioty``:
        `Chciał podnieść deskę i zejść po schodach.` żąda jednego sprawcy
        od dwóch bezokoliczników, a zdanie z ``bo`` pod którymś z nich
        ma podmiot własny i wychodzi z formą osobową.
        """
        return tuple(sprawca for zdarzenie in self.zdarzenia for sprawca in zdarzenie.sprawcy)

    def uczestnicy(self, kontekst: Kontekst = TERAZ) -> tuple[tuple[Rola, str], ...]:
        """Żadnych, bo ciąg własnego orzeczenia nie ma, tylko po jednym na zdarzenie.

        Podmiot ciąg ma mimo to, i jest nim podmiot pierwszego zdarzenia,
        bo o to pyta ``pomijalny``, składając ciąg ze zdaniem obok.
        Tu odpowiedź jest inna, bo inne jest pytanie:
        uczestnicy stają przy orzeczeniu, a nie przy zdaniu,
        więc szuka się ich w ``konteksty`` niżej, po jednym zdarzeniu naraz.
        """
        return ()

    def _kolejno(self, kontekst: Kontekst):
        """Zdarzenia wraz z kontekstem każdego: drugie i dalsze podmiot opuszczają.

        Pierwsze bierze kontekst nietknięty, a nie policzony wobec pustki,
        bo o jego podmiocie rozstrzygnął akapit, składając cały ciąg ze zdaniem
        przed nim, i ta odpowiedź stoi już w tym kontekście.

        Odpowiedź pada tu raz, a czyta ją i linearyzacja, i ``konteksty``,
        bo o opuszczonym podmiocie musi wiedzieć nie tylko ten, kto ciąg wypisuje,
        ale i ten, kto pyta, co z niego wyszło.
        """
        poprzednie = None
        for zdarzenie in self.zdarzenia:
            yield zdarzenie, (
                kontekst if poprzednie is None else po_poprzednim(zdarzenie, poprzednie, kontekst)
            )
            poprzednie = zdarzenie

    def konteksty(self, kontekst: Kontekst = TERAZ):
        """Zdania wszystkich zdarzeń, a nie samego ciągu, każde w kontekście z ``_kolejno``."""
        for zdarzenie, jego in self._kolejno(kontekst):
            yield from zdarzenie.konteksty(jego)

    def linearyzuj(self, kontekst: Kontekst = TERAZ) -> Kawałek:
        return _lista([zdarzenie.linearyzuj(jego) for zdarzenie, jego in self._kolejno(kontekst)])

zdarzenia instance-attribute

podmiot property

czasownik property

konstytuenty property

podmioty property

Podmioty wszystkich zdarzeń, a nie samego pierwszego.

Domyślne liczenie schodzi pod konstytuenty, a te ciąg ma sklejone, więc znalazłoby zdania pod zdarzeniami i minęłoby same zdarzenia.

sprawcy property

Sprawca każdego zdarzenia, bo bezokolicznik wyjdzie z każdego osobno.

Zdania pod zdarzeniami tu nie wchodzą, w odróżnieniu od podmioty: Chciał podnieść deskę i zejść po schodach. żąda jednego sprawcy od dwóch bezokoliczników, a zdanie z bo pod którymś z nich ma podmiot własny i wychodzi z formą osobową.

uczestnicy(kontekst=TERAZ)

Żadnych, bo ciąg własnego orzeczenia nie ma, tylko po jednym na zdarzenie.

Podmiot ciąg ma mimo to, i jest nim podmiot pierwszego zdarzenia, bo o to pyta pomijalny, składając ciąg ze zdaniem obok. Tu odpowiedź jest inna, bo inne jest pytanie: uczestnicy stają przy orzeczeniu, a nie przy zdaniu, więc szuka się ich w konteksty niżej, po jednym zdarzeniu naraz.

Source code in olski/skład/składnia.py
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
def uczestnicy(self, kontekst: Kontekst = TERAZ) -> tuple[tuple[Rola, str], ...]:
    """Żadnych, bo ciąg własnego orzeczenia nie ma, tylko po jednym na zdarzenie.

    Podmiot ciąg ma mimo to, i jest nim podmiot pierwszego zdarzenia,
    bo o to pyta ``pomijalny``, składając ciąg ze zdaniem obok.
    Tu odpowiedź jest inna, bo inne jest pytanie:
    uczestnicy stają przy orzeczeniu, a nie przy zdaniu,
    więc szuka się ich w ``konteksty`` niżej, po jednym zdarzeniu naraz.
    """
    return ()

konteksty(kontekst=TERAZ)

Zdania wszystkich zdarzeń, a nie samego ciągu, każde w kontekście z _kolejno.

Source code in olski/skład/składnia.py
1381
1382
1383
1384
def konteksty(self, kontekst: Kontekst = TERAZ):
    """Zdania wszystkich zdarzeń, a nie samego ciągu, każde w kontekście z ``_kolejno``."""
    for zdarzenie, jego in self._kolejno(kontekst):
        yield from zdarzenie.konteksty(jego)

linearyzuj(kontekst=TERAZ)

Source code in olski/skład/składnia.py
1386
1387
def linearyzuj(self, kontekst: Kontekst = TERAZ) -> Kawałek:
    return _lista([zdarzenie.linearyzuj(jego) for zdarzenie, jego in self._kolejno(kontekst)])

__init__(zdarzenia)

Czyj dataclass

Bases: Nominalne

Rzecz określona drugą rzeczą: parser podzbioru.

Kierunek tej relacji jest kształtem drzewa, a nie kolejnością słów, więc parser podzbioru i podzbiór parsera są dwoma różnymi drzewami. Nad samym workiem lematów te dwa zdania są nie do rozróżnienia, i to jest ta wieloznaczność, którą ten poziom zdejmuje za darmo.

Określenie jest rolą, a nie rzeczą, bo niesie własną liczbę: bez tego parser podzbiorów nie miałby jak powstać.

Source code in olski/skład/składnia.py
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
@dataclass(frozen=True)
class Czyj(Nominalne):
    """Rzecz określona drugą rzeczą: parser podzbioru.

    Kierunek tej relacji jest kształtem drzewa, a nie kolejnością słów,
    więc parser podzbioru i podzbiór parsera są dwoma różnymi drzewami.
    Nad samym workiem lematów te dwa zdania są nie do rozróżnienia,
    i to jest ta wieloznaczność, którą ten poziom zdejmuje za darmo.

    Określenie jest rolą, a nie rzeczą, bo niesie własną liczbę:
    bez tego parser podzbiorów nie miałby jak powstać.
    """

    głowa: Nominalne
    określenie: Rola

    @property
    def rodzaj(self) -> str:
        return self.głowa.rodzaj

    def linearyzuj(self, case: str, number: str, kontekst: Kontekst = TERAZ) -> Kawałek:
        głowa = self.głowa.linearyzuj(case, number, kontekst)
        return _sklej([głowa, wypisz(self.określenie, "gen", kontekst)])

głowa instance-attribute

określenie instance-attribute

rodzaj property

linearyzuj(case, number, kontekst=TERAZ)

Source code in olski/skład/składnia.py
444
445
446
def linearyzuj(self, case: str, number: str, kontekst: Kontekst = TERAZ) -> Kawałek:
    głowa = self.głowa.linearyzuj(case, number, kontekst)
    return _sklej([głowa, wypisz(self.określenie, "gen", kontekst)])

__init__(głowa, określenie)

Jaki dataclass

Bases: Nominalne

Rzecz wraz z określeniem przymiotnikowym: zwykły tekst, dobry kod.

Przymiotnik zgadza się z rzeczą w przypadku, liczbie i rodzaju, a wszystkie trzy przychodzą policzone: dwa z pozycji, rodzaj z leksykonu.

Source code in olski/skład/składnia.py
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
@dataclass(frozen=True)
class Jaki(Nominalne):
    """Rzecz wraz z określeniem przymiotnikowym: zwykły tekst, dobry kod.

    Przymiotnik zgadza się z rzeczą w przypadku, liczbie i rodzaju,
    a wszystkie trzy przychodzą policzone: dwa z pozycji, rodzaj z leksykonu.
    """

    cecha: str
    rzecz: Nominalne

    @property
    def rodzaj(self) -> str:
        return self.rzecz.rodzaj

    def linearyzuj(self, case: str, number: str, kontekst: Kontekst = TERAZ) -> Kawałek:
        przymiotnik = odmień(
            self.cecha, "adj", case=case, number=number, gender=self.rodzaj, degree="pos"
        )
        return _sklej([Kawałek(przymiotnik), self.rzecz.linearyzuj(case, number, kontekst)])

cecha instance-attribute

rzecz instance-attribute

rodzaj property

linearyzuj(case, number, kontekst=TERAZ)

Source code in olski/skład/składnia.py
417
418
419
420
421
def linearyzuj(self, case: str, number: str, kontekst: Kontekst = TERAZ) -> Kawałek:
    przymiotnik = odmień(
        self.cecha, "adj", case=case, number=number, gender=self.rodzaj, degree="pos"
    )
    return _sklej([Kawałek(przymiotnik), self.rzecz.linearyzuj(case, number, kontekst)])

__init__(cecha, rzecz)

Jest dataclass

Bases: Zdanie

Orzeczenie imienne: zwykły tekst polski jest wejściem.

Orzecznik idzie w narzędniku, bo tyle bierze kopula. Szyk wychodzi z wyróżnień tak samo jak przy zdarzeniu, więc Wejściem jest zwykły tekst polski. jest tu orzecznikiem postawionym na czele wraz z podmiotem odesłanym na koniec, a nie wariantem linearyzacji.

Kopula jest polem, a nie stałą, bo autor wybiera między orzekaniem o tym, co jest, a orzekaniem o tym, co się kimś staje albo kimś zostaje, i jest to wybór dziedziny, a nie forma do policzenia. Wybór ogranicza leksykon, tak samo jak przy czynności: orzecznik w narzędniku bierze kopula i nikt poza nią, więc lemat, którego rama go nie ma, zgłasza się tutaj (olski.walencja.KOPULA).

Okoliczność dochodzi do orzekania tak samo jak do czynności, bo pytanie, na które ona odpowiada, jest w obu wypadkach to samo, i dlatego Kot jest zwierzęciem w piwnicy. wychodzi z tej kategorii.

Source code in olski/skład/składnia.py
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
@dataclass(frozen=True)
class Jest(Zdanie):
    """Orzeczenie imienne: zwykły tekst polski jest wejściem.

    Orzecznik idzie w narzędniku, bo tyle bierze kopula.
    Szyk wychodzi z wyróżnień tak samo jak przy zdarzeniu,
    więc `Wejściem jest zwykły tekst polski.` jest tu orzecznikiem postawionym
    na czele wraz z podmiotem odesłanym na koniec, a nie wariantem linearyzacji.

    Kopula jest polem, a nie stałą, bo autor wybiera między orzekaniem
    o tym, co jest, a orzekaniem o tym, co się kimś staje albo kimś zostaje,
    i jest to wybór dziedziny, a nie forma do policzenia.
    Wybór ogranicza leksykon, tak samo jak przy czynności:
    orzecznik w narzędniku bierze kopula i nikt poza nią,
    więc lemat, którego rama go nie ma, zgłasza się tutaj
    (:data:`olski.walencja.KOPULA`).

    Okoliczność dochodzi do orzekania tak samo jak do czynności,
    bo pytanie, na które ona odpowiada, jest w obu wypadkach to samo,
    i dlatego `Kot jest zwierzęciem w piwnicy.` wychodzi z tej kategorii.
    """

    #: Kopula, którą to zdanie orzeka, gdy autor żadnej nie wybrał.
    #: Bycie jest tu domyślnością, bo o zmianie nie mówi nic,
    #: a każda pozostała kopula mówi o niej coś ponadto.
    CZASOWNIK = "być"

    co: Rola | Wyróżnienie
    czym: Rola | Wyróżnienie
    czasownik: str = CZASOWNIK
    okoliczniki: tuple = ()
    przeczenie: bool = False

    def __post_init__(self) -> None:
        if ORZECZNIK not in rama(self.czasownik):
            raise PozaRamą(f"{self.czasownik} nie bierze orzecznika w narzędniku")

    @property
    def podmiot(self) -> Rola:
        return _goły(self.co)

    @property
    def konstytuenty(self) -> tuple:
        return (self.co, self.czym, *self.okoliczniki)

    def uczestnicy(self, kontekst: Kontekst = TERAZ) -> tuple[tuple[Rola, str], ...]:
        return ((self.podmiot, "nom"), (_goły(self.czym), ORZECZNIK))

    def linearyzuj(self, kontekst: Kontekst = TERAZ) -> Kawałek:
        return _szyk(
            [
                *_podmiot(self.co, kontekst),
                (None, Kawałek(self._orzeczenie(kontekst))),
                (
                    _miejsce(self.czym, kontekst),
                    wypisz(_goły(self.czym), ORZECZNIK, kontekst),
                ),
                *_okoliczności(self.okoliczniki, kontekst),
            ]
        )

CZASOWNIK = 'być' class-attribute instance-attribute

co instance-attribute

czym instance-attribute

czasownik = CZASOWNIK class-attribute instance-attribute

okoliczniki = () class-attribute instance-attribute

przeczenie = False class-attribute instance-attribute

podmiot property

konstytuenty property

__post_init__()

Source code in olski/skład/składnia.py
995
996
997
def __post_init__(self) -> None:
    if ORZECZNIK not in rama(self.czasownik):
        raise PozaRamą(f"{self.czasownik} nie bierze orzecznika w narzędniku")

uczestnicy(kontekst=TERAZ)

Source code in olski/skład/składnia.py
1007
1008
def uczestnicy(self, kontekst: Kontekst = TERAZ) -> tuple[tuple[Rola, str], ...]:
    return ((self.podmiot, "nom"), (_goły(self.czym), ORZECZNIK))

linearyzuj(kontekst=TERAZ)

Source code in olski/skład/składnia.py
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
def linearyzuj(self, kontekst: Kontekst = TERAZ) -> Kawałek:
    return _szyk(
        [
            *_podmiot(self.co, kontekst),
            (None, Kawałek(self._orzeczenie(kontekst))),
            (
                _miejsce(self.czym, kontekst),
                wypisz(_goły(self.czym), ORZECZNIK, kontekst),
            ),
            *_okoliczności(self.okoliczniki, kontekst),
        ]
    )

__init__(co, czym, czasownik=CZASOWNIK, okoliczniki=(), przeczenie=False)

Kawałek dataclass

Wypisany konstytuent wraz z przecinkami, których żąda od sąsiadów.

Przecinek jest tu własnością kawałka, a nie znakiem w napisie, bo o tym, czy staje, rozstrzyga dopiero to, co obok niego stanie, a tego kawałek o sobie nie wie. Zdanie podrzędne żąda przecinka z obu stron i dostaje go z żadnej, gdy stoi samo; opis żąda go z jednej, bo przecinek otwierający stoi w środku samego opisu. Krawędź zdania przecinka nie stawia, i tyle wystarcza, żeby kropka nie stanęła po przecinku, a lista nie dostała dwóch.

Bez tego pola przecinek jedzie wewnątrz napisu, a każde miejsce, które po konstytuencie coś stawia, musi o nim wiedzieć z ogona tego napisu. Miejsce dopisane bez tej wiedzy stawia drugi przecinek tuż za pierwszym, czyli wypuszcza tekst błędny i nigdzie nie zgłoszony.

Source code in olski/skład/składnia.py
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
@dataclass(frozen=True)
class Kawałek:
    """Wypisany konstytuent wraz z przecinkami, których żąda od sąsiadów.

    Przecinek jest tu własnością kawałka, a nie znakiem w napisie,
    bo o tym, czy staje, rozstrzyga dopiero to, co obok niego stanie,
    a tego kawałek o sobie nie wie.
    Zdanie podrzędne żąda przecinka z obu stron i dostaje go z żadnej,
    gdy stoi samo; opis żąda go z jednej,
    bo przecinek otwierający stoi w środku samego opisu.
    Krawędź zdania przecinka nie stawia, i tyle wystarcza,
    żeby kropka nie stanęła po przecinku, a lista nie dostała dwóch.

    Bez tego pola przecinek jedzie wewnątrz napisu, a każde miejsce,
    które po konstytuencie coś stawia, musi o nim wiedzieć z ogona tego napisu.
    Miejsce dopisane bez tej wiedzy stawia drugi przecinek tuż za pierwszym,
    czyli wypuszcza tekst błędny i nigdzie nie zgłoszony.
    """

    napis: str
    przed: bool = False
    po: bool = False

napis instance-attribute

przed = False class-attribute instance-attribute

po = False class-attribute instance-attribute

__init__(napis, przed=False, po=False)

Komu dataclass

Bases: Wyróżnialne

Ten, komu zdarzenie się przydarza: parser pokazuje autorowi czytania.

Kategorią dziedziny jest tu uczestnik, a nie przypadek, i dlatego stoi tu kategoria osobna, a nie druga rola wrzucona obok pierwszej. Zdarzenie ma uczestników dwóch i nie są oni wymienni: ten, komu się coś daje, mówi się albo pokazuje, jest kimś innym niż to, co się daje, i drzewo ma powiedzieć, który jest który. Że wychodzi z tego celownik, rozstrzyga rama, tak samo jak rozstrzyga ona o przypadku dopełnienia (Robi niżej).

Nazwą jest pytanie, bo polszczyzna nie ma na tego uczestnika jednego słowa: dawać stawia tam odbiorcę, pomagać tego, komu się pomaga, a dziękować tego, komu się dziękuje, i wszyscy trzej odpowiadają, komu. Tyle jest w tej konwencji nazw, ile jest w niej pytań, i tak samo nazywają się relacje okolicznikowe w olski/skład/słownik.py.

Zdarzenia ta pozycja nie bierze i tym różni się od okoliczności: w celowniku stoi w polszczyźnie grupa imienna, a zdarzenie wypełnia pozycję ramy bezokolicznikiem albo treścią, czyli pozycją osobną (Treść wyżej).

Source code in olski/skład/składnia.py
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
@dataclass(frozen=True)
class Komu(Wyróżnialne):
    """Ten, komu zdarzenie się przydarza: parser pokazuje autorowi czytania.

    Kategorią dziedziny jest tu uczestnik, a nie przypadek, i dlatego stoi tu
    kategoria osobna, a nie druga rola wrzucona obok pierwszej.
    Zdarzenie ma uczestników dwóch i nie są oni wymienni:
    ten, komu się coś daje, mówi się albo pokazuje, jest kimś innym niż to,
    co się daje, i drzewo ma powiedzieć, który jest który.
    Że wychodzi z tego celownik, rozstrzyga rama, tak samo jak rozstrzyga ona
    o przypadku dopełnienia (``Robi`` niżej).

    Nazwą jest pytanie, bo polszczyzna nie ma na tego uczestnika jednego słowa:
    ``dawać`` stawia tam odbiorcę, ``pomagać`` tego, komu się pomaga,
    a ``dziękować`` tego, komu się dziękuje, i wszyscy trzej odpowiadają, komu.
    Tyle jest w tej konwencji nazw, ile jest w niej pytań,
    i tak samo nazywają się relacje okolicznikowe w ``olski/skład/słownik.py``.

    Zdarzenia ta pozycja nie bierze i tym różni się od okoliczności:
    w celowniku stoi w polszczyźnie grupa imienna,
    a zdarzenie wypełnia pozycję ramy bezokolicznikiem albo treścią,
    czyli pozycją osobną (``Treść`` wyżej).
    """

    co: Rola

    def linearyzuj(self, kontekst: Kontekst = TERAZ) -> Kawałek:
        return wypisz(self.co, CELOWNIK, kontekst)

co instance-attribute

linearyzuj(kontekst=TERAZ)

Source code in olski/skład/składnia.py
629
630
def linearyzuj(self, kontekst: Kontekst = TERAZ) -> Kawałek:
    return wypisz(self.co, CELOWNIK, kontekst)

__init__(co)

Kontekst dataclass

Czego linearyzacja nie znajduje w drzewie, które właśnie wypisuje.

Pierwsze dwie rzeczy są własnościami tekstu, a nie zdania, więc zdanie ich w sobie nie trzyma: ta sama rzecz opowiedziana raz jako to, co się stało, a raz jako to, co się dzieje, jest jednym drzewem i dwoma czasami. Kto tymi dwoma steruje, mówi olski/skład/opowieść.py.

Pozostałe są własnościami miejsca, w którym zdanie stoi. Zdanie wypisywane jako opis rzeczy mówi o tej rzeczy zaimkiem, a nie nazwą. Zdanie wypisywane jako dopełnienie czasownika nad nim nie ma podmiotu wcale, bo wykonawcę bierze stamtąd, i wychodzi bezokolicznikiem; to samo miejsce niesie przeczenie tamtego czasownika, bo dopełniacz negacji sięga przez bezokolicznik do jego dopełnienia. Steruje tym wszystkim drzewo, a nie tekst, a mechanizmy trzymają Opis oraz Robi niżej. Stoją tu obok czasu, bo pytanie jest jedno: czego wypisywane drzewo o sobie nie wie.

Wartość domyślna jest zdaniem stojącym samo: dzieje się teraz, nie ma za sobą nikogo, kogo dałoby się pominąć, niczego nie opisuje, orzeka o własnym podmiocie i nikt go nie przeczy.

Source code in olski/skład/składnia.py
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
@dataclass(frozen=True)
class Kontekst:
    """Czego linearyzacja nie znajduje w drzewie, które właśnie wypisuje.

    Pierwsze dwie rzeczy są własnościami tekstu, a nie zdania,
    więc zdanie ich w sobie nie trzyma:
    ta sama rzecz opowiedziana raz jako to, co się stało, a raz jako to, co się dzieje,
    jest jednym drzewem i dwoma czasami.
    Kto tymi dwoma steruje, mówi ``olski/skład/opowieść.py``.

    Pozostałe są własnościami miejsca, w którym zdanie stoi.
    Zdanie wypisywane jako opis rzeczy mówi o tej rzeczy zaimkiem, a nie nazwą.
    Zdanie wypisywane jako dopełnienie czasownika nad nim nie ma podmiotu wcale,
    bo wykonawcę bierze stamtąd, i wychodzi bezokolicznikiem;
    to samo miejsce niesie przeczenie tamtego czasownika,
    bo dopełniacz negacji sięga przez bezokolicznik do jego dopełnienia.
    Steruje tym wszystkim drzewo, a nie tekst,
    a mechanizmy trzymają ``Opis`` oraz ``Robi`` niżej.
    Stoją tu obok czasu, bo pytanie jest jedno:
    czego wypisywane drzewo o sobie nie wie.

    Wartość domyślna jest zdaniem stojącym samo:
    dzieje się teraz, nie ma za sobą nikogo, kogo dałoby się pominąć,
    niczego nie opisuje, orzeka o własnym podmiocie i nikt go nie przeczy.
    """

    czas: str = "teraz"
    pomijany: object = None
    wskazywany: object = None
    sprawca: object = None
    pod_przeczeniem: bool = False

    def podrzędne(self) -> Kontekst:
        """Kontekst, który dostaje zdanie postawione pod tym zdaniem.

        Czas dziedziczy się, bo jest własnością opowiadania, a nie zdania.
        Reszta nie dziedziczy się i każde pole ma na to własny powód:
        zaimek względny wyszedłby z niższego zdania na czoło, którego ono nie ma,
        podmiot opuszczony odsyłałby tam, gdzie stoi ktoś inny,
        a bezokolicznik i przeczenie sięgają jednego piętra,
        bo tyle sięga czasownik, który je narzucił.
        Stoi to jedną metodą, bo pole dopisane do tej klasy i tu pominięte
        przeciekłoby w dół po cichu, i to w miejscu, którego autor nie widzi.
        """
        return Kontekst(czas=self.czas)

    def pomija(self, rola: Rola) -> bool:
        """Czy podmiot jest tym, o kim mowa była zdanie wcześniej.

        Pominięty podmiot jest w polszczyźnie zwykłym sposobem mówienia dalej
        o tym samym, bo osobę i rodzaj niesie sam czasownik,
        więc nie ma czego powtarzać.
        """
        return self.pomijany is not None and rola.tożsamość is self.pomijany

    def wypisuje(self, rola: Rola) -> bool:
        """Czy podmiot wyjdzie w tekście, czy czytelnik odzyska go bez niego.

        Powody są dwa i schodzą się tutaj, bo pytają o nie dwa miejsca:
        linearyzacja, żeby podmiotu nie wypisać,
        i ``olski/skład/przegląd.py``, żeby nie liczyć formy, której nikt nie zobaczy.
        Zdanie obok orzekało o tym samym i wtedy mówi o tym ``pomija`` wyżej,
        albo wykonawcę wskazał czasownik nad tym zdaniem i wtedy wychodzi
        bezokolicznik, który podmiotu nie ma wcale.
        """
        return self.sprawca is None and not self.pomija(rola)

    def wskazuje(self, rola: Rola) -> bool:
        """Czy to ta rola, którą wypisywane zdanie wskazuje.

        Porównaniem jest tożsamość obiektu, a nie równość,
        bo tą samą rzeczą jest tu ta sama zmienna, tak samo jak przy ``Postać``:
        dwie równe grupy imienne są dwiema rzeczami, dopóki autor nie użyje jednej.
        """
        return self.wskazywany is not None and _rdzeń(rola) is _rdzeń(self.wskazywany)

czas = 'teraz' class-attribute instance-attribute

pomijany = None class-attribute instance-attribute

wskazywany = None class-attribute instance-attribute

sprawca = None class-attribute instance-attribute

pod_przeczeniem = False class-attribute instance-attribute

podrzędne()

Kontekst, który dostaje zdanie postawione pod tym zdaniem.

Czas dziedziczy się, bo jest własnością opowiadania, a nie zdania. Reszta nie dziedziczy się i każde pole ma na to własny powód: zaimek względny wyszedłby z niższego zdania na czoło, którego ono nie ma, podmiot opuszczony odsyłałby tam, gdzie stoi ktoś inny, a bezokolicznik i przeczenie sięgają jednego piętra, bo tyle sięga czasownik, który je narzucił. Stoi to jedną metodą, bo pole dopisane do tej klasy i tu pominięte przeciekłoby w dół po cichu, i to w miejscu, którego autor nie widzi.

Source code in olski/skład/składnia.py
157
158
159
160
161
162
163
164
165
166
167
168
169
def podrzędne(self) -> Kontekst:
    """Kontekst, który dostaje zdanie postawione pod tym zdaniem.

    Czas dziedziczy się, bo jest własnością opowiadania, a nie zdania.
    Reszta nie dziedziczy się i każde pole ma na to własny powód:
    zaimek względny wyszedłby z niższego zdania na czoło, którego ono nie ma,
    podmiot opuszczony odsyłałby tam, gdzie stoi ktoś inny,
    a bezokolicznik i przeczenie sięgają jednego piętra,
    bo tyle sięga czasownik, który je narzucił.
    Stoi to jedną metodą, bo pole dopisane do tej klasy i tu pominięte
    przeciekłoby w dół po cichu, i to w miejscu, którego autor nie widzi.
    """
    return Kontekst(czas=self.czas)

pomija(rola)

Czy podmiot jest tym, o kim mowa była zdanie wcześniej.

Pominięty podmiot jest w polszczyźnie zwykłym sposobem mówienia dalej o tym samym, bo osobę i rodzaj niesie sam czasownik, więc nie ma czego powtarzać.

Source code in olski/skład/składnia.py
171
172
173
174
175
176
177
178
def pomija(self, rola: Rola) -> bool:
    """Czy podmiot jest tym, o kim mowa była zdanie wcześniej.

    Pominięty podmiot jest w polszczyźnie zwykłym sposobem mówienia dalej
    o tym samym, bo osobę i rodzaj niesie sam czasownik,
    więc nie ma czego powtarzać.
    """
    return self.pomijany is not None and rola.tożsamość is self.pomijany

wypisuje(rola)

Czy podmiot wyjdzie w tekście, czy czytelnik odzyska go bez niego.

Powody są dwa i schodzą się tutaj, bo pytają o nie dwa miejsca: linearyzacja, żeby podmiotu nie wypisać, i olski/skład/przegląd.py, żeby nie liczyć formy, której nikt nie zobaczy. Zdanie obok orzekało o tym samym i wtedy mówi o tym pomija wyżej, albo wykonawcę wskazał czasownik nad tym zdaniem i wtedy wychodzi bezokolicznik, który podmiotu nie ma wcale.

Source code in olski/skład/składnia.py
180
181
182
183
184
185
186
187
188
189
190
def wypisuje(self, rola: Rola) -> bool:
    """Czy podmiot wyjdzie w tekście, czy czytelnik odzyska go bez niego.

    Powody są dwa i schodzą się tutaj, bo pytają o nie dwa miejsca:
    linearyzacja, żeby podmiotu nie wypisać,
    i ``olski/skład/przegląd.py``, żeby nie liczyć formy, której nikt nie zobaczy.
    Zdanie obok orzekało o tym samym i wtedy mówi o tym ``pomija`` wyżej,
    albo wykonawcę wskazał czasownik nad tym zdaniem i wtedy wychodzi
    bezokolicznik, który podmiotu nie ma wcale.
    """
    return self.sprawca is None and not self.pomija(rola)

wskazuje(rola)

Czy to ta rola, którą wypisywane zdanie wskazuje.

Porównaniem jest tożsamość obiektu, a nie równość, bo tą samą rzeczą jest tu ta sama zmienna, tak samo jak przy Postać: dwie równe grupy imienne są dwiema rzeczami, dopóki autor nie użyje jednej.

Source code in olski/skład/składnia.py
192
193
194
195
196
197
198
199
def wskazuje(self, rola: Rola) -> bool:
    """Czy to ta rola, którą wypisywane zdanie wskazuje.

    Porównaniem jest tożsamość obiektu, a nie równość,
    bo tą samą rzeczą jest tu ta sama zmienna, tak samo jak przy ``Postać``:
    dwie równe grupy imienne są dwiema rzeczami, dopóki autor nie użyje jednej.
    """
    return self.wskazywany is not None and _rdzeń(rola) is _rdzeń(self.wskazywany)

__init__(czas='teraz', pomijany=None, wskazywany=None, sprawca=None, pod_przeczeniem=False)

Koordynacja dataclass

Bases: Rola

Kilka bytów w jednej roli: koguci dziób, wężowy ogon i żabie oczy.

Przypadek dostają wszystkie człony ten sam, bo daje go jedna pozycja, a liczbę każdy własną, bo każdy jest osobną rzeczą. Rodzaj wychodzi z członów i wychodzi po polsku: dość jednego męskoosobowego, żeby cała grupa była męskoosobowa, a bez niego rodzaj bierze się z pierwszego, bo formy niemęskoosobowe czasownik ma wspólne.

Przecinek stoi między wszystkimi członami prócz ostatniego, a przed ostatnim staje spójnik, i to jest polska interpunkcja tej listy.

Source code in olski/skład/składnia.py
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
@dataclass(frozen=True)
class Koordynacja(Rola):
    """Kilka bytów w jednej roli: koguci dziób, wężowy ogon i żabie oczy.

    Przypadek dostają wszystkie człony ten sam, bo daje go jedna pozycja,
    a liczbę każdy własną, bo każdy jest osobną rzeczą.
    Rodzaj wychodzi z członów i wychodzi po polsku:
    dość jednego męskoosobowego, żeby cała grupa była męskoosobowa,
    a bez niego rodzaj bierze się z pierwszego,
    bo formy niemęskoosobowe czasownik ma wspólne.

    Przecinek stoi między wszystkimi członami prócz ostatniego,
    a przed ostatnim staje spójnik, i to jest polska interpunkcja tej listy.
    """

    człony: tuple[Rola, ...]

    #: Liczba grupy, a nie któregokolwiek z członów: dwie rzeczy to więcej niż jedna.
    number = "pl"

    @property
    def rodzaj(self) -> str:
        rodzaje = [człon.rodzaj for człon in self.człony]
        return "m1" if "m1" in rodzaje else rodzaje[0]

    def __and__(self, inne) -> Koordynacja:
        return Koordynacja((*self.człony, byt(inne)))

    def linearyzuj(self, case: str, kontekst: Kontekst = TERAZ) -> Kawałek:
        return _lista([wypisz(człon, case, kontekst) for człon in self.człony])

człony instance-attribute

number = 'pl' class-attribute instance-attribute

rodzaj property

__and__(inne)

Source code in olski/skład/składnia.py
523
524
def __and__(self, inne) -> Koordynacja:
    return Koordynacja((*self.człony, byt(inne)))

linearyzuj(case, kontekst=TERAZ)

Source code in olski/skład/składnia.py
526
527
def linearyzuj(self, case: str, kontekst: Kontekst = TERAZ) -> Kawałek:
    return _lista([wypisz(człon, case, kontekst) for człon in self.człony])

__init__(człony)

Nominalne

Bases: Wyróżnialne

Wszystko, co może stanąć w grupie imiennej, wraz z zapisem operatorowym.

Operatory stoją tutaj, a nie warstwę wyżej, bo są zapisem konstruktorów, a nie drugim sposobem mówienia: a / b buduje dokładnie Czyj(a, byt(b)). Zdejmowalną warstwą są same przestrzenie nazw w olski.skład.słownik.

Kontekst wchodzi do każdej linearyzacji poniżej, choć rzeczownik go nie czyta. Bierze się to z Czyj: określeniem bywa rzecz opisana zdaniem, a zdanie pyta o czas i o to, czy mówić o rzeczy zaimkiem, więc gałąź, która kontekstu nie przekazuje, gubi go dopiero pod sobą.

Source code in olski/skład/składnia.py
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
class Nominalne(Wyróżnialne):
    """Wszystko, co może stanąć w grupie imiennej, wraz z zapisem operatorowym.

    Operatory stoją tutaj, a nie warstwę wyżej, bo są zapisem konstruktorów,
    a nie drugim sposobem mówienia: ``a / b`` buduje dokładnie ``Czyj(a, byt(b))``.
    Zdejmowalną warstwą są same przestrzenie nazw w ``olski.skład.słownik``.

    Kontekst wchodzi do każdej linearyzacji poniżej, choć rzeczownik go nie czyta.
    Bierze się to z ``Czyj``: określeniem bywa rzecz opisana zdaniem,
    a zdanie pyta o czas i o to, czy mówić o rzeczy zaimkiem,
    więc gałąź, która kontekstu nie przekazuje, gubi go dopiero pod sobą.
    """

    def __truediv__(self, inne) -> Czyj:
        """Dopełniacz, czyli określenie po głowie: parser przez podzbiór."""
        return Czyj(self, byt(inne))

    def __invert__(self) -> Byt:
        """Liczba mnoga."""
        return Byt(self, "pl")

    def __and__(self, inne) -> Koordynacja:
        """Koordynacja: koguci dziób oraz wężowy ogon."""
        return byt(self) & inne

__truediv__(inne)

Dopełniacz, czyli określenie po głowie: parser przez podzbiór.

Source code in olski/skład/składnia.py
375
376
377
def __truediv__(self, inne) -> Czyj:
    """Dopełniacz, czyli określenie po głowie: parser przez podzbiór."""
    return Czyj(self, byt(inne))

__invert__()

Liczba mnoga.

Source code in olski/skład/składnia.py
379
380
381
def __invert__(self) -> Byt:
    """Liczba mnoga."""
    return Byt(self, "pl")

__and__(inne)

Koordynacja: koguci dziób oraz wężowy ogon.

Source code in olski/skład/składnia.py
383
384
385
def __and__(self, inne) -> Koordynacja:
    """Koordynacja: koguci dziób oraz wężowy ogon."""
    return byt(self) & inne

Okolicznik dataclass

Bases: Wyróżnialne

Okoliczność w relacji: w piwnicy, wzrokiem, gdy bazyliszek otworzył oczy.

Relacja jest kategorią dziedziny i to ona stoi w drzewie, a słowo, którym polszczyzna ją wyraża, rozstrzyga o sobie tyle, ile go od relacji odróżnia: w mówi, gdzie i kiedy, a gdy mówi tylko kiedy.

Okoliczność bywa rzeczą albo zdarzeniem i jest to jedna kategoria, bo pytanie stawia się jedno. Różnią się one tym, czym słowo przed nimi jest po polsku: przed rzeczą stoi przyimek, który rządzi przypadkiem (olski/skład/przyimki.py), a przed zdarzeniem spójnik, który nie rządzi niczym (olski/skład/spójniki.py), bo zdanie podrzędne rozdaje przypadki własne. Przyimkiem żadnym jest pusty napis, bo część relacji polszczyzna wyraża samym przypadkiem, a rola bez przyimka jest tu tą samą kategorią co z nim. Narzędzie wychodzi tak zawsze, a czas ma obie drogi naraz: wieczorem i w nocy odpowiadają na jedno pytanie i różnią się tym, czy relacja wyszła na wierzch słowem.

Przyłączenie stoi w drzewie i to jest cała różnica między tym kierunkiem a parserem, któremu docs/subset.md zostawia je przy czytelniku: okolicznik postawiony przy czasowniku i określenie postawione przy rzeczy są dwoma różnymi drzewami, więc nie ma tu czego rozstrzygać po fakcie.

Source code in olski/skład/składnia.py
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
@dataclass(frozen=True)
class Okolicznik(Wyróżnialne):
    """Okoliczność w relacji: w piwnicy, wzrokiem, gdy bazyliszek otworzył oczy.

    Relacja jest kategorią dziedziny i to ona stoi w drzewie,
    a słowo, którym polszczyzna ją wyraża, rozstrzyga o sobie tyle,
    ile go od relacji odróżnia: ``w`` mówi, gdzie i kiedy,
    a ``gdy`` mówi tylko kiedy.

    Okoliczność bywa rzeczą albo zdarzeniem i jest to jedna kategoria,
    bo pytanie stawia się jedno.
    Różnią się one tym, czym słowo przed nimi jest po polsku:
    przed rzeczą stoi przyimek, który rządzi przypadkiem (``olski/skład/przyimki.py``),
    a przed zdarzeniem spójnik, który nie rządzi niczym (``olski/skład/spójniki.py``),
    bo zdanie podrzędne rozdaje przypadki własne.
    Przyimkiem żadnym jest pusty napis, bo część relacji polszczyzna wyraża
    samym przypadkiem, a rola bez przyimka jest tu tą samą kategorią co z nim.
    Narzędzie wychodzi tak zawsze, a czas ma obie drogi naraz:
    `wieczorem` i `w nocy` odpowiadają na jedno pytanie
    i różnią się tym, czy relacja wyszła na wierzch słowem.

    Przyłączenie stoi w drzewie i to jest cała różnica między tym kierunkiem
    a parserem, któremu ``docs/subset.md`` zostawia je przy czytelniku:
    okolicznik postawiony przy czasowniku i określenie postawione przy rzeczy
    są dwoma różnymi drzewami, więc nie ma tu czego rozstrzygać po fakcie.
    """

    słowo: str
    relacja: str
    co: Rola | Zdanie

    @property
    def zdarzeniem(self) -> bool:
        """Czy pod tą okolicznością stoi zdarzenie, a nie rzecz."""
        return isinstance(self.co, Zdanie)

    @property
    def wysuwalna(self) -> bool:
        """Czy wolno postawić tę okoliczność na czele zdania.

        Grupa imienna staje na czele zawsze, bo szyk polszczyzny jest swobodny
        i o wysunięciu rozstrzyga to, o czym zdanie jest.
        Zdarzenie staje tam, gdy pozwala na to jego spójnik,
        i to jest jedyne miejsce w tym pliku, w którym leksykon mówi o szyku.
        """
        return not self.zdarzeniem or staje_na_czele(self.słowo, self.relacja)

    def __post_init__(self) -> None:
        if self.zdarzeniem:
            znane = wprowadza(self.słowo, self.relacja)
        else:
            znane = przypadek(self.słowo, self.relacja) is not None
        if not znane:
            raise PozaRamą(f"{self.słowo or 'sam narzędnik'} nie stoi w relacji {self.relacja}")

    def linearyzuj(self, kontekst: Kontekst = TERAZ) -> Kawałek:
        """Słowo wraz z tym, co po nim stoi: zdanie podrzędne albo grupa imienna."""
        if self.zdarzeniem:
            return _podrzędne(self.słowo, self.co, kontekst)
        grupa = wypisz(self.co, przypadek(self.słowo, self.relacja), kontekst)
        return _sklej([Kawałek(self.słowo), grupa]) if self.słowo else grupa

słowo instance-attribute

relacja instance-attribute

co instance-attribute

zdarzeniem property

Czy pod tą okolicznością stoi zdarzenie, a nie rzecz.

wysuwalna property

Czy wolno postawić tę okoliczność na czele zdania.

Grupa imienna staje na czele zawsze, bo szyk polszczyzny jest swobodny i o wysunięciu rozstrzyga to, o czym zdanie jest. Zdarzenie staje tam, gdy pozwala na to jego spójnik, i to jest jedyne miejsce w tym pliku, w którym leksykon mówi o szyku.

__post_init__()

Source code in olski/skład/składnia.py
587
588
589
590
591
592
593
def __post_init__(self) -> None:
    if self.zdarzeniem:
        znane = wprowadza(self.słowo, self.relacja)
    else:
        znane = przypadek(self.słowo, self.relacja) is not None
    if not znane:
        raise PozaRamą(f"{self.słowo or 'sam narzędnik'} nie stoi w relacji {self.relacja}")

linearyzuj(kontekst=TERAZ)

Słowo wraz z tym, co po nim stoi: zdanie podrzędne albo grupa imienna.

Source code in olski/skład/składnia.py
595
596
597
598
599
600
def linearyzuj(self, kontekst: Kontekst = TERAZ) -> Kawałek:
    """Słowo wraz z tym, co po nim stoi: zdanie podrzędne albo grupa imienna."""
    if self.zdarzeniem:
        return _podrzędne(self.słowo, self.co, kontekst)
    grupa = wypisz(self.co, przypadek(self.słowo, self.relacja), kontekst)
    return _sklej([Kawałek(self.słowo), grupa]) if self.słowo else grupa

__init__(słowo, relacja, co)

Opis dataclass

Bases: Rola

Rzecz wskazana zdarzeniem, w którym stoi: postaci, których nikt nie liczył.

Kategorią dziedziny jest tu wskazywanie, a nie zdanie podrzędne. Jaki wskazuje rzecz cechą, ta klasa wskazuje ją zdarzeniem, i pytanie jest w obu wypadkach jedno: o którą rzecz mowa. Że wychodzi z tego przydawka zdaniowa wraz z zaimkiem i przecinkami, rozstrzyga linearyzacja, tak samo jak rozstrzyga przypadek.

Które miejsce w zdarzeniu zostaje zaimkiem, mówi tożsamość obiektu, a nie osobny znacznik postawiony w tym miejscu. Autor pisze rzecz raz i stawia tę samą zmienną w zdaniu, które ją opisuje, czyli robi to samo, co robi z Postać w olski/skład/opowieść.py: tam ta sama zmienna dwa razy jest jedną rzeczą w dwóch zdaniach, a tutaj jest jedną rzeczą w zdaniu nadrzędnym i podrzędnym naraz.

Zdanie, które tej rzeczy nie stawia w miejscu, skąd zaimek wyjdzie na czoło, zgłasza się od razu, bo opis, który nie opisuje, jest błędem drzewa. Czym jest to miejsce, mówi _wskazany.

Source code in olski/skład/składnia.py
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
@dataclass(frozen=True)
class Opis(Rola):
    """Rzecz wskazana zdarzeniem, w którym stoi: postaci, których nikt nie liczył.

    Kategorią dziedziny jest tu wskazywanie, a nie zdanie podrzędne.
    ``Jaki`` wskazuje rzecz cechą, ta klasa wskazuje ją zdarzeniem,
    i pytanie jest w obu wypadkach jedno: o którą rzecz mowa.
    Że wychodzi z tego przydawka zdaniowa wraz z zaimkiem i przecinkami,
    rozstrzyga linearyzacja, tak samo jak rozstrzyga przypadek.

    Które miejsce w zdarzeniu zostaje zaimkiem, mówi tożsamość obiektu,
    a nie osobny znacznik postawiony w tym miejscu.
    Autor pisze rzecz raz i stawia tę samą zmienną w zdaniu, które ją opisuje,
    czyli robi to samo, co robi z ``Postać`` w ``olski/skład/opowieść.py``:
    tam ta sama zmienna dwa razy jest jedną rzeczą w dwóch zdaniach,
    a tutaj jest jedną rzeczą w zdaniu nadrzędnym i podrzędnym naraz.

    Zdanie, które tej rzeczy nie stawia w miejscu, skąd zaimek wyjdzie na czoło,
    zgłasza się od razu, bo opis, który nie opisuje, jest błędem drzewa.
    Czym jest to miejsce, mówi ``_wskazany``.
    """

    rzecz: Rola
    zdanie: object

    def __post_init__(self) -> None:
        kontekst = Kontekst(wskazywany=self.rzecz)
        if not any(_wskazany(część, kontekst) for część in self.zdanie.konstytuenty):
            raise PozaRamą("zdanie opisujące nie stawia opisywanej rzeczy")

    @property
    def number(self) -> str:
        return self.rzecz.number

    @property
    def rodzaj(self) -> str:
        return self.rzecz.rodzaj

    @property
    def tożsamość(self):
        return self.rzecz.tożsamość

    def wewnątrz(self, kontekst: Kontekst) -> Kontekst:
        """Kontekst zdania opisującego: podrzędne wraz z rzeczą, którą ma wskazać.

        Wydzielone z linearyzacji, bo pyta o to samo ``_zdania_pod``,
        a bez tej rzeczy opis wychodziłby stamtąd zdaniem, w którym zaimka nie ma,
        czyli napisem, którego autor nie dostał.
        """
        return replace(kontekst.podrzędne(), wskazywany=self.rzecz)

    def linearyzuj(self, case: str, kontekst: Kontekst = TERAZ) -> Kawałek:
        """Rzecz, przecinek, zdanie o niej, a przecinek zamykający jako żądanie.

        Przypadek dostaje sama rzecz, bo to ona stoi w zdaniu nadrzędnym,
        a zdanie podrzędne rozdaje przypadki własne i dostaje od ``podrzędne``
        czas oraz od tej metody to, którą rzecz ma powiedzieć zaimkiem.
        Pomijanie podmiotu w nim nie działa, i to nie jest brak:
        podmiot opuszczony w zdaniu podrzędnym czytałby się jako ten,
        którego zaimek właśnie zastąpił.

        Przecinek otwierający staje tutaj, bo stoi w środku tego kawałka,
        a zamykający zostaje żądaniem, bo stoi na jego krańcu
        i rozstrzyga o nim to, co obok stanie.
        """
        zdanie = replace(self.zdanie.linearyzuj(self.wewnątrz(kontekst)), przed=True)
        return replace(_sklej([wypisz(self.rzecz, case, kontekst), zdanie]), po=True)

rzecz instance-attribute

zdanie instance-attribute

number property

rodzaj property

tożsamość property

__post_init__()

Source code in olski/skład/składnia.py
1415
1416
1417
1418
def __post_init__(self) -> None:
    kontekst = Kontekst(wskazywany=self.rzecz)
    if not any(_wskazany(część, kontekst) for część in self.zdanie.konstytuenty):
        raise PozaRamą("zdanie opisujące nie stawia opisywanej rzeczy")

wewnątrz(kontekst)

Kontekst zdania opisującego: podrzędne wraz z rzeczą, którą ma wskazać.

Wydzielone z linearyzacji, bo pyta o to samo _zdania_pod, a bez tej rzeczy opis wychodziłby stamtąd zdaniem, w którym zaimka nie ma, czyli napisem, którego autor nie dostał.

Source code in olski/skład/składnia.py
1432
1433
1434
1435
1436
1437
1438
1439
def wewnątrz(self, kontekst: Kontekst) -> Kontekst:
    """Kontekst zdania opisującego: podrzędne wraz z rzeczą, którą ma wskazać.

    Wydzielone z linearyzacji, bo pyta o to samo ``_zdania_pod``,
    a bez tej rzeczy opis wychodziłby stamtąd zdaniem, w którym zaimka nie ma,
    czyli napisem, którego autor nie dostał.
    """
    return replace(kontekst.podrzędne(), wskazywany=self.rzecz)

linearyzuj(case, kontekst=TERAZ)

Rzecz, przecinek, zdanie o niej, a przecinek zamykający jako żądanie.

Przypadek dostaje sama rzecz, bo to ona stoi w zdaniu nadrzędnym, a zdanie podrzędne rozdaje przypadki własne i dostaje od podrzędne czas oraz od tej metody to, którą rzecz ma powiedzieć zaimkiem. Pomijanie podmiotu w nim nie działa, i to nie jest brak: podmiot opuszczony w zdaniu podrzędnym czytałby się jako ten, którego zaimek właśnie zastąpił.

Przecinek otwierający staje tutaj, bo stoi w środku tego kawałka, a zamykający zostaje żądaniem, bo stoi na jego krańcu i rozstrzyga o nim to, co obok stanie.

Source code in olski/skład/składnia.py
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
def linearyzuj(self, case: str, kontekst: Kontekst = TERAZ) -> Kawałek:
    """Rzecz, przecinek, zdanie o niej, a przecinek zamykający jako żądanie.

    Przypadek dostaje sama rzecz, bo to ona stoi w zdaniu nadrzędnym,
    a zdanie podrzędne rozdaje przypadki własne i dostaje od ``podrzędne``
    czas oraz od tej metody to, którą rzecz ma powiedzieć zaimkiem.
    Pomijanie podmiotu w nim nie działa, i to nie jest brak:
    podmiot opuszczony w zdaniu podrzędnym czytałby się jako ten,
    którego zaimek właśnie zastąpił.

    Przecinek otwierający staje tutaj, bo stoi w środku tego kawałka,
    a zamykający zostaje żądaniem, bo stoi na jego krańcu
    i rozstrzyga o nim to, co obok stanie.
    """
    zdanie = replace(self.zdanie.linearyzuj(self.wewnątrz(kontekst)), przed=True)
    return replace(_sklej([wypisz(self.rzecz, case, kontekst), zdanie]), po=True)

__init__(rzecz, zdanie)

PozaRamą

Bases: Exception

Drzewo żąda od słowa pozycji, której jego rama nie ma.

Wyjątek, a nie zdanie wypuszczone mimo to, z tego samego powodu co BrakFormy w olski/skład/morfologia.py: to jest błąd kompilacji, bo Linter pomaga dobry kod. nie jest zdaniem polskim i nikt takiego nie chciał napisać.

Ramę ma tu czasownik, przyimek i spójnik, a pytanie jest we wszystkich trzech wypadkach jedno: czy leksykon zna to, co autor postawił w drzewie. Spójnik pytany jest przy tym o dwie rzeczy, bo o dwóch mówi: o relacji, w której stoi, i o tym, czy jego zdanie staje na czele pary.

Source code in olski/skład/składnia.py
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
class PozaRamą(Exception):
    """Drzewo żąda od słowa pozycji, której jego rama nie ma.

    Wyjątek, a nie zdanie wypuszczone mimo to,
    z tego samego powodu co ``BrakFormy`` w ``olski/skład/morfologia.py``:
    to jest błąd kompilacji,
    bo `Linter pomaga dobry kod.` nie jest zdaniem polskim
    i nikt takiego nie chciał napisać.

    Ramę ma tu czasownik, przyimek i spójnik,
    a pytanie jest we wszystkich trzech wypadkach jedno:
    czy leksykon zna to, co autor postawił w drzewie.
    Spójnik pytany jest przy tym o dwie rzeczy, bo o dwóch mówi:
    o relacji, w której stoi, i o tym, czy jego zdanie staje na czele pary.
    """

Przysłówek dataclass

Bases: Wyróżnialne

Okoliczność wyrażona jednym słowem: wkrótce, nagle.

Stopnia drzewo nie niesie i dlatego linearyzacja żąda równego: przysłówek w stopniu wyższym mówi co innego niż w równym, a mówienie tego dopiero czeka na kategorię. Przysłówka, który stopnia nie ma, żądanie to nie dotyczy, i rozstrzyga to odmień w olski/skład/morfologia.py.

Source code in olski/skład/składnia.py
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
@dataclass(frozen=True)
class Przysłówek(Wyróżnialne):
    """Okoliczność wyrażona jednym słowem: wkrótce, nagle.

    Stopnia drzewo nie niesie i dlatego linearyzacja żąda równego:
    przysłówek w stopniu wyższym mówi co innego niż w równym,
    a mówienie tego dopiero czeka na kategorię.
    Przysłówka, który stopnia nie ma, żądanie to nie dotyczy,
    i rozstrzyga to ``odmień`` w ``olski/skład/morfologia.py``.
    """

    lemat: str

    def linearyzuj(self, kontekst: Kontekst = TERAZ) -> Kawałek:
        return Kawałek(odmień(self.lemat, "adv", degree="pos"))

lemat instance-attribute

linearyzuj(kontekst=TERAZ)

Source code in olski/skład/składnia.py
646
647
def linearyzuj(self, kontekst: Kontekst = TERAZ) -> Kawałek:
    return Kawałek(odmień(self.lemat, "adv", degree="pos"))

__init__(lemat)

Robi dataclass

Bases: Zdanie

Zdanie o czynności: program zapisuje ustawienia.

Dopełnienie nie pyta, czy stoi pod nim rzecz, czy zdarzenie, i jest to ta sama jedna kategoria, którą Okolicznik ma o piętro obok. Czeladnik zaczął pracę. i Czeladnik zaczął pracować. mówią, co zaczął, a różnią się tym, czy zaczął rzecz, czy zdarzenie. Że wychodzi z tego raz biernik, a raz bezokolicznik bez podmiotu, rozstrzyga linearyzacja, tak samo jak rozstrzyga przypadek. Trzecią rzeczą, która tam stoi, jest Treść wyżej, czyli zdarzenie, o którym podmiot coś orzeka, zamiast je wykonywać.

Pytana o wszystkie trzy jest rama z leksykonu walencyjnego, bo wszystkie są jej pozycjami, a pytanie pada jedno: czy pozycja, którą ten konstytuent zajmuje, stoi w ramie tego czasownika. Rama jest zbiorem, więc pozycja dopisana do leksykonu nie dokłada tu gałęzi (rama w olski/walencja.py). Pytany jest ten sam plik, o który pyta parser po drugiej stronie, bo rama jest faktem o słowie, a nie o kierunku. Ostatnie z tych pytań waży najwięcej przy czasowniku, który bierze i biernik: zamykać biernik bierze, a Zamykał, że okno stało. nie jest zdaniem, i to leksykon jest jedyną rzeczą, która te dwa czasowniki rozdziela.

Dopełnienie pyta przy tym o dwa przypadki naraz i staje w tym, który rama ma, bo przypadek bierze się tu z pozycji jak wszędzie indziej: Czeladnik szukał córki krawca. i Czeladnik zasłonił twarz. wychodzą z drzewa tego samego kształtu, a autor nie pisze przypadka w żadnym (PRZYPADKI_DOPEŁNIENIA).

Uczestnik w celowniku stoi obok tego dopełnienia, a nie zamiast niego, i dlatego ma tu osobne pole: Parser pokazuje autorowi czytania. wypełnia dwie pozycje ramy naraz, a o tym, która rzecz stoi w której, mówi Komu wyżej.

Kopuli ta kategoria nie bierze wcale, i jest to ta sama odmowa co powyższe: rama kopuli ma orzecznik, a orzecznikiem orzeka Jest obok, więc Parser jest. nie wychodzi stąd tak samo, jak nie wyprowadza się z olskiego.

Sprawca bezokolicznika stoi w drzewie, a nie w leksykonie, i jest nim ta sama zmienna postawiona dwa razy, jak w Opis i w Postać. Drzewo, które postawiło tam kogoś innego, zgłasza się, bo bezokolicznik podmiotu nie ma i wyszedłby tekstem o kimś innym; czego polszczyzna mówi tam zamiast niego, trzyma docs/kategorie-zapisu.md.

Pytania padają w konstruktorze, a nie w linearyzacji, bo to konstruktor mówi, co z czym wolno złożyć, i bo drzewo, które tego nie przechodzi, jest błędne całe, a nie w tym jednym miejscu, gdzie się je wypisuje.

Przeczenie stoi tu polem, a nie osobnym konstruktorem, bo sięga dwóch rzeczy naraz: stawia nie przed czasownikiem i zabiera dopełnieniu biernik na rzecz dopełniacza, a te dwie rzeczy są jedną decyzją i rozjechać się nie mogą. Pierwszą z nich robi Zdanie dla obu kategorii, a druga jest tutaj, bo orzeczenie imienne dopełnienia nie ma.

Source code in olski/skład/składnia.py
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
@dataclass(frozen=True)
class Robi(Zdanie):
    """Zdanie o czynności: program zapisuje ustawienia.

    Dopełnienie nie pyta, czy stoi pod nim rzecz, czy zdarzenie,
    i jest to ta sama jedna kategoria, którą ``Okolicznik`` ma o piętro obok.
    `Czeladnik zaczął pracę.` i `Czeladnik zaczął pracować.`
    mówią, co zaczął, a różnią się tym, czy zaczął rzecz, czy zdarzenie.
    Że wychodzi z tego raz biernik, a raz bezokolicznik bez podmiotu,
    rozstrzyga linearyzacja, tak samo jak rozstrzyga przypadek.
    Trzecią rzeczą, która tam stoi, jest ``Treść`` wyżej,
    czyli zdarzenie, o którym podmiot coś orzeka, zamiast je wykonywać.

    Pytana o wszystkie trzy jest rama z leksykonu walencyjnego, bo wszystkie są jej
    pozycjami, a pytanie pada jedno: czy pozycja, którą ten konstytuent zajmuje,
    stoi w ramie tego czasownika.
    Rama jest zbiorem, więc pozycja dopisana do leksykonu nie dokłada tu gałęzi
    (``rama`` w ``olski/walencja.py``).
    Pytany jest ten sam plik, o który pyta parser po drugiej stronie,
    bo rama jest faktem o słowie, a nie o kierunku.
    Ostatnie z tych pytań waży najwięcej przy czasowniku, który bierze i biernik:
    ``zamykać`` biernik bierze, a `Zamykał, że okno stało.` nie jest zdaniem,
    i to leksykon jest jedyną rzeczą, która te dwa czasowniki rozdziela.

    Dopełnienie pyta przy tym o dwa przypadki naraz i staje w tym, który rama ma,
    bo przypadek bierze się tu z pozycji jak wszędzie indziej:
    `Czeladnik szukał córki krawca.` i `Czeladnik zasłonił twarz.`
    wychodzą z drzewa tego samego kształtu, a autor nie pisze przypadka w żadnym
    (:data:`PRZYPADKI_DOPEŁNIENIA`).

    Uczestnik w celowniku stoi obok tego dopełnienia, a nie zamiast niego,
    i dlatego ma tu osobne pole:
    `Parser pokazuje autorowi czytania.` wypełnia dwie pozycje ramy naraz,
    a o tym, która rzecz stoi w której, mówi ``Komu`` wyżej.

    Kopuli ta kategoria nie bierze wcale, i jest to ta sama odmowa co powyższe:
    rama kopuli ma orzecznik, a orzecznikiem orzeka ``Jest`` obok,
    więc `Parser jest.` nie wychodzi stąd tak samo, jak nie wyprowadza się z olskiego.

    Sprawca bezokolicznika stoi w drzewie, a nie w leksykonie,
    i jest nim ta sama zmienna postawiona dwa razy, jak w ``Opis`` i w ``Postać``.
    Drzewo, które postawiło tam kogoś innego, zgłasza się,
    bo bezokolicznik podmiotu nie ma i wyszedłby tekstem o kimś innym;
    czego polszczyzna mówi tam zamiast niego, trzyma ``docs/kategorie-zapisu.md``.

    Pytania padają w konstruktorze, a nie w linearyzacji,
    bo to konstruktor mówi, co z czym wolno złożyć,
    i bo drzewo, które tego nie przechodzi, jest błędne całe,
    a nie w tym jednym miejscu, gdzie się je wypisuje.

    Przeczenie stoi tu polem, a nie osobnym konstruktorem,
    bo sięga dwóch rzeczy naraz: stawia ``nie`` przed czasownikiem
    i zabiera dopełnieniu biernik na rzecz dopełniacza,
    a te dwie rzeczy są jedną decyzją i rozjechać się nie mogą.
    Pierwszą z nich robi ``Zdanie`` dla obu kategorii, a druga jest tutaj,
    bo orzeczenie imienne dopełnienia nie ma.
    """

    kto: Rola | Wyróżnienie
    czyn: str
    co: Rola | Wyróżnienie | Zdanie | Treść | None = None
    komu: Komu | Wyróżnienie | None = None
    okoliczniki: tuple = ()
    przeczenie: bool = False

    def __post_init__(self) -> None:
        if ORZECZNIK in rama(self.czyn):
            raise PozaRamą(f"{self.czyn} orzeka orzecznikiem, a nie czynnością")
        for żądane in self._żądania():
            _pozycja(self.czyn, żądane)
        dopełnienie = _goły(self.co)
        if isinstance(dopełnienie, Zdanie) and any(
            sprawca is not _rdzeń(self.podmiot) for sprawca in dopełnienie.sprawcy
        ):
            raise PozaRamą(f"bezokolicznik przy {self.czyn} orzeka o kimś innym")

    def _żądania(self):
        """Pozycje, których to drzewo żąda od ramy: po jednym żądaniu na wypełnioną pozycję.

        Pętla, a nie pytanie na pozycję, i to jest tu cała treść:
        pozycja dopisana do tej kategorii dokłada wiersz tutaj,
        a nie gałąź w konstruktorze i drugą w leksykonie.
        """
        if self.co is not None:
            yield _żądanie(_goły(self.co))
        if self.komu is not None:
            yield (CELOWNIK,)

    @property
    def czasownik(self) -> str:
        """Lemat, którym to zdanie orzeka.

        Czyn jest kategorią dziedziny, a czasownik słowem, które z niej wychodzi,
        więc jedno pole odpowiada tu na dwa pytania i oba są nazwane:
        drzewo pisze się czynem, a o formę pyta się czasownika.
        """
        return self.czyn

    @property
    def podmiot(self) -> Rola:
        return _goły(self.kto)

    @property
    def konstytuenty(self) -> tuple:
        wypełnione = tuple(pole for pole in (self.komu, self.co) if pole is not None)
        return (self.kto, *wypełnione, *self.okoliczniki)

    def _dopełnienie(self, kontekst: Kontekst) -> Kawałek:
        """Dopełnienie wypisane jako grupa imienna, bezokolicznik albo treść.

        Treść wypisuje się sama i nie dostaje stąd nic ponad to,
        co ``Kontekst.podrzędne`` daje każdemu zdaniu podrzędnemu,
        bo ma podmiot własny i własne przypadki.

        Zdarzenie dostaje kontekst zdania podrzędnego wraz z dwiema rzeczami,
        których to zdanie o sobie nie wie i wiedzieć nie może.
        Sprawcą jest podmiot tego zdania, więc bezokolicznik podmiotu nie wypisze
        i weźmie z niego formę, której sam nie ma.
        Przeczenie idzie tą samą drogą, bo dopełniacz negacji sięga przez bezokolicznik:
        `Nie chciał wynieść lustra.` przeczy raz, a przypadek zmienia o piętro niżej,
        i dlatego jedno przeczenie liczy się tu z dwóch pięter naraz.
        Treść tej drogi nie ma i to jest cała różnica między tymi dwiema pozycjami:
        `Nie wierzył, że wyniosła kufer.` przeczy jednemu czasownikowi,
        a drugi zostaje przy swoim bierniku.
        """
        dopełnienie = _goły(self.co)
        if isinstance(dopełnienie, Treść):
            return dopełnienie.linearyzuj(kontekst)
        if isinstance(dopełnienie, Zdanie):
            return dopełnienie.linearyzuj(
                replace(
                    kontekst.podrzędne(),
                    sprawca=_rdzeń(self.podmiot),
                    pod_przeczeniem=self._przeczone(kontekst),
                )
            )
        return wypisz(dopełnienie, self._przypadek(kontekst), kontekst)

    def _przeczone(self, kontekst: Kontekst) -> bool:
        """Czy to zdanie stoi pod przeczeniem, własnym albo cudzym."""
        return self.przeczenie or kontekst.pod_przeczeniem

    def _przypadek(self, kontekst: Kontekst) -> str:
        """Przypadek, w którym staje dopełnienie: ten z ramy, a pod przeczeniem dopełniacz.

        Pytają o to dwa miejsca i muszą dostać tę samą odpowiedź:
        linearyzacja, żeby dopełnienie wypisać,
        i ``uczestnicy``, żeby powiedzieć, jaką formą ono stanęło.
        Druga kopia rozjechałaby się z pierwszą zmianą przeczenia
        i nie zgłosiłaby tego nigdzie, bo obie odpowiedzi są poprawnymi przypadkami.

        Dopełniacz negacji wchodzi w miejsce biernika i dopełniacza z leksykonu
        nie rusza, bo nie ma tam czego zmienić:
        `Czeladnik nie szukał córki krawca.` stoi w tym samym przypadku,
        co to samo zdanie bez przeczenia.
        """
        if self._przeczone(kontekst):
            return DOPEŁNIACZ
        return _pozycja(self.czyn, PRZYPADKI_DOPEŁNIENIA)

    def uczestnicy(self, kontekst: Kontekst = TERAZ) -> tuple[tuple[Rola, str], ...]:
        """Podmiot, a wraz z nim ci uczestnicy, którzy są rzeczą, a nie zdarzeniem.

        Bezokolicznik podmiotem nie stanie, więc uczestnikiem nie jest:
        pytanie, dla którego ta lista istnieje, jest pytaniem o role wymienne.
        Celownik stanąć nim nie może z innego powodu i wchodzi tu mimo to,
        bo powód ten jest formą, a nie kategorią: rzeczownik ma celownik różny
        od mianownika i to rozstrzyga ``olski/skład/przegląd.py``, a nie ta lista.
        """
        role = [(self.podmiot, "nom")]
        dopełnienie = _goły(self.co)
        if isinstance(dopełnienie, Rola):
            role.append((dopełnienie, self._przypadek(kontekst)))
        if self.komu is not None:
            role.append((_goły(self.komu).co, CELOWNIK))
        return tuple(role)

    def linearyzuj(self, kontekst: Kontekst = TERAZ) -> Kawałek:
        pozycje = _podmiot(self.kto, kontekst)
        pozycje.append((None, Kawałek(self._orzeczenie(kontekst))))
        if self.komu is not None:
            pozycje.append((_miejsce(self.komu, kontekst), _goły(self.komu).linearyzuj(kontekst)))
        if self.co is not None:
            pozycje.append((_miejsce(self.co, kontekst), self._dopełnienie(kontekst)))
        pozycje.extend(_okoliczności(self.okoliczniki, kontekst))
        return _szyk(pozycje)

kto instance-attribute

czyn instance-attribute

co = None class-attribute instance-attribute

komu = None class-attribute instance-attribute

okoliczniki = () class-attribute instance-attribute

przeczenie = False class-attribute instance-attribute

czasownik property

Lemat, którym to zdanie orzeka.

Czyn jest kategorią dziedziny, a czasownik słowem, które z niej wychodzi, więc jedno pole odpowiada tu na dwa pytania i oba są nazwane: drzewo pisze się czynem, a o formę pyta się czasownika.

podmiot property

konstytuenty property

__post_init__()

Source code in olski/skład/składnia.py
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
def __post_init__(self) -> None:
    if ORZECZNIK in rama(self.czyn):
        raise PozaRamą(f"{self.czyn} orzeka orzecznikiem, a nie czynnością")
    for żądane in self._żądania():
        _pozycja(self.czyn, żądane)
    dopełnienie = _goły(self.co)
    if isinstance(dopełnienie, Zdanie) and any(
        sprawca is not _rdzeń(self.podmiot) for sprawca in dopełnienie.sprawcy
    ):
        raise PozaRamą(f"bezokolicznik przy {self.czyn} orzeka o kimś innym")

uczestnicy(kontekst=TERAZ)

Podmiot, a wraz z nim ci uczestnicy, którzy są rzeczą, a nie zdarzeniem.

Bezokolicznik podmiotem nie stanie, więc uczestnikiem nie jest: pytanie, dla którego ta lista istnieje, jest pytaniem o role wymienne. Celownik stanąć nim nie może z innego powodu i wchodzi tu mimo to, bo powód ten jest formą, a nie kategorią: rzeczownik ma celownik różny od mianownika i to rozstrzyga olski/skład/przegląd.py, a nie ta lista.

Source code in olski/skład/składnia.py
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
def uczestnicy(self, kontekst: Kontekst = TERAZ) -> tuple[tuple[Rola, str], ...]:
    """Podmiot, a wraz z nim ci uczestnicy, którzy są rzeczą, a nie zdarzeniem.

    Bezokolicznik podmiotem nie stanie, więc uczestnikiem nie jest:
    pytanie, dla którego ta lista istnieje, jest pytaniem o role wymienne.
    Celownik stanąć nim nie może z innego powodu i wchodzi tu mimo to,
    bo powód ten jest formą, a nie kategorią: rzeczownik ma celownik różny
    od mianownika i to rozstrzyga ``olski/skład/przegląd.py``, a nie ta lista.
    """
    role = [(self.podmiot, "nom")]
    dopełnienie = _goły(self.co)
    if isinstance(dopełnienie, Rola):
        role.append((dopełnienie, self._przypadek(kontekst)))
    if self.komu is not None:
        role.append((_goły(self.komu).co, CELOWNIK))
    return tuple(role)

linearyzuj(kontekst=TERAZ)

Source code in olski/skład/składnia.py
1231
1232
1233
1234
1235
1236
1237
1238
1239
def linearyzuj(self, kontekst: Kontekst = TERAZ) -> Kawałek:
    pozycje = _podmiot(self.kto, kontekst)
    pozycje.append((None, Kawałek(self._orzeczenie(kontekst))))
    if self.komu is not None:
        pozycje.append((_miejsce(self.komu, kontekst), _goły(self.komu).linearyzuj(kontekst)))
    if self.co is not None:
        pozycje.append((_miejsce(self.co, kontekst), self._dopełnienie(kontekst)))
    pozycje.extend(_okoliczności(self.okoliczniki, kontekst))
    return _szyk(pozycje)

__init__(kto, czyn, co=None, komu=None, okoliczniki=(), przeczenie=False)

Rola

Bases: Wyróżnialne

To, co wypełnia w zdaniu jedną rolę: jeden byt albo kilka bytów naraz.

Rola niesie liczbę i rodzaj, bo tego żąda od niej zgodność z czasownikiem, i odpowiada na jeden przypadek, bo tyle daje jej pozycja, w której stoi.

Tożsamości rola z zasady nie ma. Ma ją dopiero Postać w olski/skład/opowieść.py, czyli ten, do kogo tekst wraca, i to jest jedyne miejsce, w którym dwa wystąpienia jednego lematu są tą samą rzeczą, a nie dwiema takimi samymi.

Source code in olski/skład/składnia.py
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
class Rola(Wyróżnialne):
    """To, co wypełnia w zdaniu jedną rolę: jeden byt albo kilka bytów naraz.

    Rola niesie liczbę i rodzaj, bo tego żąda od niej zgodność z czasownikiem,
    i odpowiada na jeden przypadek, bo tyle daje jej pozycja, w której stoi.

    Tożsamości rola z zasady nie ma.
    Ma ją dopiero ``Postać`` w ``olski/skład/opowieść.py``, czyli ten, do kogo tekst wraca,
    i to jest jedyne miejsce, w którym dwa wystąpienia jednego lematu
    są tą samą rzeczą, a nie dwiema takimi samymi.
    """

    tożsamość = None

    def __and__(self, inne) -> Koordynacja:
        return Koordynacja((self, byt(inne)))

tożsamość = None class-attribute instance-attribute

__and__(inne)

Source code in olski/skład/składnia.py
463
464
def __and__(self, inne) -> Koordynacja:
    return Koordynacja((self, byt(inne)))

Rzecz dataclass

Bases: Nominalne

Rodzaj bytu, bez rozstrzygnięcia, ile go i który.

Source code in olski/skład/składnia.py
388
389
390
391
392
393
394
395
396
397
398
399
@dataclass(frozen=True)
class Rzecz(Nominalne):
    """Rodzaj bytu, bez rozstrzygnięcia, ile go i który."""

    lemat: str

    @property
    def rodzaj(self) -> str:
        return rodzaj_rzeczownika(self.lemat)

    def linearyzuj(self, case: str, number: str, kontekst: Kontekst = TERAZ) -> Kawałek:
        return Kawałek(odmień(self.lemat, "subst", case=case, number=number))

lemat instance-attribute

rodzaj property

linearyzuj(case, number, kontekst=TERAZ)

Source code in olski/skład/składnia.py
398
399
def linearyzuj(self, case: str, number: str, kontekst: Kontekst = TERAZ) -> Kawałek:
    return Kawałek(odmień(self.lemat, "subst", case=case, number=number))

__init__(lemat)

Treść dataclass

To, co ktoś mówi, wie albo w co nie wierzy: zdarzenie jako uczestnik.

Kategorią dziedziny jest tu treść, a nie zdanie podrzędne, i zawinięcie jest potrzebne, bo drzewo samo tej różnicy nie niesie. V.chcieć(kot, V.spać(kot)) i V.wiedzieć(kot, Treść(V.spać(kot))) stawiają pod czasownikiem to samo zdarzenie i mówią dwie różne rzeczy, więc nie ma jak policzyć tego z tego, kto w zdarzeniu działa. Po co ta kategoria jest opowieści, mówi docs/kategorie-zapisu.md.

Zdaniem ta klasa nie jest, choć zdanie w sobie trzyma, i jest to rozstrzygnięcie, a nie wygoda dziedziczenia. Zdaniem jest to, co orzeka o kimś, a treść o nikim nie orzeka: stoi w roli uczestnika i o tym, kto ją niesie, mówi czasownik nad nią. Gdyby zdaniem była, Okolicznik wpuściłby ją tam, gdzie czeka na zdarzenie, i wypuścił gdy że, czyli dwa spójniki jeden po drugim.

Pól ta klasa nie ma poza objętym zdaniem i każde z brakujących ma swój powód. Kontroli nie ma czego zapisywać, bo zdanie podrzędne niesie podmiot własny, a przeczenia tym bardziej: dopełniacz negacji przez tę pozycję nie sięga, bo zdanie podrzędne rozdaje przypadki własne. Idzie to samo z siebie, bo Kontekst.podrzędne nie przekazuje w dół ani wykonawcy, ani przeczenia, i jest to ta sama metoda, która puszcza czas. Wyróżnienia ta klasa nie przyjmuje, bo pozycję ma jedną i wziętą z polszczyzny, a nie z tego, o czym zdanie jest; rozstrzyga o niej _miejsce niżej.

Source code in olski/skład/składnia.py
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
@dataclass(frozen=True)
class Treść:
    """To, co ktoś mówi, wie albo w co nie wierzy: zdarzenie jako uczestnik.

    Kategorią dziedziny jest tu treść, a nie zdanie podrzędne,
    i zawinięcie jest potrzebne, bo drzewo samo tej różnicy nie niesie.
    ``V.chcieć(kot, V.spać(kot))`` i ``V.wiedzieć(kot, Treść(V.spać(kot)))``
    stawiają pod czasownikiem to samo zdarzenie i mówią dwie różne rzeczy,
    więc nie ma jak policzyć tego z tego, kto w zdarzeniu działa.
    Po co ta kategoria jest opowieści, mówi ``docs/kategorie-zapisu.md``.

    Zdaniem ta klasa nie jest, choć zdanie w sobie trzyma,
    i jest to rozstrzygnięcie, a nie wygoda dziedziczenia.
    Zdaniem jest to, co orzeka o kimś, a treść o nikim nie orzeka:
    stoi w roli uczestnika i o tym, kto ją niesie, mówi czasownik nad nią.
    Gdyby zdaniem była, ``Okolicznik`` wpuściłby ją tam, gdzie czeka na zdarzenie,
    i wypuścił `gdy że`, czyli dwa spójniki jeden po drugim.

    Pól ta klasa nie ma poza objętym zdaniem i każde z brakujących ma swój powód.
    Kontroli nie ma czego zapisywać, bo zdanie podrzędne niesie podmiot własny,
    a przeczenia tym bardziej: dopełniacz negacji przez tę pozycję nie sięga,
    bo zdanie podrzędne rozdaje przypadki własne.
    Idzie to samo z siebie, bo ``Kontekst.podrzędne`` nie przekazuje w dół
    ani wykonawcy, ani przeczenia, i jest to ta sama metoda, która puszcza czas.
    Wyróżnienia ta klasa nie przyjmuje, bo pozycję ma jedną i wziętą z polszczyzny,
    a nie z tego, o czym zdanie jest; rozstrzyga o niej ``_miejsce`` niżej.
    """

    zdanie: Zdanie

    #: Spójnik, którym polszczyzna wprowadza treść orzekaną wprost. Stoi tu stałą,
    #: a nie w leksykonie jak słowo okoliczności, bo autor nie ma tu czego wybierać:
    #: ``żeby`` mówi, że tak ma być, czyli jest inną kategorią, i trzyma to ``todo/``.
    SŁOWO = "że"

    def linearyzuj(self, kontekst: Kontekst = TERAZ) -> Kawałek:
        return _podrzędne(self.SŁOWO, self.zdanie, kontekst)

zdanie instance-attribute

SŁOWO = 'że' class-attribute instance-attribute

linearyzuj(kontekst=TERAZ)

Source code in olski/skład/składnia.py
685
686
def linearyzuj(self, kontekst: Kontekst = TERAZ) -> Kawałek:
    return _podrzędne(self.SŁOWO, self.zdanie, kontekst)

__init__(zdanie)

Wyróżnienie dataclass

Konstytuent wraz z tym, czym jest w zdaniu: tematem albo rematem.

To jest ta kategoria, którą polszczyzna niesie szykiem. Drzewo mówi, o czym zdanie jest i co o tym dokłada, a kolejność słów jest z tego wnioskiem, wyciąganym przy linearyzacji. Wariantu szyku dopisanego do linearyzacji tu nie ma i nie ma być, bo taki parametr opisywałby zdanie, a to drzewo opisuje to, o czym zdanie jest.

Source code in olski/skład/składnia.py
301
302
303
304
305
306
307
308
309
310
311
312
313
@dataclass(frozen=True)
class Wyróżnienie:
    """Konstytuent wraz z tym, czym jest w zdaniu: tematem albo rematem.

    To jest ta kategoria, którą polszczyzna niesie szykiem.
    Drzewo mówi, o czym zdanie jest i co o tym dokłada,
    a kolejność słów jest z tego wnioskiem, wyciąganym przy linearyzacji.
    Wariantu szyku dopisanego do linearyzacji tu nie ma i nie ma być,
    bo taki parametr opisywałby zdanie, a to drzewo opisuje to, o czym zdanie jest.
    """

    co: object
    miejsce: str

co instance-attribute

miejsce instance-attribute

__init__(co, miejsce)

Zdanie

To, co orzeka o kimś: jedno zdarzenie albo kilka opowiedzianych naraz.

Klasa ta jest tu po to, żeby dało się o nią zapytać. Okolicznik pyta, bo od tego zależy, czy jego słowo jest przyimkiem, czy spójnikiem, a lista kategorii wypisana obok rozjechałaby się z pierwszą kategorią dopisaną i tam niedopisaną.

Wnosi jedno liczenie i żąda za nie trzech rzeczy, które daje każda kategoria: podmiotu, o którym zdanie orzeka, czasownika, którym orzeka, oraz konstytuentów, czyli tego, z czego się wypisuje.

Source code in olski/skład/składnia.py
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
class Zdanie:
    """To, co orzeka o kimś: jedno zdarzenie albo kilka opowiedzianych naraz.

    Klasa ta jest tu po to, żeby dało się o nią zapytać.
    Okolicznik pyta, bo od tego zależy, czy jego słowo jest przyimkiem,
    czy spójnikiem, a lista kategorii wypisana obok rozjechałaby się
    z pierwszą kategorią dopisaną i tam niedopisaną.

    Wnosi jedno liczenie i żąda za nie trzech rzeczy, które daje każda kategoria:
    podmiotu, o którym zdanie orzeka, czasownika, którym orzeka,
    oraz konstytuentów, czyli tego, z czego się wypisuje.
    """

    @property
    def podmioty(self) -> tuple[Rola, ...]:
        """Role, które w tym zdaniu stoją jako podmiot, wraz z tymi ze zdań pod nim.

        Zdanie proste ma jeden podmiot, a złożone ma go tyle, ile ma zdarzeń,
        i wszystkie one są tym, na co czytelnik trafia,
        szukając podmiotu, którego zdanie obok nie wypisało.
        Liczą się przez to zdania z każdego piętra drzewa (:func:`_zdania_głębiej`),
        a nie z dwóch pierwszych: `Mysz goniła ogon myszy, która spała.`
        ma dwa podmioty, a z dwóch pięter widać jeden.

        Kontekstu ta lista nie dostaje i nie ma po co,
        bo pyta o role wypisane w drzewie, a kontekst rozstrzyga o formach.
        """
        pod = (
            rola
            for konstytuent in self.konstytuenty
            for niższe in _zdania_głębiej(konstytuent)
            for rola in niższe.podmioty
        )
        return (self.podmiot, *pod)

    @property
    def sprawcy(self) -> tuple:
        """Rzeczy, o których to zdanie orzeka wprost, bez zdań stojących pod nim.

        Pyta o co innego niż ``podmioty`` i dlatego wydaje co innego.
        Tamto szuka podmiotów, na które trafia czytelnik, więc wydaje role;
        to szuka tych, których czasownik nad tym zdaniem ma wskazać,
        gdy stoi ono jako bezokolicznik, więc wydaje rzeczy spod ról,
        czyli dokładnie to, co niesie ``Kontekst.sprawca``.
        Zdanie proste ma jednego sprawcę, a ciąg zdarzeń ma po jednym na zdarzenie,
        bo bezokoliczników w nim wyjdzie tyle samo.
        """
        return (_rdzeń(self.podmiot),)

    def uczestnicy(self, kontekst: Kontekst = TERAZ) -> tuple[tuple[Rola, str], ...]:
        """Role, które w tym zdaniu stoją jako uczestnik zdarzenia, wraz z przypadkiem.

        Przypadek idzie razem z rolą, bo osobno żadne z dwojga nie mówi,
        którą formą uczestnik w zdaniu stanie,
        a to jest jedyne pytanie, dla którego ta lista istnieje.

        Uczestnikiem nie jest okoliczność, i to jest tu cała treść:
        rzecz spod przyimka staje w przypadku, którego żąda ten przyimek,
        a nie w tym, który by jej przypadł z roli w zdarzeniu.
        Przez to samo lista ta mówi coś, czego po samych formach nie widać,
        i korzysta z tego ``olski/skład/przegląd.py``.

        Nie schodzi ona pod konstytuenty, inaczej niż ``podmioty`` wyżej,
        bo uczestnicy dwóch zdań zestawieni w jedną listę
        dawaliby parę, która przy żadnym orzeczeniu razem nie stanęła;
        po zdania schodzi ``konteksty`` niżej.
        """
        return ((self.podmiot, "nom"),)

    def konteksty(self, kontekst: Kontekst = TERAZ):
        """To zdanie wraz z tymi, które stoją pod nim, każde w swoim kontekście.

        Jednostką jest tu orzeczenie, bo tyle wystarcza,
        żeby o dwóch rolach powiedzieć, że stanęły przy jednym.

        Kontekst idzie razem ze zdaniem, bo bez niego nie wiadomo,
        jakim napisem to zdanie wyszło: zdanie podrzędne mówi o wskazanej rzeczy
        zaimkiem, a zdanie po zdaniu o tym samym podmiocie podmiotu nie wypisuje.
        Liczy się go tą samą drogą, którą idzie linearyzacja,
        bo druga kopia mierzyłaby tekst, którego ten plik nie składa;
        tak samo robi ``Akapit.konteksty`` w ``olski/skład/opowieść.py`` piętro wyżej.
        """
        yield self, kontekst
        for konstytuent in self.konstytuenty:
            for niższe, niżej in _zdania_pod(konstytuent, kontekst):
                yield from niższe.konteksty(niżej)

    def _orzeczenie(self, kontekst: Kontekst) -> str:
        """Czasownik w formie, której żąda podmiot, wraz z przeczeniem.

        Stoi tu, bo przeczenie stawia ``nie`` przed czasownikiem tak samo
        w zdaniu o czynności i w orzeczeniu imiennym.
        Różni je to, co przeczenie robi poza czasownikiem:
        dopełnienie traci biernik na rzecz dopełniacza, a orzecznik nie ma czego stracić,
        bo narzędnika przeczenie w polszczyźnie nie rusza.
        """
        forma = forma_czasownika(self.czasownik, self.podmiot, kontekst)
        return f"nie {forma}" if self.przeczenie else forma

podmioty property

Role, które w tym zdaniu stoją jako podmiot, wraz z tymi ze zdań pod nim.

Zdanie proste ma jeden podmiot, a złożone ma go tyle, ile ma zdarzeń, i wszystkie one są tym, na co czytelnik trafia, szukając podmiotu, którego zdanie obok nie wypisało. Liczą się przez to zdania z każdego piętra drzewa (_zdania_głębiej), a nie z dwóch pierwszych: Mysz goniła ogon myszy, która spała. ma dwa podmioty, a z dwóch pięter widać jeden.

Kontekstu ta lista nie dostaje i nie ma po co, bo pyta o role wypisane w drzewie, a kontekst rozstrzyga o formach.

sprawcy property

Rzeczy, o których to zdanie orzeka wprost, bez zdań stojących pod nim.

Pyta o co innego niż podmioty i dlatego wydaje co innego. Tamto szuka podmiotów, na które trafia czytelnik, więc wydaje role; to szuka tych, których czasownik nad tym zdaniem ma wskazać, gdy stoi ono jako bezokolicznik, więc wydaje rzeczy spod ról, czyli dokładnie to, co niesie Kontekst.sprawca. Zdanie proste ma jednego sprawcę, a ciąg zdarzeń ma po jednym na zdarzenie, bo bezokoliczników w nim wyjdzie tyle samo.

uczestnicy(kontekst=TERAZ)

Role, które w tym zdaniu stoją jako uczestnik zdarzenia, wraz z przypadkiem.

Przypadek idzie razem z rolą, bo osobno żadne z dwojga nie mówi, którą formą uczestnik w zdaniu stanie, a to jest jedyne pytanie, dla którego ta lista istnieje.

Uczestnikiem nie jest okoliczność, i to jest tu cała treść: rzecz spod przyimka staje w przypadku, którego żąda ten przyimek, a nie w tym, który by jej przypadł z roli w zdarzeniu. Przez to samo lista ta mówi coś, czego po samych formach nie widać, i korzysta z tego olski/skład/przegląd.py.

Nie schodzi ona pod konstytuenty, inaczej niż podmioty wyżej, bo uczestnicy dwóch zdań zestawieni w jedną listę dawaliby parę, która przy żadnym orzeczeniu razem nie stanęła; po zdania schodzi konteksty niżej.

Source code in olski/skład/składnia.py
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
def uczestnicy(self, kontekst: Kontekst = TERAZ) -> tuple[tuple[Rola, str], ...]:
    """Role, które w tym zdaniu stoją jako uczestnik zdarzenia, wraz z przypadkiem.

    Przypadek idzie razem z rolą, bo osobno żadne z dwojga nie mówi,
    którą formą uczestnik w zdaniu stanie,
    a to jest jedyne pytanie, dla którego ta lista istnieje.

    Uczestnikiem nie jest okoliczność, i to jest tu cała treść:
    rzecz spod przyimka staje w przypadku, którego żąda ten przyimek,
    a nie w tym, który by jej przypadł z roli w zdarzeniu.
    Przez to samo lista ta mówi coś, czego po samych formach nie widać,
    i korzysta z tego ``olski/skład/przegląd.py``.

    Nie schodzi ona pod konstytuenty, inaczej niż ``podmioty`` wyżej,
    bo uczestnicy dwóch zdań zestawieni w jedną listę
    dawaliby parę, która przy żadnym orzeczeniu razem nie stanęła;
    po zdania schodzi ``konteksty`` niżej.
    """
    return ((self.podmiot, "nom"),)

konteksty(kontekst=TERAZ)

To zdanie wraz z tymi, które stoją pod nim, każde w swoim kontekście.

Jednostką jest tu orzeczenie, bo tyle wystarcza, żeby o dwóch rolach powiedzieć, że stanęły przy jednym.

Kontekst idzie razem ze zdaniem, bo bez niego nie wiadomo, jakim napisem to zdanie wyszło: zdanie podrzędne mówi o wskazanej rzeczy zaimkiem, a zdanie po zdaniu o tym samym podmiocie podmiotu nie wypisuje. Liczy się go tą samą drogą, którą idzie linearyzacja, bo druga kopia mierzyłaby tekst, którego ten plik nie składa; tak samo robi Akapit.konteksty w olski/skład/opowieść.py piętro wyżej.

Source code in olski/skład/składnia.py
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
def konteksty(self, kontekst: Kontekst = TERAZ):
    """To zdanie wraz z tymi, które stoją pod nim, każde w swoim kontekście.

    Jednostką jest tu orzeczenie, bo tyle wystarcza,
    żeby o dwóch rolach powiedzieć, że stanęły przy jednym.

    Kontekst idzie razem ze zdaniem, bo bez niego nie wiadomo,
    jakim napisem to zdanie wyszło: zdanie podrzędne mówi o wskazanej rzeczy
    zaimkiem, a zdanie po zdaniu o tym samym podmiocie podmiotu nie wypisuje.
    Liczy się go tą samą drogą, którą idzie linearyzacja,
    bo druga kopia mierzyłaby tekst, którego ten plik nie składa;
    tak samo robi ``Akapit.konteksty`` w ``olski/skład/opowieść.py`` piętro wyżej.
    """
    yield self, kontekst
    for konstytuent in self.konstytuenty:
        for niższe, niżej in _zdania_pod(konstytuent, kontekst):
            yield from niższe.konteksty(niżej)

leksem(nazwa)

Identyfikator leksemu, którym ta nazwa jest, albo nazwa nietknięta.

Milczenie leksykonu jest tu zgodą na to, co słownik ma pod tym napisem, a nie brakiem wiedzy, i tym ten plik różni się od olski/skład/przyimki.py: tamten milczy o przyimku, którego nie zna, i milczenie zgłasza wyjątkiem, a tutaj większość nazw jest lematami o jednym leksemie i wpis byłby dla nich powtórzeniem napisu.

Source code in olski/skład/leksemy.py
48
49
50
51
52
53
54
55
56
57
def leksem(nazwa: str) -> str:
    """Identyfikator leksemu, którym ta nazwa jest, albo nazwa nietknięta.

    Milczenie leksykonu jest tu zgodą na to, co słownik ma pod tym napisem,
    a nie brakiem wiedzy, i tym ten plik różni się od ``olski/skład/przyimki.py``:
    tamten milczy o przyimku, którego nie zna, i milczenie zgłasza wyjątkiem,
    a tutaj większość nazw jest lematami o jednym leksemie
    i wpis byłby dla nich powtórzeniem napisu.
    """
    return LEKSEMY.get(nazwa, nazwa)

odmień(nazwa, pos, **żądane)

Forma nazwy, która spełnia żądanie postawione cechami.

Cechy, której cały paradygmat nie ma, żądanie nie dotyczy. Żądanie jest tu kryterium wyboru, a nad kolumną o jednej wartości kryterium nie wybiera niczego, więc odsianie po niej byłoby odsianiem wszystkiego. Widać to na przysłówku: nagle ma stopień i wkrótce go nie ma, a żądać stopnia równego trzeba od obu, bo o odmienności rozstrzyga leksem. Cecha, którą paradygmat ma, a której ta forma nie niesie, żądania nadal nie spełnia, i to jest różnica między brakiem wyboru a wyborem chybionym.

Gdzie żądaniu odpowiadają leksemy zgodne co do jakiejś formy, bierze tę formę. Zgoda leksemów jest tu odpowiedzią, a nie kolejność, w jakiej słownik je wydaje: dziób odesłany do żeglarstwa ma w dopełniaczu dzioba obok dziobu, a ten bez kwalifikatora dzióba obok dzioba, więc dzioba jest dobre pod oba i autor nie ma tu o czym rozstrzygać.

Gdzie leksemy nie zgadzają się co do żadnej formy, zgłasza WieleLeksemów, bo wtedy każda odpowiedź mówi co innego: oczy obok oka albo stoi obok stanie, czyli teraz obok potem. Który leksem, jest wtedy pytaniem do autora i odpowiada na nie olski/skład/leksemy.py. Kosztem tego jest cisza tam, gdzie leksemy różnią się poza żądaną komórką, czyli w miejscu, w którym autor o żaden wybór nie pytał.

Gdzie zostaje kilka form jednego leksemu, bierze pierwszą. To zostaje jedynym miejscem, w którym kompilator wybiera i nie mówi o tym, a reszta wyborów stoi w drzewie, które napisał autor; trzyma to todo/. Wybiera przy tym z form, które paradygmat już przepuścił, więc forma odesłana poza rejestr nie stoi tu ani pierwsza, ani żadna: któren i zgasnęła wychodziły stąd, dopóki kwalifikatora nikt nie czytał.

Source code in olski/skład/morfologia.py
 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
def odmień(nazwa: str, pos: str, **żądane: str) -> str:
    """Forma nazwy, która spełnia żądanie postawione cechami.

    Cechy, której cały paradygmat nie ma, żądanie nie dotyczy.
    Żądanie jest tu kryterium wyboru, a nad kolumną o jednej wartości
    kryterium nie wybiera niczego, więc odsianie po niej byłoby odsianiem wszystkiego.
    Widać to na przysłówku: ``nagle`` ma stopień i ``wkrótce`` go nie ma,
    a żądać stopnia równego trzeba od obu, bo o odmienności rozstrzyga leksem.
    Cecha, którą paradygmat ma, a której ta forma nie niesie, żądania nadal nie spełnia,
    i to jest różnica między brakiem wyboru a wyborem chybionym.

    Gdzie żądaniu odpowiadają leksemy zgodne co do jakiejś formy, bierze tę formę.
    Zgoda leksemów jest tu odpowiedzią, a nie kolejność, w jakiej słownik je wydaje:
    ``dziób`` odesłany do żeglarstwa ma w dopełniaczu ``dzioba`` obok ``dziobu``,
    a ten bez kwalifikatora ``dzióba`` obok ``dzioba``,
    więc ``dzioba`` jest dobre pod oba i autor nie ma tu o czym rozstrzygać.

    Gdzie leksemy nie zgadzają się co do żadnej formy, zgłasza ``WieleLeksemów``,
    bo wtedy każda odpowiedź mówi co innego:
    ``oczy`` obok ``oka`` albo ``stoi`` obok ``stanie``, czyli teraz obok potem.
    Który leksem, jest wtedy pytaniem do autora i odpowiada na nie
    ``olski/skład/leksemy.py``.
    Kosztem tego jest cisza tam, gdzie leksemy różnią się poza żądaną komórką,
    czyli w miejscu, w którym autor o żaden wybór nie pytał.

    Gdzie zostaje kilka form jednego leksemu, bierze pierwszą.
    To zostaje jedynym miejscem, w którym kompilator wybiera i nie mówi o tym,
    a reszta wyborów stoi w drzewie, które napisał autor; trzyma to ``todo/``.
    Wybiera przy tym z form, które ``paradygmat`` już przepuścił,
    więc forma odesłana poza rejestr nie stoi tu ani pierwsza, ani żadna:
    ``któren`` i ``zgasnęła`` wychodziły stąd, dopóki kwalifikatora nikt nie czytał.
    """
    formy = paradygmat(nazwa, pos)
    obecne = {cecha for _forma, cechy, _identyfikator in formy for cecha, _wartości in cechy}
    kryterium = {cecha: wartość for cecha, wartość in żądane.items() if cecha in obecne}
    # Kolejność trzyma lista, a nie zbiór, bo pierwsza forma jednego leksemu
    # jest tu odpowiedzią i musi być tą, którą słownik wydał pierwszą.
    trafienia: list[str] = []
    wedle_leksemu: dict[str, set[str]] = {}
    for forma, cechy, identyfikator in formy:
        if _spełnia(dict(cechy), kryterium):
            trafienia.append(forma)
            wedle_leksemu.setdefault(identyfikator, set()).add(forma)
    if not trafienia:
        raise BrakFormy(f"{nazwa} ({pos}) nie ma formy {żądane}")
    zgodne = set.intersection(*wedle_leksemu.values())
    if not zgodne:
        raise WieleLeksemów(f"{nazwa} ({pos}) w formie {żądane}", wedle_leksemu)
    return next(forma for forma in trafienia if forma in zgodne)

rodzaj_rzeczownika(nazwa) cached

Rodzaj wzięty z mianownika tej liczby, którą ten rzeczownik ma.

Rodzaj rzeczownika jest leksykalny: autor go nie wybiera, a zgodność go żąda, więc nie stoi w drzewie, tylko przychodzi stąd.

Liczba pojedyncza idzie pierwsza i jest odpowiedzią wszędzie tam, gdzie rzeczownik ma obie, a mnoga jest tu dla tych, które pojedynczej nie mają: drzwi i Włochy stoją tylko w mnogiej i rodzaj niosą tam, gdzie stoją, więc pytanie o samą pojedynczą odbierałoby im każdą pozycję, z której wychodzi czasownik albo człon koordynacji.

Rodzaj wychodzi stąd tak, jak forma wychodzi z odmień, i z tego samego powodu: zgoda leksemów jest odpowiedzią, a brak zgody jest pytaniem do autora. Pod napisem potwór stoją dwa leksemy i jeden z nich jest zwierzęciem, a drugi zwierzęciem albo osobą, więc zwierzę jest tym, co oba przyjmują. Zostaje po tym rodzaj, który sam słownik wypisuje dwiema wartościami, i tu ta funkcja bierze pierwszą alfabetycznie, nie mówiąc o tym nigdzie. Tamto jest wyborem autora, a to jest słownik mówiący „albo tak, albo tak”, więc drugiego olski/skład/leksemy.py nie rozstrzyga; trzyma to todo/.

Source code in olski/skład/morfologia.py
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
@functools.lru_cache(maxsize=4096)
def rodzaj_rzeczownika(nazwa: str) -> str:
    """Rodzaj wzięty z mianownika tej liczby, którą ten rzeczownik ma.

    Rodzaj rzeczownika jest leksykalny: autor go nie wybiera, a zgodność go żąda,
    więc nie stoi w drzewie, tylko przychodzi stąd.

    Liczba pojedyncza idzie pierwsza i jest odpowiedzią wszędzie tam,
    gdzie rzeczownik ma obie, a mnoga jest tu dla tych, które pojedynczej nie mają:
    `drzwi` i `Włochy` stoją tylko w mnogiej i rodzaj niosą tam, gdzie stoją,
    więc pytanie o samą pojedynczą odbierałoby im każdą pozycję,
    z której wychodzi czasownik albo człon koordynacji.

    Rodzaj wychodzi stąd tak, jak forma wychodzi z ``odmień``, i z tego samego
    powodu: zgoda leksemów jest odpowiedzią, a brak zgody jest pytaniem do autora.
    Pod napisem ``potwór`` stoją dwa leksemy i jeden z nich jest zwierzęciem,
    a drugi zwierzęciem albo osobą, więc zwierzę jest tym, co oba przyjmują.
    Zostaje po tym rodzaj, który sam słownik wypisuje dwiema wartościami,
    i tu ta funkcja bierze pierwszą alfabetycznie, nie mówiąc o tym nigdzie.
    Tamto jest wyborem autora, a to jest słownik mówiący „albo tak, albo tak”,
    więc drugiego ``olski/skład/leksemy.py`` nie rozstrzyga; trzyma to ``todo/``.
    """
    rodzaje = _rodzaje(nazwa, "sg") or _rodzaje(nazwa, "pl")
    if not rodzaje:
        raise BrakFormy(f"{nazwa} nie ma mianownika w żadnej liczbie")
    zgodne = set.intersection(*rodzaje.values())
    if not zgodne:
        raise WieleLeksemów(f"rodzaj, który niesie {nazwa}", rodzaje)
    return sorted(zgodne)[0]

przejrzyj(drzewo, kontekst=TERAZ)

Kolizje w zdaniu, które z tego drzewa wychodzi, po jednej na orzeczenie.

Zestawiany jest podmiot z każdym uczestnikiem obok niego, bo wymienić się mogą tylko te dwie role: pozycji podmiotu jest jedna, więc dwa dopełnienia przy jednym czasowniku o nią nie konkurują.

Kontekst każde zdanie dostaje własny i bierze go z konteksty, czyli stamtąd, skąd bierze go linearyzacja. Bez tego przegląd mierzyłby zdanie wypisane samo, a mierzyć ma to, co wyszło: podmiot bywa opuszczony, a rzecz wskazana wychodzi zaimkiem, który przypadek pokazuje.

Source code in olski/skład/przegląd.py
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
def przejrzyj(drzewo: Zdanie, kontekst: Kontekst = TERAZ) -> list[Kolizja]:
    """Kolizje w zdaniu, które z tego drzewa wychodzi, po jednej na orzeczenie.

    Zestawiany jest podmiot z każdym uczestnikiem obok niego,
    bo wymienić się mogą tylko te dwie role: pozycji podmiotu jest jedna,
    więc dwa dopełnienia przy jednym czasowniku o nią nie konkurują.

    Kontekst każde zdanie dostaje własny i bierze go z ``konteksty``,
    czyli stamtąd, skąd bierze go linearyzacja.
    Bez tego przegląd mierzyłby zdanie wypisane samo,
    a mierzyć ma to, co wyszło: podmiot bywa opuszczony,
    a rzecz wskazana wychodzi zaimkiem, który przypadek pokazuje.
    """
    kolizje = []
    for zdanie, jego in drzewo.konteksty(kontekst):
        (podmiot, _), *reszta = zdanie.uczestnicy(jego)
        #  Krotka pusta tam, gdzie podmiot z tekstu wypadł, bo zgłoszenie wymienia
        #  formy, które autor w napisie zobaczy, a tej nie zobaczy żadnej.
        wypisany = (wypisz(podmiot, "nom", jego).napis,) if jego.wypisuje(podmiot) else ()
        for rola, przypadek in reszta:
            if not _rozróżnia(zdanie, podmiot, rola, przypadek, jego):
                kolizje.append(Kolizja((*wypisany, wypisz(rola, przypadek, jego).napis)))
    return kolizje

przypadek(przyimek, relacja)

Przypadek, w którym staje grupa imienna po tym przyimku w tej relacji.

Milczenie leksykonu jest tu brakiem wiedzy, a nie ramą domyślną, i tym ten plik różni się od olski/leksykon.txt: tamten wylicza wyjątki od ramy, którą ma większość czasowników, a przyimków jest tyle, że wyliczyć da się je wszystkie. Odpowiedzią na milczenie jest None, a nie wyjątek, bo zgłasza je konstruktor okolicznika w olski/skład/składnia.py, czyli to samo miejsce, w którym zgłasza się rama czasownika, i po to, żeby drzewo błędne nie powstało zamiast zgłosić się przy wypisywaniu.

Source code in olski/skład/przyimki.py
58
59
60
61
62
63
64
65
66
67
68
69
70
def przypadek(przyimek: str, relacja: str) -> str | None:
    """Przypadek, w którym staje grupa imienna po tym przyimku w tej relacji.

    Milczenie leksykonu jest tu brakiem wiedzy, a nie ramą domyślną,
    i tym ten plik różni się od ``olski/leksykon.txt``:
    tamten wylicza wyjątki od ramy, którą ma większość czasowników,
    a przyimków jest tyle, że wyliczyć da się je wszystkie.
    Odpowiedzią na milczenie jest ``None``, a nie wyjątek,
    bo zgłasza je konstruktor okolicznika w ``olski/skład/składnia.py``,
    czyli to samo miejsce, w którym zgłasza się rama czasownika,
    i po to, żeby drzewo błędne nie powstało zamiast zgłosić się przy wypisywaniu.
    """
    return PRZYIMKI.get((przyimek, relacja))

byt(rzecz)

Rzecz postawiona tam, gdzie stoi rola, znaczy jeden egzemplarz.

Domyślność zapisana raz, a nie zgadywanie: liczbę mnogą trzeba napisać. Co rolą już jest, przechodzi tędy nietknięte, więc ta jedna funkcja stoi wszędzie tam, gdzie konstruktor bierze rolę.

Source code in olski/skład/składnia.py
530
531
532
533
534
535
536
537
def byt(rzecz):
    """Rzecz postawiona tam, gdzie stoi rola, znaczy jeden egzemplarz.

    Domyślność zapisana raz, a nie zgadywanie: liczbę mnogą trzeba napisać.
    Co rolą już jest, przechodzi tędy nietknięte,
    więc ta jedna funkcja stoi wszędzie tam, gdzie konstruktor bierze rolę.
    """
    return Byt(rzecz) if isinstance(rzecz, Nominalne) else rzecz

kompiluj(drzewo, kontekst=TERAZ)

Drzewo jako zdanie: wielka litera na początku i kropka na końcu.

Wielkość litery należy do składu, a nie do lematu, bo ta sama rzecz stoi raz na początku zdania, a raz w jego środku.

Przecinek, którego żądają krańce zdania, nie staje nigdzie, bo z jednej strony stoi kropka, a z drugiej nie stoi nic. Odjąć go stąd nie ma czego: żądanie krańca jest polem Kawałek, a nie znakiem doklejonym do napisu.

Source code in olski/skład/składnia.py
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
def kompiluj(drzewo, kontekst: Kontekst = TERAZ) -> str:
    """Drzewo jako zdanie: wielka litera na początku i kropka na końcu.

    Wielkość litery należy do składu, a nie do lematu,
    bo ta sama rzecz stoi raz na początku zdania, a raz w jego środku.

    Przecinek, którego żądają krańce zdania, nie staje nigdzie,
    bo z jednej strony stoi kropka, a z drugiej nie stoi nic.
    Odjąć go stąd nie ma czego: żądanie krańca jest polem ``Kawałek``,
    a nie znakiem doklejonym do napisu.
    """
    tekst = drzewo.linearyzuj(kontekst).napis
    return f"{tekst[0].upper()}{tekst[1:]}."

nie(zdanie)

To samo zdanie zaprzeczone.

Konstruktorem to nie jest, tylko zmianą jednej cechy zdania, bo zaprzeczone zdanie ma te same role co twierdzące i drugi konstruktor kazałby wypisać je jeszcze raz.

Sięga jednego orzeczenia, bo tyle znaczy nie w polszczyźnie, więc ciąg zdarzeń przeczy się zdarzenie po zdarzeniu, a nie w całości: Nie podniosła deski i nie zeszła po schodach.

Source code in olski/skład/składnia.py
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
def nie(zdanie: Jest | Robi) -> Jest | Robi:
    """To samo zdanie zaprzeczone.

    Konstruktorem to nie jest, tylko zmianą jednej cechy zdania,
    bo zaprzeczone zdanie ma te same role co twierdzące
    i drugi konstruktor kazałby wypisać je jeszcze raz.

    Sięga jednego orzeczenia, bo tyle znaczy ``nie`` w polszczyźnie,
    więc ciąg zdarzeń przeczy się zdarzenie po zdarzeniu,
    a nie w całości: `Nie podniosła deski i nie zeszła po schodach.`
    """
    return replace(zdanie, przeczenie=True)

po_poprzednim(zdanie, poprzednie, kontekst)

Kontekst zdania stojącego za poprzednim, czyli z podmiotem opuszczonym albo nie.

Pytają o to trzy miejsca i muszą dostać tę samą odpowiedź: akapit i ciąg zdarzeń, bo z tego składają tekst, oraz odsiew olski/skład/makieta.py, bo pyta o zdanie, które akapit dopiero złoży. Trzy kopie tego jednego wiersza rozjechałyby się na pierwszym warunku dopisanym do pomijalny wyżej, a odsiew mierzyłby wtedy inny tekst, niż akapit potem wypisze.

Source code in olski/skład/składnia.py
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
def po_poprzednim(zdanie: Zdanie, poprzednie: Zdanie | None, kontekst: Kontekst) -> Kontekst:
    """Kontekst zdania stojącego za poprzednim, czyli z podmiotem opuszczonym albo nie.

    Pytają o to trzy miejsca i muszą dostać tę samą odpowiedź:
    akapit i ciąg zdarzeń, bo z tego składają tekst,
    oraz odsiew ``olski/skład/makieta.py``, bo pyta o zdanie, które akapit dopiero złoży.
    Trzy kopie tego jednego wiersza rozjechałyby się na pierwszym warunku
    dopisanym do ``pomijalny`` wyżej, a odsiew mierzyłby wtedy inny tekst,
    niż akapit potem wypisze.
    """
    return replace(kontekst, pomijany=pomijalny(zdanie, poprzednie, kontekst))

pomijalny(zdanie, poprzednie, kontekst)

Podmiot, którego nie trzeba wypisywać, bo czytelnik odzyska go z czasownika.

Warunków jest cztery i każdy chroni przed inną stratą. Podmiot bez tożsamości nie jest tym samym podmiotem, tylko takim samym, a podmiot inny niż w zdaniu obok odsyła czytelnika do kogoś, o kim nie mowa. Podmiot opisany zdaniem przepada wraz z opisem, czyli wraz z tym, co autor o nim akurat powiedział, więc opuszczeniem to nie jest.

Czwarty warunek jest tym, którego reguła sama z siebie nie ma, a bez którego opuszczenie mówi co innego, niż mówił autor. Po opuszczonym podmiocie zostaje forma czasownika, więc podmiot wraca stamtąd tylko wtedy, gdy nikt inny tej samej formy z tego czasownika nie wyciąga. Skrzynia stojąca w piwnicy odbiera córce krawca rodzaj żeński, a bazyliszek odbiera czeladnikowi rodzaj męski, i wtedy podmiot staje wypisany, choć zdanie obok mówiło o tym samym. Liczone jest to tym samym czasownikiem, który podmiotu nie wypisze, bo różnice, których on nie robi, nie są różnicami dla czytelnika: czas przeszły rozdziela rodzaje, a teraźniejszy nie rozdziela żadnego.

Source code in olski/skład/składnia.py
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
def pomijalny(zdanie: Zdanie, poprzednie: Zdanie | None, kontekst: Kontekst):
    """Podmiot, którego nie trzeba wypisywać, bo czytelnik odzyska go z czasownika.

    Warunków jest cztery i każdy chroni przed inną stratą.
    Podmiot bez tożsamości nie jest tym samym podmiotem, tylko takim samym,
    a podmiot inny niż w zdaniu obok odsyła czytelnika do kogoś, o kim nie mowa.
    Podmiot opisany zdaniem przepada wraz z opisem, czyli wraz z tym,
    co autor o nim akurat powiedział, więc opuszczeniem to nie jest.

    Czwarty warunek jest tym, którego reguła sama z siebie nie ma,
    a bez którego opuszczenie mówi co innego, niż mówił autor.
    Po opuszczonym podmiocie zostaje forma czasownika, więc podmiot wraca stamtąd
    tylko wtedy, gdy nikt inny tej samej formy z tego czasownika nie wyciąga.
    Skrzynia stojąca w piwnicy odbiera córce krawca rodzaj żeński,
    a bazyliszek odbiera czeladnikowi rodzaj męski,
    i wtedy podmiot staje wypisany, choć zdanie obok mówiło o tym samym.
    Liczone jest to tym samym czasownikiem, który podmiotu nie wypisze,
    bo różnice, których on nie robi, nie są różnicami dla czytelnika:
    czas przeszły rozdziela rodzaje, a teraźniejszy nie rozdziela żadnego.
    """
    podmiot = zdanie.podmiot
    tożsamość = podmiot.tożsamość
    if tożsamość is None or poprzednie is None:
        return None
    if poprzednie.podmiot.tożsamość is not tożsamość or isinstance(podmiot, Opis):
        return None
    forma = forma_czasownika(zdanie.czasownik, podmiot, kontekst)
    mylące = (
        rola
        for rola in (*poprzednie.podmioty, *zdanie.podmioty)
        if rola.tożsamość is not tożsamość
    )
    if any(forma_czasownika(zdanie.czasownik, rola, kontekst) == forma for rola in mylące):
        return None
    return tożsamość

zdarzenie(kto, czyn, *reszta)

Zdarzenie złożone z tego, co dostało, po kategoriach, a nie po pozycjach.

Pierwszy argument jest tym, kto działa, i stoi zawsze. Reszta rozdziela się kategorią (_pole): okoliczności może być wiele, a uczestnik jest w każdej pozycji jeden, więc liczenie pozycji zostaje po tej stronie, a nie po stronie autora. Czasownik nieprzechodni składa się więc tak samo jak przechodni, a o pozycje pyta rama z leksykonu, którą sprawdza Robi.

Source code in olski/skład/składnia.py
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
def zdarzenie(kto, czyn: str, *reszta) -> Robi:
    """Zdarzenie złożone z tego, co dostało, po kategoriach, a nie po pozycjach.

    Pierwszy argument jest tym, kto działa, i stoi zawsze.
    Reszta rozdziela się kategorią (:func:`_pole`): okoliczności może być wiele,
    a uczestnik jest w każdej pozycji jeden,
    więc liczenie pozycji zostaje po tej stronie, a nie po stronie autora.
    Czasownik nieprzechodni składa się więc tak samo jak przechodni,
    a o pozycje pyta rama z leksykonu, którą sprawdza ``Robi``.
    """
    pola: dict[str, list] = {"co": [], "komu": [], "okoliczniki": []}
    for część in reszta:
        pola[_pole(_goły(część))].append(część)
    for nazwa in ("co", "komu"):
        if len(pola[nazwa]) > 1:
            raise PozaRamą(f"{czyn} dostaje {len(pola[nazwa])} uczestników w jednej pozycji")
    return Robi(
        kto=byt(kto),
        czyn=czyn,
        co=byt(pola["co"][0]) if pola["co"] else None,
        komu=pola["komu"][0] if pola["komu"] else None,
        okoliczniki=tuple(pola["okoliczniki"]),
    )

staje_na_czele(spójnik, relacja)

Czy zdanie z tym spójnikiem wolno wysunąć przed to, przy którym stoi.

Pytany jest ten leksykon, a nie polszczyzna liczona z relacji, bo bo i ponieważ stoją w jednej relacji i odpowiadają różnie.

Source code in olski/skład/spójniki.py
57
58
59
60
61
62
63
def staje_na_czele(spójnik: str, relacja: str) -> bool:
    """Czy zdanie z tym spójnikiem wolno wysunąć przed to, przy którym stoi.

    Pytany jest ten leksykon, a nie polszczyzna liczona z relacji,
    bo ``bo`` i ``ponieważ`` stoją w jednej relacji i odpowiadają różnie.
    """
    return SPÓJNIKI[spójnik, relacja]

wprowadza(spójnik, relacja)

Czy tym słowem polszczyzna wprowadza zdarzenie stojące w tej relacji.

Odpowiedzią jest prawda albo fałsz, a nie wyjątek, bo zgłasza go konstruktor okolicznika w olski/skład/składnia.py, czyli to samo miejsce, które zgłasza milczenie leksykonu przyimków.

Source code in olski/skład/spójniki.py
47
48
49
50
51
52
53
54
def wprowadza(spójnik: str, relacja: str) -> bool:
    """Czy tym słowem polszczyzna wprowadza zdarzenie stojące w tej relacji.

    Odpowiedzią jest prawda albo fałsz, a nie wyjątek,
    bo zgłasza go konstruktor okolicznika w ``olski/skład/składnia.py``,
    czyli to samo miejsce, które zgłasza milczenie leksykonu przyimków.
    """
    return (spójnik, relacja) in SPÓJNIKI