Przejdź do treści

olski.parse.czytanie

Czytanie i jego kawałki: pozycja lasu, liść i węzeł.

Typy, którymi mówią do siebie warstwy rozbioru i którymi parser odpowiada na zewnątrz. Co czyni dwa wyprowadzenia jednym czytaniem, rozstrzyga Node.signature.

Tree = Leaf | Node module-attribute

Cykl

Bases: Exception

Pozycja stoi sama pod sobą, więc czytań jest nieskończenie wiele.

Source code in olski/parse/czytanie.py
15
16
class Cykl(Exception):
    """Pozycja stoi sama pod sobą, więc czytań jest nieskończenie wiele."""

Pozycja dataclass

Miejsce w tablicy: co się wyprowadza i skąd dokąd.

Pakowanie polega na tym, że dwa wyprowadzenia jednego kształtu dostają jedną pozycję. Las rośnie wtedy z długością zdania, a nie z liczbą czytań.

Etykieta i rozpiętość to dokładnie tyle, ile odróżnia jedno czytanie od drugiego, a Node.signature wywodzi dlaczego; pozycja o jeden składnik bogatsza liczyłaby wyprowadzenia zamiast czytań. Ile kosztuje rozdzielanie pozycji po cechach, mierzy docs/parsowanie.md#co-się-pakuje-rozstrzyga-tożsamość-czytania.

Liść etykiety nie ma, bo czytaniem liścia jest sama rozpiętość: dwa czytania jednej formy są jednym liściem.

Source code in olski/parse/czytanie.py
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@dataclass(frozen=True)
class Pozycja:
    """Miejsce w tablicy: co się wyprowadza i skąd dokąd.

    Pakowanie polega na tym, że dwa wyprowadzenia jednego kształtu dostają jedną pozycję.
    Las rośnie wtedy z długością zdania, a nie z liczbą czytań.

    Etykieta i rozpiętość to dokładnie tyle, ile odróżnia jedno czytanie od drugiego,
    a :meth:`Node.signature` wywodzi dlaczego;
    pozycja o jeden składnik bogatsza liczyłaby wyprowadzenia zamiast czytań.
    Ile kosztuje rozdzielanie pozycji po cechach, mierzy
    docs/parsowanie.md#co-się-pakuje-rozstrzyga-tożsamość-czytania.

    Liść etykiety nie ma, bo czytaniem liścia jest sama rozpiętość:
    dwa czytania jednej formy są jednym liściem.
    """

    label: str | None
    span: tuple[int, int]

    @property
    def liść(self) -> bool:
        return self.label is None

label instance-attribute

span instance-attribute

liść property

__init__(label, span)

Leaf dataclass

Forma pod terminalem i czytania, którymi ją ten kształt bierze.

Source code in olski/parse/czytanie.py
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
@dataclass(frozen=True)
class Leaf:
    """Forma pod terminalem i czytania, którymi ją ten kształt bierze."""

    segment: Segment
    #: Odczytania licencjonujące ten liść w kształcie, w jakim stoi, a nie
    #: dowolne odczytania formy: `lubi` pod orzeczeniem ma tu samo `lubić`, choć
    #: Morfeusz czyta tę formę również jako rzeczownik i jako przymiotnik.
    #: Jest ich kilka tam, gdzie kształtu nie rozstrzygają — `Janek` w podmiocie
    #: stoi i jako `subst:sg:nom:m1`, i jako nazwisko nieodmienne —
    #: i wtedy wybór między nimi nie należy do gramatyki
    #: (:meth:`Node.signature` mówi, dlaczego odczytania kształt nie liczy).
    #: Kolejność jest kolejnością odczytań w segmencie, żeby dwa przebiegi
    #: wypisywały to samo.
    odczytania: tuple[Reading, ...]

    @property
    def reading(self) -> Reading:
        """Pierwsze z odczytań licencjonujących, dla tego, kto pyta o jedno.

        Kto pyta o lemat, tym wyborem wiązać się nie powinien:
        ``olski/skład/rozbiór.py`` pyta o lemat krawędź grafu i mówi, po co.
        """
        return self.odczytania[0]

    @property
    def span(self) -> tuple[int, int]:
        return (self.segment.start, self.segment.end)

    def signature(self):
        """Liść jest swoją rozpiętością i niczym więcej.

        Część mowy zeszła stąd rozmyślnie i nie ma tu wracać przez przeoczenie;
        co ją zdjęło, mówi :meth:`Node.signature`.
        """
        return self.span

    def forms(self) -> list[str]:
        return [self.segment.form]

    def liść_głowy(self) -> Leaf:
        """Głową słowa jest ono samo, i tu schodzenie po głowach się kończy."""
        return self

segment instance-attribute

odczytania instance-attribute

reading property

Pierwsze z odczytań licencjonujących, dla tego, kto pyta o jedno.

Kto pyta o lemat, tym wyborem wiązać się nie powinien: olski/skład/rozbiór.py pyta o lemat krawędź grafu i mówi, po co.

span property

__init__(segment, odczytania)

signature()

Liść jest swoją rozpiętością i niczym więcej.

Część mowy zeszła stąd rozmyślnie i nie ma tu wracać przez przeoczenie; co ją zdjęło, mówi Node.signature.

Source code in olski/parse/czytanie.py
73
74
75
76
77
78
79
def signature(self):
    """Liść jest swoją rozpiętością i niczym więcej.

    Część mowy zeszła stąd rozmyślnie i nie ma tu wracać przez przeoczenie;
    co ją zdjęło, mówi :meth:`Node.signature`.
    """
    return self.span

forms()

Source code in olski/parse/czytanie.py
81
82
def forms(self) -> list[str]:
    return [self.segment.form]

liść_głowy()

Głową słowa jest ono samo, i tu schodzenie po głowach się kończy.

Source code in olski/parse/czytanie.py
84
85
86
def liść_głowy(self) -> Leaf:
    """Głową słowa jest ono samo, i tu schodzenie po głowach się kończy."""
    return self

Node dataclass

Source code in olski/parse/czytanie.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
@dataclass(frozen=True)
class Node:
    label: str
    children: tuple[Leaf | Node, ...]
    #: Skąd dokąd węzeł sięga w grafie segmentów.
    #: Wpisana przy budowaniu,
    #: bo węzeł produkcji o pustym ciele nie ma dzieci, z których dałoby się ją wyliczyć,
    #: a stoi w miejscu, które zna parser.
    #: Takiej produkcji gramatyka olskiego nie ma i nie żąda jej rozwinięcie szyku:
    #: miejsce na okolicznik wychodzi z niego osobnym ciałem, a nie córką o pustej rozpiętości,
    #: bo córka taka stałaby w każdym miejscu każdego zdania i mnożyła wyprowadzenia.
    #: Pustego ciała żąda natomiast luka, i tego żądania nikt nie zaspokoił.
    span: tuple[int, int]
    #: Która z córek jest głową, wzięta z produkcji, która ten węzeł złożyła.
    #: Niesie ją węzeł, a nie odczytuje się jej z gramatyki,
    #: bo streszczenie czytania gramatyki nie dostaje,
    #: a węzeł powstaje tam, gdzie produkcja jest pod ręką.
    głowa: int
    #: Pozycje cennika, którymi płaci produkcja tego węzła (``olski/cennik.py``).
    #: Niesione tu z tego samego powodu co głowa: rachunek czytania składa się nad
    #: drzewem, a drzewo gramatyki już nie widzi.
    koszty: tuple[str, ...]

    def signature(self):
        """Co czyni dwa czytania jednym czytaniem.

        Czytanie jest swoim kształtem i niczym więcej: role stoją w etykietach
        węzłów, przyłączenie w rozpiętościach, a wszystko, o co olski pyta, jest
        pytaniem o drzewo. Wyłączone rozmyślnie: wartości cech, bo zgodność
        wymusiła już unifikacja; lematy, bo polskie formy są homonimiczne
        wszędzie i liczone jako dwa odrzuciłyby prawie całą polszczyznę; części
        mowy, bo tam, gdzie zmieniają strukturę, różni wyprowadzenia już
        kształt — ``do`` jako przyimek i jako nuta dalej są dwoma czytaniami.

        Ostatnią z tych trzech wywodzi docs/subset.md: co ją zdjęło, ile to
        kupuje nad bankiem drzew i czego było warunkiem.

        Pozycja lasu niesie dokładnie ten kształt,
        więc dwa drzewa wyliczone z lasu mają dwie różne sygnatury
        i nie ma tu czego odsiewać.

        Wyliczone drzewo niesie za to więcej niż sygnaturę,
        bo na liściach stoją czytania, a tych kształt nie liczy.
        Klasa czytania zbiera wyprowadzenia różne samą morfologią,
        więc nie rozstrzyga, które z nich w drzewie stoi;
        rozstrzyga, że czytanie spoza niej jest w nim błędem,
        i tyle drzewo dostaje (:meth:`Las._wybierz`).
        """
        return (self.label, tuple(child.signature() for child in self.children))

    def forms(self) -> list[str]:
        return [form for child in self.children for form in child.forms()]

    def liść_głowy(self) -> Leaf:
        """Liść głowy tego konstytuenta: jedno słowo, którym się go nazywa.

        Schodzi po głowach aż do liścia,
        bo głową grupy jest słowo, a nie podgrupa:
        gospodarzem przyłączenia jest ``koszt``, a nie ``koszt szynki``.

        Liściem, a nie samą formą, bo pytający pytają o dwie różne rzeczy o tym
        samym słowie: streszczenie o formę (:meth:`forma_głowy`), a wiersz żądania
        o odczytania, którymi ono w tym kształcie stoi (``olski/werdykt.py``).
        """
        return self.children[self.głowa].liść_głowy()

    def forma_głowy(self) -> str:
        return self.liść_głowy().segment.form

    def find(self, label: str, skip: Sequence[str] = ()) -> list[Node]:
        """Every node with this label, this one included, outermost first.

        A subtree labelled with one of ``skip`` is named where it stands and not
        entered, which is how the summary asks for the roles of the clause it
        summarises rather than for the roles of a clause subordinate to it
        (:attr:`Deklaracja.podrzędne`). Named, because a subordinate clause is
        sometimes a role itself: an adverbial clause is one of the roles readings
        differ in, and its inside is a separate sentence all the same.
        The coverage check passes nothing, because the gold tree marks a role
        wherever a clause has one.
        """
        found = [self] if self.label == label else []
        if self.label in skip:
            return found
        for child in self.children:
            if isinstance(child, Node):
                found.extend(child.find(label, skip))
        return found

label instance-attribute

children instance-attribute

span instance-attribute

głowa instance-attribute

koszty instance-attribute

__init__(label, children, span, głowa, koszty)

signature()

Co czyni dwa czytania jednym czytaniem.

Czytanie jest swoim kształtem i niczym więcej: role stoją w etykietach węzłów, przyłączenie w rozpiętościach, a wszystko, o co olski pyta, jest pytaniem o drzewo. Wyłączone rozmyślnie: wartości cech, bo zgodność wymusiła już unifikacja; lematy, bo polskie formy są homonimiczne wszędzie i liczone jako dwa odrzuciłyby prawie całą polszczyznę; części mowy, bo tam, gdzie zmieniają strukturę, różni wyprowadzenia już kształt — do jako przyimek i jako nuta dalej są dwoma czytaniami.

Ostatnią z tych trzech wywodzi docs/subset.md: co ją zdjęło, ile to kupuje nad bankiem drzew i czego było warunkiem.

Pozycja lasu niesie dokładnie ten kształt, więc dwa drzewa wyliczone z lasu mają dwie różne sygnatury i nie ma tu czego odsiewać.

Wyliczone drzewo niesie za to więcej niż sygnaturę, bo na liściach stoją czytania, a tych kształt nie liczy. Klasa czytania zbiera wyprowadzenia różne samą morfologią, więc nie rozstrzyga, które z nich w drzewie stoi; rozstrzyga, że czytanie spoza niej jest w nim błędem, i tyle drzewo dostaje (Las._wybierz).

Source code in olski/parse/czytanie.py
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
def signature(self):
    """Co czyni dwa czytania jednym czytaniem.

    Czytanie jest swoim kształtem i niczym więcej: role stoją w etykietach
    węzłów, przyłączenie w rozpiętościach, a wszystko, o co olski pyta, jest
    pytaniem o drzewo. Wyłączone rozmyślnie: wartości cech, bo zgodność
    wymusiła już unifikacja; lematy, bo polskie formy są homonimiczne
    wszędzie i liczone jako dwa odrzuciłyby prawie całą polszczyznę; części
    mowy, bo tam, gdzie zmieniają strukturę, różni wyprowadzenia już
    kształt — ``do`` jako przyimek i jako nuta dalej są dwoma czytaniami.

    Ostatnią z tych trzech wywodzi docs/subset.md: co ją zdjęło, ile to
    kupuje nad bankiem drzew i czego było warunkiem.

    Pozycja lasu niesie dokładnie ten kształt,
    więc dwa drzewa wyliczone z lasu mają dwie różne sygnatury
    i nie ma tu czego odsiewać.

    Wyliczone drzewo niesie za to więcej niż sygnaturę,
    bo na liściach stoją czytania, a tych kształt nie liczy.
    Klasa czytania zbiera wyprowadzenia różne samą morfologią,
    więc nie rozstrzyga, które z nich w drzewie stoi;
    rozstrzyga, że czytanie spoza niej jest w nim błędem,
    i tyle drzewo dostaje (:meth:`Las._wybierz`).
    """
    return (self.label, tuple(child.signature() for child in self.children))

forms()

Source code in olski/parse/czytanie.py
139
140
def forms(self) -> list[str]:
    return [form for child in self.children for form in child.forms()]

liść_głowy()

Liść głowy tego konstytuenta: jedno słowo, którym się go nazywa.

Schodzi po głowach aż do liścia, bo głową grupy jest słowo, a nie podgrupa: gospodarzem przyłączenia jest koszt, a nie koszt szynki.

Liściem, a nie samą formą, bo pytający pytają o dwie różne rzeczy o tym samym słowie: streszczenie o formę (forma_głowy), a wiersz żądania o odczytania, którymi ono w tym kształcie stoi (olski/werdykt.py).

Source code in olski/parse/czytanie.py
142
143
144
145
146
147
148
149
150
151
152
153
def liść_głowy(self) -> Leaf:
    """Liść głowy tego konstytuenta: jedno słowo, którym się go nazywa.

    Schodzi po głowach aż do liścia,
    bo głową grupy jest słowo, a nie podgrupa:
    gospodarzem przyłączenia jest ``koszt``, a nie ``koszt szynki``.

    Liściem, a nie samą formą, bo pytający pytają o dwie różne rzeczy o tym
    samym słowie: streszczenie o formę (:meth:`forma_głowy`), a wiersz żądania
    o odczytania, którymi ono w tym kształcie stoi (``olski/werdykt.py``).
    """
    return self.children[self.głowa].liść_głowy()

forma_głowy()

Source code in olski/parse/czytanie.py
155
156
def forma_głowy(self) -> str:
    return self.liść_głowy().segment.form

find(label, skip=())

Every node with this label, this one included, outermost first.

A subtree labelled with one of skip is named where it stands and not entered, which is how the summary asks for the roles of the clause it summarises rather than for the roles of a clause subordinate to it (Deklaracja.podrzędne). Named, because a subordinate clause is sometimes a role itself: an adverbial clause is one of the roles readings differ in, and its inside is a separate sentence all the same. The coverage check passes nothing, because the gold tree marks a role wherever a clause has one.

Source code in olski/parse/czytanie.py
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
def find(self, label: str, skip: Sequence[str] = ()) -> list[Node]:
    """Every node with this label, this one included, outermost first.

    A subtree labelled with one of ``skip`` is named where it stands and not
    entered, which is how the summary asks for the roles of the clause it
    summarises rather than for the roles of a clause subordinate to it
    (:attr:`Deklaracja.podrzędne`). Named, because a subordinate clause is
    sometimes a role itself: an adverbial clause is one of the roles readings
    differ in, and its inside is a separate sentence all the same.
    The coverage check passes nothing, because the gold tree marks a role
    wherever a clause has one.
    """
    found = [self] if self.label == label else []
    if self.label in skip:
        return found
    for child in self.children:
        if isinstance(child, Node):
            found.extend(child.find(label, skip))
    return found