A REXX programozási nyelv

Utasítások, vezérlési szerkezetek

Értékadás, üres utasítás

[Értékadás] ::= [azonosító] '=' ([kifejezés] | [sztring literál] | [numerikus literál] )
Az értékadás egyszerű utasítás, értéket nem ad vissza. Többszörös értékadás nincs a nyelvben. Üres utasítás a nop. A nop utasítás nem csinál semmit. Használata a select vezérlési szerkezetnél indokolt.

Szekvencia

Több utasítás egymásután írásával kapjuk. Ha az utasításokat egy sorba írjuk, akkor ';' kell elválasztani az egyes utasításokat, különben a pontosvesszőt nem kötelező kitenni az utasítások után. Tehát a ';' szerepe az utasítások elválasztása. Az utasításokat blokkokba lehet szervezni. Ennek a szintaxisa:

[blokk] ::= 'DO' [utasítássorozat] 'END'
A DO külön utasításként viselkedik, ezért a DO után az utasításokat új sorba kell írni, vagy a DO után pontosvesszőt tenni. A DO után megadható egy szám, ekkor az utasítássorozat annyiszor fog egymásután végrehajtódni, mint a megadott szám.

Elágazás

A nyelvben van két- és többirányú elágazás is. Kétirányú elágazás Az elágazás szintaxisa:

'IF' [kifejezés] 'THEN' [utasítás] 'ELSE' [utasítás]
A szabvány nem írja elő azt, hogy az ELSE utáni rész melyik elágazó utasításhoz tartozzon. Többirányú elágazás A szintaxisa:
'SELECT' [select törzs] + [különben] 'END' [select törzs] ::= 'WHEN' [kifejezés] 'THEN' [utasítás] [különben] ::= 'OTHERWISE' [utasítások]
A [kifejezés] tetszőleges logikai kifejezés lehet. A többirányú elágazás működése a következő: ha valamelyik [select törzs]-ben szereplő kifejezés igaz, akkor a 'THEN' utáni utasítás hajtódik végre, majd az elágazás utáni utasításhoz kerül a vezérlés. Ha egyik ágnál se teljesül a feltétel, akkor a [különben]-ben megadott utasítások hajtódnak végre, majd az elágazást követő utasításhoz kerül a vezérlés.

Ciklus

A nyelv többféle ciklust is tartalmaz. A ciklusok általános szerkezete a következő:

[ciklus] ::= [ciklusfej] [utasítások] 'END' [ciklusfej]::='DO' [dorep] | 'DO' [docond]| 'DO' [dorep] [docond] | 'DO' 'FOREVER' [[docond]] [docond]::= 'WHILE ' [kifejezés] | 'UNTIL ' [kifejezés] [dorep]::= [értékadás] [[docount]] | [itkifejezés] [docount]::= [dot] [[dobf]] | [dob] [ [dotf] ] | [dof] [ [dotb] ] [dobf] ::= [dob] [[dof]] | [dof] [[dob]] [dotf] ::= [dot] [[dof]] | [dof] [[dobt]] [dotb] ::= [dot] [[dob]] | [dob] [[dot]] [dot] ::= 'TO' [kifejezés] [dob] ::= 'BY' [kifejezés] [dof] ::= 'FOR' [kifejezés]
A ciklusok működése: WHILE ha a [kifejezés] hamissá válik, a ciklus befejeződik. UNTIL ha a [kifejezés] igazzá válik, a ciklus befejeződik. [értékadás] akkor fut le, amikor a ciklushoz ér a végrehajtás. A kezdeti értékadás után a feltételek kiértékelése. Mivel blokkonkénti hatáskör a nyelvben nem ismert, így a cikluson kívül is látható a ciklusváltozó, és a ciklus lefutása után a változó értéke a cikluson belül elvégzett műveletektől függ. A ciklusvátozó változtatható a ciklus törzsében. [itkifejezés] - egész számnak kell lennie, legfeljebb ennyiszer hajtódik végre a ciklusmag. FOREVER A ciklus végtelen, ha a FOREVER után esetleg következő [docond]-ból nem következik más. Tehát:
DO FOREVER SAY 'OK' END
programrészlet végtelen ciklusban fogja a 'ok' sztringet kiírni. for [kifejezés] - a [kifejezés] egész értékű, a ciklus legfeljebb ennyiszer hajtódik végre. to [kifejezés] - a [kifejezés] egész értékű kifejezés, a ciklusváltozó végértékét adja meg. by [kifejezés] - [kifejezés] egészértékű kifejezés, a ennyivel változik a ciklusváltozó értéke a ciklus minden lefutásánál. A fentiekből következik: A nyelv két ciklusmegszakító utasítást tartalmaz:
leave [numt]
Kilép a [numt] által megadott szintű ciklusból. A [numt] egy egész érték, amely egy ciklust azonosít. Az egymásba ágyazott ciklusok sorszámmal láthatók el, amely a beágyazottság mértékét mutatja.
iterate [numt]
A [numt] jelentése megegyezik az előző pontban leírtakkal. A utasítás hatására a utasítás helyétől a [numt] által megadott ciklus végéig tartó kódrészletet az interpreter átugorja, és a ciklus fejéhez kerül a vezérlés.

Kivételkezelő utasítás

A nyelv lehetőséget ad kivételek kezelésére. A kivételkezelés a signal utasítás segítségével valósítható meg. A szintaxisa:

[signal] ::= 'SIGNAL ' [címke] | SIGNAL VALUE [kifejezés] | 'SIGNAL' ( 'OFF' | 'ON' ) ( 'ERROR' | 'SYNTAX' | 'HALT' | 'NOVALUE')
Az utasítás működése:
SIGNAL [címke] hatására a vezérlés a [címke] címkére ugrik. SIGNAL VALUE [kifejezés] a [kifejezés] kiszámításából kapott értéket, mint címkenevet használva, a vezérlés átadódik a címke által megcímzett kódrészletre. SIGNAL (ON | OFF) (ERROR | SYNTAX | HALT | NOVALUE ) Az ERROR, SYNTAX, HALT, NOVALUE kulcsszóval leírt események hatására, amennyiben a megfelelő paraméterrel a SIGNAL ON parancs előzőleg ki lett adva, a vezérlés a hasonnevű címke által megcímzett programrészletnek adódik át.

Speciális utasítások

ADDRESS utasítás Az utasítás szintaxisa:

[address]::= 'ADDRESS' [(taken_constant [kifejezés] | 'VALUE' [kifejezés] ) [ WITH [kapcsolat]]]
A taken_constant tetszőleges sztring lehet. A [kifejezés] tetszőleges kifejezés lehet. A parancs azt a külső környezetet állítja be, amelyhez majd a külső parancsokként felismert utasítások elküldetnek. A [kapcsolat] a külső környezettel kapcsolatos I/O beállítsokat tartalmazza, a szintaxisa igen összetett.

PARSE utasítás A utasítás szintaxisa ( vázlatosan )

parse ::= 'PARSE' parse_type [template_list] | 'PARSE' 'UPPER' parse_type [template_list] parse_type :: = parse_key | parse_value | parse_var parse_key ::= 'ARG' | 'PULL' | 'SOURCE' | 'LINEIN' | 'VERSION' parse_value ::= 'VALUE' [kifejezés] 'WITH' parse_var ::= VAR [azonosító]
A parancs a megadott forrásból vett karaktersorozatot változókra bontja. A parancsnak többféle szintaxisa létezik, a különböző formátumok a bemenő karaktersorozat forrását jelölik meg. A parse arg parancs az eljárásnak megadott argumentumokat választja szét.
Példa:
parse arg a.1 a.2 a.3 a.4 do i=1 to 4 say "Az" i "-edik argumetum" a.i end
Az a. tömb négy elemét inicializálhatjuk úgy, hogy a fenti programot négy egy egymástól szóközzel elválasztott argumentummal hívjuk meg. Ha kevesebb argumentumot adunk meg a programnak, akkor a nem inicializált változókat a parse parancs üresre állítja. Ha több paramétert adunk meg a programnak, akkor az utolsó változó tartalmazni fogja az összes megmaradt argumentum konkatenáltját, vagyis a parse azokat nem választja szét. Példa:
parse value time() with hour ':' min ':' sec
Ez a példa azt is illusztrálja, hogy nem csak a szóköz karakter lehet az elválasztó, itt a time függvény által visszaadott stringet a pontosvessző karakterrel választja szét a parse parancs. A time függvény az időt adja vissza, melynek formátuma óra:perc:másodperc.
A parse var parancs a "név"-el megadott változó értéke vesz részt a műveletben.
Példa:
d=date() parse var d day month year
A date() függvény a dátumot adja vissza nap hónap év formátumban.
A parse version parancs megadja a REXX interpreter verzióját.
Az adat stack
A Rexx nyelv használ egy belső adat stack-et amit közvetlenül parancsok segítségével is elérhetünk. A parse pull parancs a felhasználói inputot olvassa be amennyiben nincs a belső stack-en adat. Amennyiben van, a stack következő sorát emeli ki és azt dolgozza fel. A stack-be újsort a queue és a push parancsokkal tudunk tenni.
Példa:
"Hello!" parse pull a /* a változó értéke "Hello!" */ parse pull b /* b a következő felhasználói inputot tartalmazza */ push "67890" push "12345" parse pull c /* c változó éréke "12345" */ /*a stack egyetlen sora 67890*/
A lényeges különbség a queue és a push utasítás között, hogy azok az sorok melyeket a queue paranccsal teszünk a stackbe FIFO elérésűek lesznek, és azok melyet a push paranccsal LIFO elérésűek. Ha a stack sorait mindkét parancs használatával töltöttük fel, akkor először a LIFO elérésű sorokat tudjuk elérni majd a FIFO elérésűeket. A stack-et különböző Rexx programok ill. alprogramok közötti kommunikációra használhatjuk. A program terminálás után a stack-beli adat egyes rendszereken törlődik, másik rendszereken végrehajtódik, esetleg megőrződik. Amennyiben nem akarjuk a stack-beli adatokat később később is használni, célszerű azokat törölni(kiolvasni) a programunk terminálása előtt.

Egyéb hasznos Rexx parancsok:

A trace parancs A hibakeresés egy lehetősége a Rexx-ben a trace parancs mellyel a programunk futását tudjuk nyomon követni, változók értékét kiíratni. A trace all parancs hatására az interpreter minden programsort kiír a terminálra, mielőtt azt végrehajtaná. A trace results hatására az interpreter minden programsort és annak eredményét is kiírja a terminálra. A trace parancs használatával lehetőség van interaktív nyomkövetésre is. Az interpret parancs Az interpret parancs használatával végrehajthatunk olyan program részleteket, amelyeket a REXX program dinamikusan állít elő, és például egy változóban tárol. Az interpret kifejezés parancs hatására a kifejezés értéke kiszámítódik, majd egy REXX programsorként végrehajtódik. Példa:
parse pull var interpret var "=" 42
A fenti példában a var nevű változó értéke beállítódik negyvenkettőre.

Stringkezelés

A stringkezelésre nagyszámú beépített függvény áll rendelkezésre REXX nyelvben. Következzék most néhány stringkezelő beépített függvény leírása.
Az abrev(str1,str2,ln) függvény megvizsgálja, hogy az str1 string megegyezik-e az str2-vel balról kezdve, ln hosszúságban. Ha igen, 1-et ad vissza. Ha nem, akkor 0 az eredmény.
A center(str1,ln,tölt) függvény eredménye egy "ln" hosszúságú string lesz, melyet először feltölt a "tölt" karakterrel, majd a közepére beteszi az "str1" stringet.
A compare(str1,str2,tölt ) függvény a rövidebb string kiegészítése után összehasonlítja a két stringet, és nullát ad vissza, ha egyenlők. Egyébként pedig az első nem egyező karakter pozícióját adja vissza.
A copies(str1,n) függvény eredménye str1 lesz, n-szer egymás után másolva.
A c2d(str1,n) függvény az str1 string-et n byte-os bináris számként értelmezi, és decimális számra alakítja. Ha a legfelső bitje 1, akkor 2-es komplemensben tárolt negatív számról van szó, egyébként pozitív.
A c2x(str1) függvény az str1-et hexadecimálisan adja vissza.
A datatype(str1,típus) ha nem adjuk meg a típus -t, akkor megvizsgálja, hogy az str1 értéke milyen típusú. Ha szám, akkor visszaadja, hogy NUM. Ha nem szám, akkor "CHAR" az eredmény. Ha megadjuk a típust, akkor megvizsgálja, hogy str1 megfelel-e a megadott típusnak. Ha igen, egyet ad vissza, ha nem akkor nullát.
A delstr(str1,n,ln) függvény az str1 string-ből kitörli az n-ik karaktertol kezdodo, ln hosszúságú részt. Ha nem adunk meg ln-t, akkor a string hátralévő része törlődik.
A delword(str1,n,ln) függvény az str1 string-bol kitöröl az n-iktől kezdve ln darab szót.
A find(str1,str2) függvény az str2 string-ben lévő, esetleg több szóból álló szöveget megkeresi az str1-ben. A szavakat egymástól egy vagy több szóköz választhatja el, de a szóközök száma a keresés szempontjából közömbös. Az eredmény egy szám, amely azt adja meg, hogy str1-ben hányadik szótól kezdve található meg str2.
Az index(str1,str2,n) függvény megkeresi str2-t str1-ben, és visszaadja, hogy hányadik pozíciótól kezdve találta meg. Ha n-et magadjuk, akkor a keresés "str1" "n"-ik pozícióján kezdődik.
Az insert(str1,str2,n,ln,tölt) függvény először str1-et kiegészíti ln hosszúságúra tölt karakterekkel, majd beszúrja str2 n-ik karaktere után. Az így kapott string lesz a függvény eredménye.
A justify(str1,ln,tölt) az str1-et kiegészíti ln hosszúságban, majd a benne lévő szavakat úgy helyezi el, hogy az összes szóköz a szavak közé kerüljön egyenletesen elosztva, de közben minden szóközt tölt karakterrel helyettesít.
A lastpos(str1,str2,n) megkeresi str1-et str2-ben visszafelé, és visszaadja azt, hogy hol találta meg. Ez az érték tehát az utolsó elofordulás helye lesz. Ha n-et megadjuk, akkor nem str2 legvégétol, hanem csak az n-ik karakterétől kezd keresni, természetesen visszafelé.
A left(str1,ln,tölt) függvény az str1 baloldali ln hosszú részével tér vissza. Ha szükséges, akkor az eredményt ln hosszra tölt karakterrel egészíti ki.
A left(str1) függvény visszaadja str1 hosszát.
Az overlay(str1,str2,n,ln,tölt) függvény az str1 stringet-et ln hosszúságban (esetleg tölt-el kiegészítve) beleteszi str2 n-ik karakterétol kezdve str2-be, annak eme pozíciókon lévő karaktereit felülírva.
A pos(str1,str2,start) függvény str1-et megkeresi str2-ben, majd visszaadja azt a pozíciót, ahol megtalálta.
A reverse(str1) függvény str1-et adja vissza, fordítva. Az utolsó karakter lesz az első, az utolsó előtti a második, stb.
A right(str1,ln,tölt) függvény az str1 jobboldali ln karakterével tér vissza, szükség esetén balról tölt karakterekkel kiegészítve.
A space(str1,n,tölt) függvény az str1 string-ben a szavak között lévő szóköz karakterek eltávolítása után n darab tölt karaktert tesz be a szavak közé.
A strip(str1,opció,chr) függvény eltávolítja az str1-bol a vezető és/vagy záró chr-el megegyező karaktereket, az opciótól függően. A chr paraméter alapértelmezése szóköz.
Az opció paraméter értékei az alábbiak lehetnek: A substr(str1,n,ln,tölt) függvény az str1-ből az n-ik karaktertől kezdődően kivág egy ln hosszú karaktersorozatot, és ezt adja vissza. Ha rövidebb akkor tölt karakterekkel egészíti ki.
A verify (str1,str2,'M',n) függvény megvizsgálja, hogy str1 minden egyes karaktere megtalálható-e str2-ben. Ha minden karaktert megtalált, akkor nulla a függvény értéke. Ha olyan karakter van str1-ben, mely nem található meg str2-ben, akkor a kérdéses karakter str1-beli pozícióját adja vissza eredményként. Ha megadjuk az 'M' paramétert, akkor str1 azon karakterének az str1-en belüli pozícióját adja vissza, amelyik benne van az str2-ben. Az n paraméter az összehasonlítás kezdetét jelzi, mindkét stringben.

Label-ök

A Rexx-ben minden olyan szimbólum, vagy string, amit egy kettőspont követ, az egy label. (Jelen kontextusban a kettőspont feltételezi a pontosvesszőt, szóval a sort nem kell pontosvesszővel lezárni.) A label-ek azok a kódrészletek, amikre a CALL hívások hivatkozhatnak. Ezekre helyeződhet át a vezérlés akkor is, ha valamilyen SIGNAL keletkezik a nyelvben. Ez az egyetlen olyan kontextus a nyelveben, amikor case-sensitive-en illeszti a különböző literálokat. A duplikált label-öket nem tiltja a nyelv (sem a preprocesszor, sem a futtatókörnyezet), de a vezérlést mindig az elsőnek definiált label-re helyezi a program.