É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:
- nincs igazi hatultesztelős ciklus.
- van elöltesztelős ciklus.
- a ciklusváltozónak beállítható a kezdeti értéke, felső értéke, lépésszáma.
- a ciklusváltozónak egészértékűnek kell lennie.
- a ciklusváltozót lehet a ciklusmagon belül változtatni.
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.
- A parse external parancs a terminál input pufferből vett argumentumokkal dolgozik.
- A parse numeric az utolsó numeric parancs paramétereit adja vissza. A numeric
parancs az aritmetikai változók és műveletek pontosságának megadására szolgál.
- A parse pull parancs a program stack következo sorát emeli ki, és azzal dolgozik.
A program stack ismertetése az ezt követő fejezetben található.
- A parse source parancs megadja, hogy milyen módon indítottuk el ezt a REXX programot.
A parse value parancs a megadott "kif" kifejezés kiértékelodik és így vesz részt
a további műveletben.
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:
- L - vezető karaktereket távolítja el
- T - záró karaktereket távolítja el
- B - a vezető és a záró karaktereket is eltávolítja, ez az alapértelmezés szerinti opció.
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.