Specyfikacja wyrażeń funkcyjnych WCCL
- Typy danych, składnia zapisu stałych i zmiennych
- Składnia i semantyka
Wyrażenia funkcyjne stanowią podstawową część języka WCCL. Wyrażenia te są inspirowane operatorami języka JOSKIPI; wprowadzono jednak kilka ulepszeń (np. silną typizację) oraz kilka zmian składniowych.
Typy danych, składnia zapisu stałych i zmiennych¶
Chociaż wyrażenia języka ewaluowane są na zdaniach i tokenach, żaden z tych bytów nie ma odpowiadającego typu wspieranego przez język. Dla wyrażeń WCCL bieżące zdanie jest „całym uniwersum”, więc nie musimy go nazywać (za odpalenie na konkretnym zdaniu odpowiedzialny jest użytkownik implementacji). Jeśli chodzi o tokeny, odwołujemy się do pozycji, pod którymi widzimy różne cechy, np. orth, wartość przypadka. Fizycznie te cechy są wyłuskiwane z tokenu leżącego na podanej pozycji, lecz na tym poziomie abstrakcji widzimy konkretne cechy, a nie tokeny, leksemy itp.
Język jest statycznie typizowany, typy są wywodzone automatycznie z danych (type-inferred).
Typy danych wspierane przez język:- zbiór symboli z tagsetu, np.
{subst, fin, praet}
,{nom}
- zbiór napisów, np.
["być", "zostać"]
,['nie']
- wartości logiczne: True, False
- pozycje, czyli wskazanie na konkretny token w zdaniu względem bieżącej pozycji lub
begin
/end
(bezwzględne odwołanie do początku/końca zdania)
- liczba całkowita, np. 0, 2
- pojedynczy napis, np. "NP", 'l1.lex'
Typy liczba całkowita i pojedynczy napis są niepełnowartościowe, ponieważ 1) takich bytów nie można zwrócić, 2) dopuszczamy tylko stałe, 3) wartości te są używane w bardzo wąskich kontekstach. Co więcej, obsługa niepełnowartościowych typów danych na poziomie implementacji może być zamknięta w parserze — wartości tych typów nie można zwrócić, więc i tak nie mogą one opuścić parsera.
Typy zbiór symboli z tagsetu nie ma odpowiadającego typu „pojedynczy symbol”. Istnieje wprawdzie typ „pojedynczy napis”, ale typ ten jest niepełnowartościowy i wartości tego typu nigdy nie są przyrównywane do wartości typu „zbiór napisów”. Wszystkie operacje na symbolach i napisach zakładają, że przetwarzany jest zbiór. Jeśli mówimy o pojedynczej wartości, jest to zbiór jednoelementowy. To jest celowe. WCCL z założenia operuje na wieloznacznych interpretacjach: tokenowi przypisane może być wiele alternatywnych tagów i wiele alternatywnych lematów. Poniekąd podobnie zachowuje się typ str
i unicode
w Pythonie: nie ma typu char
, 'kocur'[1] == 'o'
.
Konkretne stałe z tagsetu nie należą do gramatyki, ponieważ tagsety mogą być różne. Gramatyka określa jedynie warunki, które musi spełniać ciąg znaków, by mógł być uznany za symbol z tagsetu. Podczas parsowania stałe z tagsetu zamieniane są na wewnętrzną reprezentację (np. liczby wg wartości zdefiniowanych w tagsecie). Reprezentacja ta jest używana tylko wewnątrz implementacji i użytkownik WCCL może uzyskać jedynie reprezentację tekstową. Stwarza to możliwość optymalizacji.
Typ „zbiór symboli z tagsetu”¶
Pomocnicza definicja składniowa: symbol to dowolny ciąg, który składa się z liter, cyfr i podkreślnika oraz nie zaczyna się cyfrą, np. nom
, NP
, _x8
. Dopuszczalna jest również składnia `sym`, gdzie znakiem otaczającym jest gravis (U+0060 GRAVE ACCENT
, „backquote”) — składnia ta pozwala na podanie pożądanej nazwy w sytuacji, gdy nazwa ta pokrywa się ze słowem kluczowym (podobną funkcję ten symbol ma w SQL-u).
Zbiór pusty: {}
Zbiór niepusty: {w1, w2, …, wn}
Zbiór jednoelementowy (cukier składniowy): w1
Każdy z elementów w1
… wn
to symbol.
- wartość klasy gramatycznej (np.
subst
) albo - wartość jednego z atrybutów (np.
nom
) albo - nazwa jednego z atrybutów (np.
cas
; klasa gramatyczna to nie atrybut).
W ostatnim przypadku każde wystąpienie nazwy atrybutu rozwijane jest do wszystkich jego wartości. Rozwijanie ma miejsce podczas parsowania, różne sposoby określenia tego samego zbioru dają ten sam wynik.
Przykładowo, w tagsecie KIPI mamy {gnd}
= {sg, pl}
{nmb, gnd, cas}
= {nmb, sg, pl, cas}
= … = {m1,m2,m3,n,f,sg,pl,nom,gen,dat,acc,loc,inst,voc}
Uwaga: symbole określające nazwy atrybutów stają się automatycznie nazwami operatorów do pobierania wartości atrybutu. Te oraz pozostałe symbole brane są z pliku definiującego tagset. Autorzy tagsetów KIPI i NKJP nie definiują takich symboli (w poprzednich JOSKIPI określiliśmy własne symbole, np. cas i ppr; dla porównania, Spejd i Pantera korzystają z pełnych nazw atrybutów, np. case, post-prepositionality).
Typ „zbiór napisów”¶
Zbiór pusty: []
Zbiór niepusty: [s1, s2, …, sn]
Zbiór jednoelementowy (cukier składniowy): s1
każdy z symboli s1
to napis otoczony cudzysłowami ASCII (U+0022 QUOTATION MARK
) bądź apostrofami ASCII (U+0027 APOSTROPHE). Dopuszczalne są sekwencje kontrolne (escape sequences) zdefiniowane przez ICU.
Typ „pozycja”¶
Pozycja wskazuje na token w przetwarzanym zdaniu. Wartością pozycji może być:nowhere
(nieustawiona),begin
(pierwszy token w zdaniu),end
(ostatni token w zdaniu),- liczba całkowita, np. -3, 0, 1 — wskazuje token względem bieżącej pozycji w zdaniu. Pozycja
0
zawsze wskazuje na bieżący token. „Bieżąca pozycja w zdaniu” nie jest pozycją w sensie tu rozumianym, jest raczej indeksem tokenu w wektorze opisującym zdanie.
Pozycja to abstrakcyjne określenie tokenu w zdaniu: pozycję określamy z góry w ramach danego wyrażenia, nie wiedząc jeszcze do jakich zdań to wyrażenie zostanie zaaplikowane. W związku z tym nie możemy na tym etapie wymagać, by pozycja mieściła się w granicach zdania. Konkretne zachowanie operatora w sytuacji, gdy jeden z jego argumentów to pozycja, która ewaluuje się do indeksu poza granicami zdania zależy od semantyki danego operatora. Wszystkie jednoargumentowe operatory przyjmujące pozycję i zwracające zbiór symboli zwracają w takiej sytuacji zbiór pusty. Zachowanie innych operatorów może być różne; np. llook
i rlook
wymagają, by obie pozycje znalazły się w granicach zdania, w przeciwnym razie operator od razu kończy.
Zmienne, ich składnia i zasięg¶
Definiujemy zmienne czterech podstawowych typów. Składnia zmiennych:$Var
(pozycja)$s:Var
(zbiór napisów)$t:Var
(zbiór symboli z tagsetu)$b:Var
(wartość logiczna)
Var
oznacza tu dowolny symbol.
Powyższa składnia zmiennych może pełnić jedną z dwóch ról: odwołanie do zmiennej (w celu pobrania wartości) albo wskazanie zmiennej (w celu zmiany przypisanej wartości). Odwołania do zmiennej typu T można użyć we wszystkich kontekstach wymagających wyrażenia typu T (np. zamiast stałej typu T, wyrażenia funkcyjnego zwracającego typ T). W przypadku kilku operatorów, np. setvar
, jeden z argumentów musi być wskazaniem zmiennej, której wartość zostanie ustawiona. Przykładowo, wyrażenie setvar($A, $B)
powoduje przypisanie zmiennej $A
wartości, którą ma obecnie zmienna $B
. Składnia zmiennych nie rozróżnia więc odwołania do zmiennej od określenia zmiennej — rozróżnienie to wynika z kontekstu życia (składnia konkretnych wyrażeń WCCL określa jakiego rodzaju argumenty są wymagane).
WCCL stosuje dynamiczny zasięg zmiennych przy założeniu, że zasięgów nie można zagnieżdżać (dążymy do prostoty kosztem uniwersalności). Przez zasięg będziemy tutaj rozumieć przypisanie identyfikatorom zmiennych ich wartości.
Wszystkie wyrażenia funkcyjne działają w zasięgu zmiennych. Zmienne nie wymagają deklaracji; pierwsze odwołanie do zmiennej o danej nazwie powoduje utworzenie w zasięgu obiektu danego typu ustawionego na wartość domyślną (w przypadku typu pozycja to nowhere
). Kolejne odwołania mogą użyć tej wartości lub ją zmienić. Nie ma możliwości przesłonięcia zasięgu innym zasięgiem.
Uwaga nt. implementacji: parser udostępnia reguły parsowania dodatkowych wyrażeń, które typem odpowiadają wyrażeniom funkcyjnym (po jednym dla każdego ze zwracanych typów), natomiast nie wymagają podania obiektu zasięgu. Reguły takie pozwolą użytkownikowi na przeparsowanie pojedynczego, „zewnętrznego” wyrażenia WCCL, tj. zakłada się, że tworzymy nowy obiekt zasięgu i w nim osadzane jest parsowane wyrażenie (fizycznie, obiekt zasięgu przekazywany jest niżej do reguły parsowania wyrażenia funkcyjnego). Obok parsowania całego pliku, takie funkcje stanowią podstawowe API parsera.
Składnia i semantyka¶
Uwaga: token rozumiany jest jako para (forma napotkana, zbiór par (lemat, tag)).
Każde wyrażenie funkcyjne ma określony typ (jeden ze zdefiniowanych czterech typów głównych).
Wyrażenie funkcyjne WCCL to- stała określonego typu lub
- odwołanie do zmiennej określonego typu lub
- operator zwracający wartość, czyli funkcja zwracająca wartość jednego ze zdefiniowanych wcześniej typów.
Wyrażenie funkcyjne jest albo czysto funkcyjne, albo ma skutki uboczne w postaci zmiany wartości przypisanym zmiennym. Innych skutków ubocznych nie dopuszczamy (w szczególności wyrażenia funkcyjne nie mogą zmienić oznakowania).
Interpretacja wyrażenia WCCL to abstrakcyjne ujęcie struktury, która powstaje po przeparsowaniu wyrażenia.
Interpretacją wyrażenia funkcyjnego WCCL jest funktor typu kontekst -> zwracany typ. Kontekst to opakowanie na zdanie, bieżącą pozycję i wartościowanie zmiennych. Idea: raz przeparsowane wyrażenie można zaaplikować do różnych zdań względem różnego tokenu centralnego (pozycji bieżącej w zdaniu). Interpretacją stałej jest funktor, który niezaleznie od kontekstu zwraca tę samą wartość. Dzięki temu samemu typowi interpretacji, możliwe jest używanie stałych i operatorów w tych samych kontekstach.
Kod WCCL może zawierać komentarze:- komentarze do końca linii po znakach
//
- komentarze wieloliniowe
/* … */
(bez zagnieżdżeń)
Wyrażenia czysto funkcyjne (w tym ograniczenia)¶
Wyrażenia funkcyjne można podzielić ze względu na typ zwracanej wartości: 1) zbiór symboli z tagsetu, 2) wartość logiczną, 3) zbiór napisów 4) pozycja.
Operatory pobierające wartości z tagsetu.¶
Odtąd w definicjach składni operatorów wszystkie argumenty nazwane pos
, pos1
, pos2
to wskazania pozycji.
op[pos]
, op
jest symbolem, jednym z poniższych:
class
(klasa gramatyczna, w JOSKIPI operator nazywał sięflex
) lub- nazwa atrybutu z tagsetu,
- nazwa wartości z tagsetu (nowe).
Jeśli podana pozycja leży poza granicami zdania, operatory te zwrócą zbiór pusty.
Operatory zwracają sumę wartości danego atrybutu lub klasy gramatycznej (class
) wszystkich tagów tokenu na podanej pozycji (tu, jak i w całym języku nie patrzymy na znaczniki disamb
). W przypadku podania konkretnej wartości (np. gen[0]
w tagsecie KIPI), operator zwróci albo zbiór jednoelementowy zawierający podaną wartość (wtt. gdy podana wartość wystąpi w którymkolwiek tagu na podanej pozycji) lub zbiór pusty (w przeciwnym razie). Operator odpowiadający atrybutowi zwróci zbiór pusty, jeśli żaden z tagów tokenu na podanej pozycji nie ma określonej wartości podanego atrybutu (np. jeśli spytamy o przypadek, a żaden z tagów nie ma określonego przypadka).
range(symbol, pos1, pos2)
symbol
to nazwa atrybutu z tagsetu lubclass
- jeśli któraś z
pos1
,pos2
ewaluuje się do indeksu poza granicami zdania, zwracamy pusty zbiór symboli - w przeciwny razie zwracamy sumę zbiorów @symbol(pos) dla pos należ. do [pos1,pos2] włącznie.
Operatory filtrujące¶
Niech tag|maska
to część wspólna zbioru zwracanego przez operator maska
i zbioru wartości wszystkich atrybutów i klasy gramatycznej tagu tag
. Np. subst:pl:nom:m1|{subst,m1,m2,m3}
= {subst,m1}
, subst:pl:nom:m1|{m1,m2,m3}
= {m1}
.
catflt(pos, which, filter)
zwraca zbiór symboli będący podzbiorem zbioru zwróconego przez filter
which
ifilter
to wyrażenia zwracające zbiory symboli,- niech tags = { (
tag
należące do tokenu na pozycjipos
) :tag|which
!= {} } catflt(pos, which, filter)
= suma zbiorów (tag|filter
dlatag
należących do tags )
agrflt(pos1, pos2, agr_attrs, filter)
zwraca zbiór symboli będący podzbiorem zbioru zwróconego przez filter
agr_attrs
ifilter
to wyrażenia zwracające zbiory symboli,- sprawdzane jest słabe uzgodnienie na podanym zakresie pozycji
- niech frags =
weak_agr_constrs(pos1, pos2, agr_attrs)
- zwracamy
{}
, jeślifset
jest pusty - w innym razie zwracamy sumę zbiorów ( część wspólna ( filter, fset ) dla fset należącego do frags )
Operatory zwracające zbiór napisów¶
Odtąd w definicjach składni operatorów wszystkie argumenty nazwane strset
, strset1
, strset2
to wyrażenie funkcyjne WCCL typu zbiór napisów. Wszystkie argumenty nazwane tset
, tset1
, … to wyrażenia funkcyjne WCCL typy zbiór symboli z tagsetu.
orth[pos]
zwraca formę napotkaną tokenu na podanej pozycji: zbiór jednoelementowy (lub pusty, jeśli pozycja wychodzi poza zakresem zdania)
base[pos]
zwraca zbiór lematów tokenu na podanej pozycji: zbiór niepusty, jeśli w granicach zdania
lower(strset)
= { lstr : lstr = lowercase ( str ) dla każdego str w strset }
upper(strset)
= { ustr : ustr = uppercase ( str ) dla każdego str w strset }
affix(strset, n)
=
n < 0: { suff : suff = suffix ( str, len
= -n or whole
) dla każdego str w strset }
n > 0: { pref : pref = prefix ( str, len
= n or whole
) dla każdego str w strset }
n = 0: strset
Jeśli długość prefiksu lub sufiksu jest dłuższa niż dany napis, pozostaje cały. Jeśli długość jest równa zero, zwraca niezmieniony zbiór.
prop(pos, strset)
pobiera token znajdujący się na pozycji pos
i sprawdza jego metadane (własności klucz--wartość). Zwracany jest zbiór zawierający wartości przypisane tym kluczom, które znajdują się w przekazanym zbiorze napisów i jednocześnie obecne są jako klucze w metadanych tokenu. Zwrócony zbiór może być pusty, jeśli żaden z przekazanych kluczy nie pojawia się w metadanych lub pozycja znajduje się poza granicami zdania.
Operator anninter(pos, phrases) wymaga zdania oznakowanego anotacjami (AnnotatedSentence). Przyjmuje pozycję pos
oraz zbiór napisów phrases
. Zwraca zbiór napisów. Semantyka jest następująca: operator sprawdza, które anotacje przecinają podaną pozycję i zwraca nazwy kanałów anotacji, które należą do podanego zbioru phrases
i jednocześnie przecinają podaną pozycję.
Operator lex
. Operator ten odwołuje się do zewnętrznego zasobu, jakim jest leksykon napisów. Można z niego skorzytać jedynie w przypadku użycia składni całego pliku (ew. gdy użytkownik implementacji w jakiś zewnętrzny sposób załaduje leksykon).
Składnia: lex(strset, string)
. Pierwszy argument to dowolne wyrażenie zwracające zbiór napisów, drugie to nazwa leksykonu (pod jaką został zaimportowany).
Operator lex
zwraca typ zbiór napisów. Operator odwołuje się do leksykonu napisów będącego odwzorowaniem napis -> napis.
Semantyka. Jeśli leksykon nie został załadowany, to zachowanie nieokreślone (implementacja powinna zgłosić wyjątek).
Operator przyjmuje zbiór napisów S i zwraca zbiór napisów {s: lex[s0] = s dla każdego s0 należącego do S}
.
Przykładowo, przy leksykon {"maca":"jadło", "serek":"jadło", "krowa":"mięso"}
przekształca zbiór ["nic"]
w []
, a zbiór ["serek","nic","maca","krowa"]
w ["jadło", "mięso"].
Operatory działające na zbiorach¶
Operatory te działają bądź na zbiorach napisów, bądź na zbiorach symboli z tagsetu.
union(s1, s2, …)
-- suma zbiorówintersection(s1, s2, …)
-- część wspólna zbiorów
Predykaty¶
Predykaty (ograniczenia) to wyrażenia funkcyjne WCCL typu logicznego.
Odtąd w definicjach składni operatorów wszystkie argumenty nazwane pred
, pred1
, pred2
, predn
to predykaty.
and(pred1, …, predn)
ewaluuje predykaty po kolei aż do pierwszej porażki i zwraca False, a w pp. Trueor(pred1, …, predn)
ewaluuje predykaty po kolei aż do pierwszego sukcesu i zwraca True, a w pp. Falsenot(pred1, …, predn)
(operacja NOR == not(or(pred1, …, predn))
) ewaluuje predykaty po kolei aż do pierwszego sukcesu i zwraca False, a w pp. True
Powyższe wyrażenia przyjmują jeden lub więcej predykatów.
in(strset1, strset2)
wtt. gdy strset1
!= {} i strset1
jest podzbiorem strset2
inter(strset1, strset2)
wtt. gdy przecięcie_zbiorów ( strset1
, strset2
) != {}equal(strset1, strset2)
wtt. gdy strset1
== strset2
I analogicznie dla zbiorów symboli:in(tset1, tset2)
wtt. gdy tset1
!= {} i tset1
jest podzbiorem tset2
inter
…equal
…
Dla typu pozycja definiujemy operator equal
:equal(pos1, pos2)
wtt. gdy pos1
== pos2
Składnia dla obu typów jest taka sama. Nie stworzy to problemu, bo typ wyrażenia da się wywieść z typów argumentów.
inside(pos)
zwraca True, gdy pozycja leży w granicach zdania.outside(pos
— na odwrót.
regex(strset, re_text)
sprawdza, czy wszystkie elementy zbioru strset
spełniają podane wyrażenie regularne (re_text
element typu nazwa zawierający wyrażenie regularne w formacie ICU)
empty(tset)
, empty(strset)
zwraca True, gdy zbiór jest pusty
ambiguous(tset)
zwraca True, gdy zbiór symboli tagsetu podany jako argument zawiera więcej niż jeden element.ambiguous(strset)
zwraca True, gdy zbiór napisów podany jako argument zawiera więcej niż jeden element.ambiguous(pos)
zwraca True, gdy token na pozycji podanej jako argument zawiera więcej niż jeden leksem.
singular(tset)
zwraca True, gdy zbiór symboli tagsetu podany jako argument jest jednostkowy, tj. zawiera co najwyżej jedną wartość dla każdego z atrybutów tagsetu. singular({sg,nom})
zwraca True
, singular({sg,pl})
-- False
.
Osobną grupą predykatów są operatory sprawdzające, czy zachodzi uzgodnienie morfo-syntaktyczne. Interpretacja uzgodnienia różnych typów omówiona jest tu. Poniższe definicje odwołują się do tych typów. agr_attrs
to zbiór wartości atrybutów, których uzgodnienie zachodzi lub nie.
agr(pos1, pos2, agr_attrs)
wtt., gdy zachodzi silne uzgodnienie na podanym zakresie pozycjiagrpp(pos1, pos2, agr_attrs)
wtt, gdy zachodzi silne uzgodnienie między podanymi dwoma pozycjamiwagr(pos1, pos2, agr_attrs)
wtt, gdy zachodzi słabe uzgodnienie na podanym zakresie pozycji
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.
Operator debug(pos)
, debug(strset)
, debug(tset)
, debug(bool)
zwraca wartość True
niezależnie od przekazanego argumentu. Jego celem jest umożliwienie implementacji wypisania informacji diagnostycznej na temat wartości przekazanego wyrażenia (specyfikacja języka nakazuje jedynie zwrócić wartość True
, nie określa jaka informacja jest wypisywana i gdzie).
Operatory warunkowe¶
Konstrukcja warunkowa. Mamy tę samą składnię dla czterech typów. Pierwszy arg. to warunek, drugi to wartość do zwrócenia, gdy warunek spełniony, trzeci to wartość „else”. Typ całego wyrażenia można wywieść z typów zwracanych.if(pred, tset1, tset2)
if(pred, strset1, strset2)
if(pred, pred1, pred2)
if(pred, pos1, pos2)
Operator warunkowy: j.w., ale mamy tylko jedną wartość do zwrócenia; jeśli warunek nie jest spełniony, wartość zwracana zależy od typu:if(pred, tset1)
zwraca wartość wyrażenia tset1
, jeśli pred
, w pp. zwraca pusty zbiór symboliif(pred, strset1)
zwraca wartość wyrażenia strset1
, jeśli pred
, w pp. zwraca pusty zbiór napisówif(pred, pred1)
zwraca wartość wyrażenia pred1
, jeśli pred
, w pp. zwraca False
if(pred, pos1)
zwraca wartość wyrażenia pos1
, jeśli pred
, w pp. zwraca nowhere
Wyrażenia zwracające pozycje¶
Operator +
(pos + int
) zwraca pozycję po zaaplikowaniu przesunięcia (liczby całkowitej).
Wyrażenia zmieniające wartości zmiennych¶
Wyrażenia te zachowują się jak wyrażenia funkcyjne, lecz ich skutkiem ubocznym może być zmiana wartości zmiennych.
Jawne ustawienie wartości¶
setvar(varname, pos)
zawsze zwraca True, powoduje ustawienie zmiennej varname
na określoną wartość. Wyrażenie to jest zdefiniowane dla wszystkich podstawowych typów.
Iteracja za pomocą zmiennej¶
Zakres między pozycjami pos1
i pos2
to ciąg kolejnych indeksów w tablicy tokenów danego zdania (tablica taka uzyskiwany jest po zaaplikowaniu danego operatora na konkretnym zdaniu przy ustawionej konkretnej wartości pozycji bieżącej). Jeśli którakolwiek z pozycji jest nieustawiona (nowhere
), iteracja jest natychmiast przerywana i operator zwraca False
. W przeciwnym wypadku otrzymujemy ciąg kolejnych indeksów począwszy od ewaluowanej pos1
do ewaluowanej pos2
, przycięty do granic zdania.
only(pos1, pos2, posvar, pred)
wtt., gdy predykat jest spełniony na wszystkich pozycjach z zakresu lub zakres jest pusty (zakres pusty otrzymujemy również gdy pos1
> pos2
)Skutki uboczne:
- jeśli zakres jest pusty, wartość
posvar
pozostaje niezmieniona (operator wtedy zwracaTrue
) - jeśli zakres jest niepusty, a predykat jest spełniony na wszystkich pozycjach,
posvar
pozostaje ustawiona na ostatniej pozycji z zakresu - w razie niepustego zakresu i porażki,
posvar
zostaje ustawiona nanowhere
atleast(pos1, pos2, posvar, pred, n)
wtt., gdy predykat jest spełniony na co najmniej n
pozycjach z zakresuSkutki uboczne:
- w razie sukcesu
posvar
pozostaje ustawiona na n-tej pozycji, która spełnia predykat - w razie porażki,
posvar
zostaje ustawiona nanowhere
(również gdy przedział jest pusty)
llook(pos2, pos1, posvar, pred)
wtt., gdy predykat jest spełniony na którejś pozycji z zakresu oraz pos2
>= pos1
.Skutki uboczne:
- w razie porażki
posvar
jest ustawiana nanowhere
- w razie sukcesu, ustawiana jest na pierwszym od prawej tokenie spełniającym predykat
rlook(pos1, pos2, posvar, pred)
wtt., gdy predykat jest spełniony na którejś pozycji z zakresu oraz pos2
>= pos1
.Skutki uboczne:
- w razie porażki
posvar
jest ustawiana nanowhere
- w razie sukcesu, ustawiana jest na pierwszym od lewej tokenie spełniającym predykat
skip
jest ustawienie wartości posvar
na n-ty token względem pos1
pomijąjąc tokeny spełniające predykat.skip(pos1, posvar, pred, n)
wtt., gdy pos1 mieści się w granicach zdania oraz token oddalony o n on pos1 z pominięciem tokenów spełniających predykat mieści się w granicach zdania.Skutki uboczne:
- w razie porażki
posvar
jest ustawiana nanowhere
- w razie sukcesu, ustawiana jest na n-tym tokenie niespełniającym predykatu (z lewej jeśli n < 0, z prawej jeśli n > 0, na pos1 jeśli n == 0).