Reguły tagowania¶
Reguły tagowania wywodzą się z tagera TaKIPI. Pozwalają one na zapis reguł w stylu „wykreśl interpretację X tokenu bieżącego, o ile zachodzi warunek Y”.
W WCCL reguły te mają nieco inną składnię niż w JOSKIPI (przede wszystkim nie ma numerków, w zamian są nazwy). Poza tym rozszerzono mechanizm reguł o dwa zasadnicze elementy:- Dodano mechanizm unifikacji inspirowany Spejdem.
- Dodano możliwość znakowania anotacji w ograniczonym zakresie (tak więc wbrew nazwie, reguły nie muszą służyć tylko tagowaniu).
Każda reguła tagowania, podobnie jak wyrażenie funkcyjne WCCL, wartościowana jest względem bieżącej pozycji w zdaniu. Domyślnie zakłada się, że poddawany modyfikacji jest token bieżący (na pozycji 0).
Reguła tagowania określana jest przez nazwę, ciąg akcji do wykonania oraz opcjonalny warunek (jeśli warunek nie zostanie podany, to równoważne jest to warunkowiTrue
). Reguły tagowania odpalane są na bieżącej pozycji w zdaniu. Parser powinien pozwalać na przeparsowanie ciągu reguł i udostępnienie wygodnego mechanizmu, który pozwala na odpalenie całego ciągu reguł na zdaniu w dwóch trybach:
- jednorazowo — iterujemy po pozycjach w zdaniu i dla każdej pozycji kolejno próbujemy wszystkich reguł oraz
- iteracyjnie — dopóki są zmiany. Reguła zwraca czy dokonała jakichkolwiek zmian w zdaniu.
Akcje reguł są specjalnego typu wyrażeniami, które przypominają predykaty, lecz mają (mogą mieć) skutki uboczne.
Składnia i semantyka reguł¶
rule(NAME, ACTIONS)
rule(NAME, COND, ACTIONS)
NAME
to string określający nazwę reguły (przydatne w diagnozowaniu), COND
to dowolny predykat, a ACTIONS
to niepusty ciąg akcji oddzielonych przecinkami. Odpalenie reguły zaczyna się od sprawdzenia warunku. Jeśli warunek jest spełniony, akcje uruchamiane są sekwencyjnie. Każda akcja zwraca informację o tym, czy reguła dokonała jakichkolwiek zmian w zdaniu. Reguła zwraca wartość, która określa, czy którakolwiek z akcji dokonała zmian. Uwaga: to nie jest operator and
; gdy warunek jest spełniony, to odpalane są wszystkie akcje — niezależnie od tego, czy pierwsza akcja dokonała zmian.
Uwaga: zwracana wartość określa, czy którakolwiek z reguł dokonała zmian w zdaniu. W skrajnym wypadku zwrócona może być wartość True
, mimo że efektywnie zmian nie będzie — stać się tak może jeśli druga akcja cofa działanie pierwszej.
Przykładowa reguła zawierająca warunek:
rule("r1", in(class[0], {subst,xxx}), delete( equal(class[0], {xxx}) ) )
Reguła może być prostsza, np.:
rule("r2", delete( equal(cas[0], {voc}) ) )
Ciąg reguł to wyrażenie o następującej składni:
tag_rules( RULE; RULE2; ..., RULEn )
Ciąg reguł nie może być pusty. Ciąg jest parsowany do obiektu pozwalającego na aplikację reguł na podanym zdaniu.
Akcje¶
Część akcji ma dwa warianty: z podaniem pozycji oraz bez. Warianty bez podawania pozycji są równoznaczne z podaniem pozycji 0
.
Akcje badające leksem po leksemie¶
Akcje te działają w specyficzny sposób: wyjmujemy wszystkie leksemy z tokenu na podanej pozycji, po czym każdorazowo wkładamy z powrotem po jednym leksemie i sprawdzamy czy spełniony jest warunek (zależny od danego operatora). Otrzymujemy w ten sposób dwie grupy leksemów — te, które samodzielnie spełniają predykat (dokładniej: gdy jednoleksemowy token spełnia predykat) oraz pozostałe. Wynikiem działania operatora jest wstawienie nowego zbioru leksemów na miejsce starego. Nowy zbiór ustalany jest na podstawie wspomnianych grup oraz specyfiki konkretnego operatora.
delete(pos, pred)
, delete(pred)
— pozostawia jedynie leksemy niespełniające predykatu, no chyba że wszystkie spełniają, to nie wprowadza żadnych zmian
select(pos, pred)
, select(pred)
— pozostawia jedynie leksemy spełniające predykat, no chyba że żaden nie spełnia, to nie wprowadza żadnych zmian
relabel(pos, tset_op, pred)
, relabel(tset_op, pred)
— leksemy niespełniające predykatu pozostają niezmienione, natomiast spełniające poddawane są korekcie tagów; korekta tagów polega na wstawieniu podanych w zbiorze uzyskanym z tset_op
wartości w odpowiednie miejsce tagu, czyszcząc poprzednie wartości ustawianych atrybutów, łącznie z klasą gramatyczną (jeśli została podana)
Uwaga: akcji relabel
należy używać ostrożnie, gdyż może ona prowadzić do powstania tagów niezgodnych z tagsetem. Dalszych konsekwencji takiego stanu rzeczy nie da się określić na etapie specyfikacji języka (zależy to od implementacji).
Unifikacja zakresu¶
Unifikacja jest próbą wymuszenia uzgodnienia na podanym zakresie. W tym wypadku wymuszamy „bardzo słabe uzgodnienie”, tj. odpowiednik słabego uzgodnienia lecz bez szczególnego traktowania krańców zakresu (wszystkie tokeny z zakresu traktowane są jak środek zakresu słabego uzgodnienia). Wymuszenie polega na zostawieniu jedynie tych leksemów, które nie naruszają uzgodnienia. Zwracamy True
tylko wtedy, gdy usuniemy przynajmniej jeden leksem.
unify(pos1, pos2, agr_attrs)
Operator unify
może być szczególnie przydatny, jeśli przynajmniej jedna z pozycji będzie wskazywana przez zmienną, której wartością użytkownik może sterować.
Akcje zmieniające anotacje¶
Uwaga: w poniższych operacjach podane zakresy są najpierw przycinane do granic zdania.
mark(pos1, pos2, phrase)
— w kanale o nazwie phrase
znakuje anotację zaczynającą się od pos1
, kończącą się na pos2
; nardzędnik ustawiany jest na pos1
.
mark(pos1, pos2, head_pos, phrase)
— w kanale o nazwie phrase
znakuje anotację zaczynającą się od pos1
, kończącą się na pos2
; nadrzędnik ustawiany jest na head_pos
. Jeśli przekazany head_pos
jest poza zakresem, powinno zgłosić wyjątek.
unmark(pos, phrase)
— w kanale o nazwie phrase
usuwa anotację, która przechodzi przez pozycję pos
. Jeśli przez tę pozycję nie przechodzi żadna anotacja, nie dzieje się nic.
Uwaga: jeśli przez podany zakres przebiega jakakolwiek anotacja, żadna akcja nie jest wykonywana.