Nowości w języku¶
Ten dokument opisuje zmiany w języku w stosunku do JOSKIPI. Są to zarówno zmiany typowo składniowe, jak i nowa funkcjonalność.
Główne zmiany składniowe¶
1. Operator flex
zmienia nazwę na class
. Motywacja: skrót flex nie kojarzy się z klasą gramatyczną, poza tym obsługujemy dowolny tagset, więc klasy słów nie muszą być klasami fleksyjnymi.
2. Zbiory stringów zapisujemy w nawiasach kwadratowych (np. ["zawsze", "nigdy", "czasami"]
, []
), zbiory symboli z tagsetu zapisujemy w nawiasach wąsowych ({nom,acc}
, {cas}
, {}
). Pozostawiliśmy cukier składniowy dla zbiorów jednoelementowych (można pominąć nawiasy — sg
= {sg}
, "tak"
= ["tak"]
). Motywacja: teraz typ pustych zbiorów jest jednoznaczny.
3. Dowolne wyrażenie można do woli otaczać nawiasami.
4. Dodaliśmy komentarze blokowe — składnia /* … */
(bez zagnieżdżania). Działają też komentarze jednoliniowe //
.
5. Wszelkie stringi można zapisać zarówno w cudzysłowach ASCII, jak i w apostrofach ASCII (jak w Pythonie, np. '"'
oznacza znak cudzysłowia). Oprócz tego dopuszczalne są sekwencje kontrolne (escape sequences) zdefiniowane przez ICU, m.in. \uhhhh
(znak unikodowy o podanym kodzie).
6. Operatory uzgodnienia: usunęliśmy ostatni, nadmiarowy argument, czyli liczbę atrybutów („bitów”). Reszta argumentów pozostaje na swoich miejscach, semantyka niezmieniona.
7. Mamy literały True
, False
, {}
(pusty zbiór symboli), []
(pusty zbiór stringów).
8. Nazwy symboli z tagsetu można otoczyć znakami Gravis („backtick”, U+0060 GRAVE ACCENT). To może być przydatne, gdyby w którymś tagsecie symbol pokrywał się ze słowem kluczowym języka, np. gdybyśmy mieli symbol if
, można go zapisać `if`
i parser nie potraktuje tego jak słowa kluczowego.
9. Nazwy zmiennych również można otoczyć znakami Gravis, np. $`agr`
to zmienna o nazwie agr
. To tylko możliwość, nie zachęcamy do nadużywania jej.
Ujednolicona składnia pliku WCCL i leksykony¶
Język JOSKIPI definiował różne składnie w zależności od konkretnych zastosowań: plik definiujący wzorce tagera miał inną składnię, inną składnię miały reguły tagowania, a jeszcze inną plik zawierający jeden predykat. W WCCL-u definiujemy ogólną składnię pliku WCCL. Pozwala ona na używanie pliku o tej samej strukturze w większości zastosowań. Pozwala to też na odwołanie się do zewnętrznych słowników (leksykonów), które są ładowane jednorazowo, po czym mogą z nich korzystać wszystkie wyrażenia zawarte w pliku.
Leksykony ładowane są za pomocą deklaracji import
umieszczonej na początku pliku. Odwołanie do leksykonu realizowane jest poprzez operator lex(STRSET, LEXNAME)
, gdzie STRSET
to dowolne wyrażenie zwracające zbiór napisów, natomiast LEXNAME
to pojedynczy napis będący nazwą leksykonu (zgodnie z deklaracją import
). Operator zwraca zbiór napisów — każdy napis należący do leksykonu zamieniany jest na przypisaną mu wartość, natomiast napisy pozostałe są pomijane.
Składnię oraz format pliku z leksykonem opisano szczegółowo tu.
Zdania z anotacją (chunks/named entities)¶
Operator isannpart(pos, phrase)
wymaga zdania oznakowanego anotacjami (AnnotatedSentence). Zwraca True, jeśli przez podaną pozycję przechodzi anotacja (dowolnej długości) w kanale o nazwie phrase.
Operator isannhead(pos, phrase) działa w sposób analogiczny, lecz zwraca True, jeśli dodatkowo w danej pozycji znajduje się nadrzędnik frazy phrase.
Operatory isannbeg(pos, phrase) i isannend(pos, phrase) sprawdzają, czy na danej pozycji znajduje się odpowiednio pierwszy lub ostatni token anotacji.
Silne rozróżnienie typów danych¶
W JOSKIPI typy danych mieszały się ze sobą. W szczególności możliwe było utworzenie zbioru {subst, "kaczka"}
. Operatorom działającym z założenia na symbolach można było przekazać stringi i vice-versa.
Teraz mamy silne rozróżnienie typów danych. Każde wyrażenie — stałe, zmienne i operatory z argumentami — ma jasno określony zwracany typ. Dzięki temu więcej błędów można wykryć na etapie parsowania. Konsekwencją była konieczność zmiany wspomnianej składni zbiorów.
Pozycje są pełnoprawnym typem danych¶
1. Wycofaliśmy składnię $-2V
. Przesunięcia realizowane są teraz infiksowymi operatorami +
i -
. Przykładowo, $V - 2
, $3 - 2
, begin + 1
. Uwaga: operacje te nie są przemienne. Na pierwszym miejscu zawsze musi stać pozycja, na drugiej — liczba całkowita. Nawet jeśli oba te argumenty wyglądają tak samo (2 + 2
), to traktowane są różnie. Składnia nie pozwala na zapisy typu 2 + 2 + 2 + 2
; jeśli komuś bardzo na tym zależy, można to ująć w nawiasy: ((2 + 2) + 2) + 2
(wynik każdego działania jest typu pozycja).
equal
oraz operatory warunkowe mają też swoje warianty dla typu pozycja (można tam przekazać zarówno stałą, zmienną, jak i dowolny operator zwracający typ pozycja). Dwie pozycje są sobie równe wtt. gdy:
- obie mieszczą się w granicach zdania i wskazują na ten sam token,
- obie są poza granicami zdania i wskazywałyby na ten sam token, gdyby zdanie było odpowiednio długie,
- obie mają wartość
nowhere
.
Zmienne czterech typów danych¶
1. Pozycje: składnia $Var
. Jak wspomniano wyżej, nie ma już odwołań do zmiennej z przesunięciem, zamiast tego są operatory +
i -
.
2. Zbiory stringów: składnia $s:V
.
3. Zbiory symboli z tagsetu: składnia $t:V
.
4. Wartości logiczne: składnia $b:V
.
Uwaga: nazwa zmiennej nie musi się zaczynać z wielkiej litery. Proponuję jednak dalej używać zmiennych zaczynających się z wielkiej litery w ramach konwencji.
Jawne przypisanie wartości zmiennej: operator setvar(TARGET, EXPR)
, gdzie TARGET
to zmienna, a EXPR
to wyrażenie zwracające wartość tego typu. Np. setvar($P, begin + 2)
, setvar($t:Casehere, cas[0])
.
Operatory warunkowe¶
1. Operator if(condition, value_when_true, value_when_false)
. Operator zdefiniowany jest dla czterech typów: zbiór symboli, zbiór stringów, wartość logiczna, pozycja. Jeśli typ wyrażenia value_when_true
będzie inny niż typ value_when_false
, parser zgłosi błąd.
2. Operator if(condition, value_when_true)
. Jeśli warunek jest niespełniony, operator zwraca wartość domyślną dla danego typu, czyli odpowiednio {}
, []
, False
, nowhere
. Operator ten jest odpowiednikiem operatora ? value_when_true ? condition
, choć semantyka jest zmieniona: tamten operator w przypadku niepowodzenia zwracał pusty zbiór, niezależnie od typu wyrażenia zwracanego w razie sukcesu. W nowym języku mamy silnie określone typy danych, więc obie wartości muszą mieć ten sam typ.
Operatory warunkowe można dowolnie zagnieżdżać. Np.
if( rlook(if(inter(class[0], subst),1,0), end, $Adj, in(class[$Adj], {adj, pact, ppas}) ), if(inter({m1,m2,m3}, gnd[$Adj]),class[$Adj]) )
Operator regex¶
regex(strop, re_text)
zwraca True, jeśli wszystkie elementy zbioru stringów zwróconego przez operator strop
spełniają wyrażenie regularne re_text
(zgodne z ICU, można korzystać z character properties). Np. regex(["nie","on"],"\\p{L}+")
zwróci True
.
Zakresy pozycji¶
Operatory iterujące (np. rlook
, only
) oraz uzgodnienia na zakresach (np. agr
) przycinają podane zakresy do granic zdania zanim nastąpi ewaluacja właściwego warunku.
Pomijanie tokenów spełniających predykat¶
Wprowadzamy nowy operator iterujący skip(pos1, posvar, pred, n)
, którego zadaniem jest ustawienie wartości zmiennej posvar
na token oddalony o n
od pos1
, licząc jedynie tokeny niespełniające predykatu pred
. Operator jest przydatny do eksperymentów z pomijaniem tokenów nieistotnych składniowo (np. partykuł).
Nowe operatory pomocnicze¶
inside(pos)
i outside(pos)
sprawdzają, czy pozaycja jest odpowienio wewnąytrz lub poza zdaniem.intersection
oraz union
pozwalają wykonywac operacje sumy i iloczynu na zbiorach napisów i symboli z tagsetu.ambiguous
dla typów zbiorowych zwraca, czy zbiory te są wieloelementowe; dla typu pozycja zwraca, czy token zawiera więcej niż jeden leksem.singular(symset)
(zdefiniowany tylko dla zbiorów symboli z tagsetu) sprawdza, czy każdy z atrybutów jest reprezentowany w podanym zbiorze przez co najwyżej jedną wartość (np. że zbiór zawiera po jednej wartości przypadka i rodzaju)
Podjęzyk reguł dopasowania¶
W WCCL-u oprócz reguł tagowania (analogicznych do JOSKIPI) wprowadzono podjęzyk reguł dopasowania. Reguły te nie odwołują się do bieżącej pozycji w zdaniu, lecz iterują każdorazowo po całym zdaniu i znakują rozpoznane anotacje.
Szczegóły opisano w specyfikacji podjęzyka reguł dopasowań.