A Snobol programozási nyelv

Vezérlés és alprogramok

Success és Failure

A Success és a Failure jelzések, amelyek nem sorolhatók az adattípusok közé. Egy utasítás (statement) végrehajtása alatt jelennek meg. Például az INPUT és OUTPUT változók segítségével file-ból/ba is tudunk olvasni/írni. File vége jel olvasása esetén az INPUT változó nem kap értéket, hanem failure lesz az eredmény.

Egy SNOBOL program utasítások sorozatából áll, a végrehajtás során soronként megy végig az utasításokon.
Az utasítások alakja:

címke törzs :GOTO

A címke - nem meglepő módon - azt a helyet mutatja meg, hogy a program végrehajtása hova ugorjon a jelen utasítás befejezte után. Az S illetve az F azt jelzi, hogy success vagy failure jelzés esetén kell a címkére ugrani (ellenkező esetben jön a következő sor, mint rendesen), ha nincs S illetve F, akkor feltétel nélkül ugrik. Lényeges megjegyezni, hogy ezekkel lehet ciklust, elágazást megvalósítani.

Egy egyszerű program:

N = 0 COPY OUTPUT = INPUT :F(DONE) N = N + 1 :(COPY) DONE OUTPUT = 'THERE WERE ' N ' LINES' END

Az 1. sor az N értékét 0-ra állítja.
A 2. sorban, ha van helyes input érték (nem nyomtunk 'CTRL+Z'-t vagy még nem vagyunk a bemeneti fájl végén), akkor azt visszhangozza a képernyőre vagy fájlba írja, és mivel volt helyes input (success, és nem failure), ezért a következő sorra ugrik a végrehajtás.
A 3. sorban N értéke 1-gyel nő, és irány a COPY címkés sor.
Ha nincs helyes input érték, akkor a végrehajtás a 4. sorra ugrik, ahol az OUTPUT változó megkapja az N értékét.
Ennek a programnak a 2. és 3. sora így együtt hasonlít az elöltesztelő (while) ciklusra.

Függvények

Egy függvény eredményének két része van:

FUGGVENY_NEVE(ARG1, ARG2, ..., ARGn)

Ha nem adunk meg megfelelő számú argumentumot, akkor a fordító a hiányzó argumentumokat null stringgel helyettesíti és így hívja meg a függvényt.

Kétféle függvény van:

Természetesen mi is definiálhatunk új függvényeket, mint ezt az operátoroknál is megtehettük.

Predikátumfüggvények

Néhány egyszerű programrészlet:

N = 3 EQ(N, 3) * Success IDENT(3, "3") * Failure -- integer és string INTEGER('47') * Success LGT('ABC', 'ABD') * Failure N = LT(N,10) N + 1 :S(LOOP) * ha 10-nél kisebb N értéke, akkor N 1-gyel növekszik, * LT(N,10) ekkor a null string, és ezt konkatenáljuk N + 1-hez

Egyéb függvények

Néhány egyszerű programrészlet:

OUTPUT = 'Az aktualis datum és ido: ' DATE() * Az aktualis datum és ido: 02-07-06 01:05:08.93 OUTPUT = DUPL('ABC', 5) * ABCABCABCABCABC OUTPUT = TRIM('TRAILING BLANKS ') 'GONE' * TRAILING BLANKSGONE OUTPUT = REPLACE('spoon','so','SO') * SpOOn -- az S2-ben szereplő karaktereket cseréli ki S3 alapján

Megjegyzés: a SNOBOL4+ már számos új beépített függvénnyel rendelkezik. link

Függvény definiálás

A beépített DEFINE függvénnyel tudunk definiálni egy új függvényt. Hívjuk az új függvényünket SHIFT-nek, ami egy string karaktereit rotálja. A függvényben megadhatjuk, hogy a string elejéről mennyit tegyen a végére. Például, a SHIFT('ENGRAVING',3) visszatér a 'RAVINGENG' stringgel. A függvényünknek két formális paramétere lesz: az S (string) és az N (karakterek száma). A függvény definíció tehát így néz ki:

DEFINE('SHIFT(S,N)')

Más nyelvekkel ellentétben a SNOBOL4-ben a függvény definíciók nem fordítási, hanem futási időben értékelődnek ki.
Már deklaráltuk a függvény nevét és a formális paramétereit, de még nem implementáltuk, meg kell írni a függvény törzsét is. Nagyon egyszerű szabályt ad erre a SNOBOL4, amikor a függvény előkerül egy utasításban, akkor a SHIFT nevű címkére ugrik a vezérlés. Persze a vezérlést majd vissza kell adni a hívónak, erre szolgál a RETURN címke.
A függvény törzse ezek után:

SHIFT S LEN(N) . FRONT REM . REST SHIFT = REST FRONT :(RETURN)

Az 1. utasítás az S stringet két részre osztja, az első N hosszú stringet a FRONT nevű változóba teszi, míg a maradékot a REST-be.
A 2. utasítás a REST és a FRONT-ot összekonkatenálja, és a függvény visszatér ezzel az értékkel.
Az utasítás GOTO része alapján visszatér a hívóhoz a vezérlés.

Mi van akkor, ha pl. N-nek az S string hosszánál nagyobb értéket adunk? Azzal bíza bajban leszünk, de erre is van kibúvó a SNOBOL-ban. Az FRETURN címke alapján a függvény visszatér failure jelzéssel a hívóhoz:

SHIFT S LEN(N) . FRONT REM . REST :F(FRETURN) SHIFT = REST FRONT :(RETURN)

Függvény és operátor szinonimák

Szinonimákat az OBSYN függvénnyel lehet megadni, melynek 3 argumentuma van:

OPSYN(new name, old name, i)

A 'new name' definiálja az 'old name' egy szinonimáját. A 3. argumentum értéke lehet 0, 1, vagy 2, attól függően, hogy függvénynek, unáris operátornak, vagy bináris operátornak szeretnénk szinonimát definiálni.

Néhány egyszerű példa:

* függvény szinonima OPSYN('LENGTH', 'SIZE', 0) OUTPUT = LENGTH('RABBIT') * 6 * operátor szinonima OUTPUT = 1 # 1 * Execution error #5, Undefined function or operation OPSYN('#', 'DIFFER', 2) OUTPUT = 1 # 2 * Failure -- nincs DIFFER operátor a SNOBOL-ban OPSYN('PLUS', '+', 2) OUTPUT = PLUS(4, 5) * 9

Fájl és egységszám

File és "egység szám" összekapcsolása:

Az Input függvény használata

INPUT('variable',unit,length,'filename')

Paraméterek:

A függvény visszatérési értéke:

Néhány egyszerű programrészlet:

INPUT('READLINE', 1, , 'TEXT.IN') :S(OK) OUTPUT = 'Could not find file' :(END) OK . . . * TEXT.IN file-t megnyitja olvasásra az 1-es egységszámmal * parancssorban: /1=TEXT.IN INPUT('READLINE', 1) :S(OK) OUTPUT = 'Could not find file' :(END) OK . . . * ugyanaz, mint az előző LINE = READLINE :F(END.OF.FILE)

File vége észlelésénél failure jelet kap (a művelet sikertelen). Minden file-végénél megáll a beolvasással. Ha egy sor hosszabb a megadott hossznál (a fenti length érték), akkor a sor végét levágja. Az end-of-file karaktert nem veszi bele a stringbe.

Ha a sor rövidebb a megadottnál, akkor szóközökkel tölti fel a sor végét a megadott hosszig. Ez néhol zavaró lehet, ezért van szükség egy szóközlevágó függvényre (TRIM), amely a string végén levő szóközöket eltávolítja:

LINE = TRIM (READLINE)

Az Output függvény használata

OUTPUT('variable',unit,length,'filename')

A függvény paraméterei az Input függvényével megegyeznek.
A függvény visszatérési értéke:

Ha a sor, amit ki akarunk írni, hosszabb, mint a length értéke, akkor több sorba tördeli. Minden sor végére CR LF-et rak (sor vége).

Az I/O alapértelmezett értékeket meg lehet változtatni a parancssorban: pl. I=f1 /O=f2. Így az Input változóhoz f1-et, az Outputhoz f2 file-t rendeli.

Egy egyszerű program file-ok használatára:

* hossz.sno tartalma LOOP S = TRIM(INPUT) :F(END) OUTPUT = SIZE(S) ' ' S :(LOOP) END

A program meghívása:

parancssor> vsnobol4 hossz /i=text /o=text

A program a text.in input file minden sorának hosszát és a megfelelő sorát egymás mellé írva soronként kiírja a text.out nevű fájlba.
A program 1. sora az aktuális bemeneti sor végén levő szóközöket levágja.
A 2. sor egy egyszerű konkatenáció. Addig folyik a beolvasás, amíg a file-nak nincs vége.

Kulcsszavak

Az Input/Output megengedte, hogy a programunk kommunikáljon a külvilággal. De jó lenne, ha programunk magával a SNOBOL rendszerrel is tudna kommunikálni. A kulcsszavak által magunk tudjuk módosítani a SNOBOL viselkedését, és információkat szerezhetünk a rendszerről. A kulcsszavak '&amap;' jellel kezdődnek, melyet egy alfabetikus név követ. Az utasításokban hasonlóképpen tudjuk használni őket, mint a változókat.

INCLUDE utasítás

A SNOBOL4+ tartalmazza az '-INCLUDE' vezérlő utasítást, ami lehetővé teszi, hogy a program file-ba belevegyük egy másik file kódját. Például nézzük a következő programot:

* main.sno OUTPUT = 'Here is the first line,' -INCLUDE "subprog.sno" OUTPUT = 'and here is the third line.' END * subprog.sno OUTPUT = 'this is in the subprogram, ' * a main.sno ekvivalens a következőkkel OUTPUT = 'Here is the first line,' OUTPUT = 'this is in the subprogram,' OUTPUT = 'and here is the third line.' END