features of REXX. - IBM Mainframe

Learning a new language can be intimidating, whether it is a natural language or a computer language. For computer languages, the actual difficulty of the learning process depends a great deal on the nature of the language itself. Because ease of use was a primary consideration in the design of REXX, learning it should prove to be as easy as learning almost any other computer language, and probably easier.

Many readers will already know one or more computer languages. Since REXX uses concepts, which are widely used in other popular, contemporary languages,' it should be especially easy to learn. That is, language constructs in REXX such as literals, variables, arithmetic expressions, conditional statements, subroutines, and so forth are very similar to their counterparts in other languages like C, Basic, or Pascal.

There are, however, some constructs in REXX that are both powerful and not present in most common languages. These include such things as compound variables and the PARSE instruction. Experienced programmers can use much of their present programming knowledge and will want to focus on the distinctive features of REXX.

On the other hand, for beginning programmers there are many concepts that have to be learned regardless of which language one starts with. Since REXX is intended to be used as a system command language (among other things), it will in fact be the first serious programming language that many people learn. While it is beyond the scope of the present text to teach programming, beginners will find that much of the REXX language is simple, intuitive, and a natural step from using operating system batch files and application macros.

A complete REXX program may consist of as little as two simple lines, for instance:

features of REXX.This program displays the words HELLO WORLD on the screen. Here, SAY is a REXX reserved word that begins an output instruction. "HELLO WORLD" is a literal string. A single blank separates the verb from the literal. SAY is not always a reserved word in REXX. It is reserved and has a special meaning only when it is the first word of a clause. SAY could be used elsewhere in the program, even in the same clause, without any conflict.

There are two fundamental program units in REXX: the statement and the clause. There are three types of statements: REXX instructions which begin with keywords such as SAY, assignments of some value to a variable, and commands to external environments. A clause is a slightly smaller unit of executable code. Most statements, including assignments and commands, are single clauses all by themselves. Most keyword instructions are also single clauses, but a few (such as IF and DO) are more complex and consist of multiple clauses. Also, for technical reasons; a label is considered to be a clause which is neither a statement by itself nor part of a statement. We will go much further into these details, but you can think of a REXX program as a sequence of statements.

In REXX terminology, the example above consists of a single statement, which is also a single clause. Although clauses and lines are not the same thing, in general, REXX programs tend to be written as if they were. That is, the usual practice is to put one clause on a line. Multiple clauses can be written on a single line by ending each clause with a semicolon, but this usually decreases the readability of the program. It is possible to write REXX programs consisting of thousands of clauses with each one on a separate line and without using a single semicolon. So, the end of a line normally means the end of a clause as well.

However, most REXX implementations place a limit on the length of a single line. Most editors or word processors used to write programs do, too. And for readability (always a very important concern with REXX), it is desirable to keep lines shorter than the width of the screen or editing window. The length of a clause in most REXX implementations is also limited, but it is usually longer than 80 characters, which is the width of most screens. Therefore, some mechanism is necessary for continuing a single clause onto additional lines. This is done by ending each line to be continued with a comma as we have seen in the previous chapter:

SAY "TO BE OR NOT TO BE:", "THAT IS THE QUESTION."

This example will display the two quoted phrases on the same line of the screen, because it is really just one clause as far as REXX is concerned. It is equivalent to:

SAY "TO BE OR NOT TO BE: THAT IS THE QUESTION."

Blanks play a very special role in REXX—several roles, actually. One or more blanks separate individual tokens in a REXX clause, just as in the preceding example where a blank separated the verb and the literal. Except within literals, it is irrelevant whether one or more than one blank is used to delimit tokens. Therefore, it is common to use blanks to help format a program for greater readability. Above, for instance, they were used to line up the quoted phrases.

One of the design goals of REXX was to make a language in which it is especially easy to work with character strings, and to do so in as natural a way as possible. One of the most frequent operations on character strings is concatenation, in which two strings are joined together. This is expressed in REXX simply by writing the two strings together with one or more blanks in between. So, a third way to write the example

we have been using is

SAY "TO BE OR NOT TO BE:" "THAT IS THE QUESTION."

Here, there are three tokens in the clause: the verb and two literal strings. When this statement is executed, the two literals are concatenated, and a single blank is inserted between them. Only one blank is inserted in the concatenation regardless of how many blanks separate the literals.

A REXX clause can contain other types of tokens. The verb SAY is a special case of a symbol token. Such a token begins with an alphabetic character and extends to the next delimiter. Delimiters are either blanks or special characters like ":", ";", "*", "+" and '/". Such delimiter characters may be tokens all by themselves (as are each of the ones just mentioned), or they may be the start of longer operator tokens such as "=" (not equal). Operator tokens include the standard arithmetic operators ("+", "-", "*", "/", "**") string operators such as "| |" (concatenation) and '>" (comparison), and logical operators such as "&" (logical and) and "" (negation).

Numbers are the other major sort of token. A number is delimited like a symbol, but it consists only of numerals, ".", ",", "+',"-" and "e". Numbers can be integers, decimals, or in exponential notation, and may be signed. The following are all valid numbers in REXX:

  • 666
  • 2.718281828
  • -32768
  • 6.63E-27

We now have enough terminology to examine a more interesting REXX program. The task is to convert temperature expressed as Fahrenheit to Centigrade. The program should ask the user to enter a number representing the Fahrenheit temperature and display the corresponding Centigrade value. It should terminate when the user enters nothing but blanks. Here is the program:

features of REXX.

Let us look at what is new here, line by line. The first two lines are comments. As in C and PL/I, comments in REXX begin with '/* and end with */• Comments may extend over as many lines as necessary without the need to do anything special to indicate continuation. Beginning every program with a comment containing the word REXX is required in order to distinguish the file from others that may use a different language.

The third line (DO FOREVER) contains the REXX reserved word DO as its first token. This begins a loop, which extends to the matching END instruction on the last line. Any other REXX statements can occur between the DO and the END. This includes other DO statements, so that loops can be nested up to an implementation-defined limit, each beginning with DO and terminated with END. A DO statement may have a number of optional modifiers that specify a control variable to be incremented on each iteration, or define conditions on when the loop should be ended. In this case, the keyword FOREVER means that the DO statement itself has no specified terminating condition. Other instructions within the body of the loop can cause it to terminate. In this example, that is the function of the EX IT instruction on the seventh line.

The fourth line is a SAY instruction. In this case, the literal string has been delimited with single quotation marks (') instead of double ones ("). This is done as a convenience in case quotation marks need to be part of the literal, as in

"JUMP!" HE SAID.'

That is, all literal strings are terminated with the sort of quotation mark with which they began. An exception to this is made if the quotation character is doubled. Within a literal that begins with the same sort of quotation mark, the doubled one is treated as if it were a single one that is part of the literal, so that

" " "JUMP!"" HE SAID."

is exactly the same literal. The next line, PARSE PULL FAHRENHEIT, reads user input. It is the most common input instruction in REXX, corresponding to the output SAY instruction. PARSE PULL causes a read to the keyboard, which is terminated when carriage return (Enter) is pressed. Everything typed up to (but not including) the carriage return is assigned to a REXX variable, FAHRENHEIT in this case.

There is actually a shorter input instruction, PULL. This does input just like PARSE PULL, but has the additional side effect of converting the input to uppercase. (PULL is shorthand for PARSE UPPER PULL.) Sometimes this is useful; more often it is annoying. Here it does not matter, since the input should be a number.

A REXX variable like FAHRENHEIT is any symbol beginning with an alphabetic character, except for a reserved word occurring at the start of a clause. (In certain kinds of statements, such as DO, there may be reserved words after the first token.) Variable names may be very long—up to 250 characters in most implementations of REXX.

sitive to alphabetic case. So symbols can be written in either upper or lower case, or any mixture, and no distinction is made. The convention in this book will be to use lowercase in most examples and uppercase for REXX reserved words mentioned outside of an example (for emphasis). The most obvious instance in which case matters is in character string literals. Internally, REXX converts the whole program (except for literals and comments) to uppercase. The next two lines of the example,

IF FAHRENHEIT = " THEN EXIT

begin with an IF instruction that performs a test and executes other instructions according to the results. Technically, REXX considers this statement to consist of several clauses. The first begins with IF and concludes with an expression that must evaluate to 1 or 0. 1 represents true, and 0 represents false. In the present case, the expression uses the "=" operator to compare the value of the variable FAHRENHEIT to the literal string " (null or empty string). One of the convenient characteristics of the "=" (equality) operator when comparing strings is that leading and trailing blanks are ignored.

This behavior of ignoring blanks in circumstances where they are not meaningful is common throughout REXX; it is one of the ways in which REXX tries to be helpful. In the present instance it is useful because the user is expected to type either a number or nothing. Several blanks are taken as equivalent to nothing; it is considered irrelevant whether any blanks are entered before or after the number. Blanks are in fact stored internally. The "=" operator just happens to ignore them. Blanks in the middle of a string are not ignored. If it is important to recognize leading or trailing blanks, another operator ("= =", exact equality) can be used.

THEN is a reserved word in an IF clause. In fact, it is considered to be a separate clause all by itself. Its purpose is to mark the end of the conditional expression. The statement immediately following THEN is executed if (and only if) the expression after IF evaluates to 1. Here, that is the case, provided that the expressions on either side of "=" are the same except for leading and trailing blanks. (Alphabetic case is significant to the '=" operator.) The expression here is evaluated by taking the value of the FAHRENHEIT variable and comparing it to a null string. If this value contains any nonblank characters, the value of the whole expression is 0, and the statement after THEN would not be executed.

In the present example, the clause after THEN is another REXX reserved word, EXIT. This instruction terminates not only the DO loop but the entire REXX program, and allows control to return to the operating system. The statement after THEN could be any legal REXX statement, including another IF statement. In case several statements need to be executed when the condition is true (i.e., 1), they can be enclosed between a DO. . . END pair.

The end of the IF statement is recognized because the line following EXIT begins with a token other than the reserved word ELSE, which would be used if there were a statement to be executed in case the conditional expression has the value 0. Since there is no such statement in this example, the next statement will always be executed. The next statement here

CENTIGRADE = 5 * (FAHRENHEIT - 32) / 9

is an assignment, recognized by the presence of the assignment operator as the second token in the clause. Here, the variable named CENTIGRADE is given the value of the expression on the right-hand side. In this case the expression is purely an algebraic one. Although that value of the variable FAHRENHEIT was stored as a character string, and could be used as such if appropriate, here it is automatically treated as a number. This illustrates one of the key characteristics of REXX: as little distinction as possible is maintained between different data types until they are actually used. REXX neither requires nor even possesses data type declarations. All data is stored internally as a character string (at least in principle). Only when values are actually used are any conversions made—if necessary and if possible. Of course, only certain character strings represent numbers, and conversion may not be possible. In our example, the user may have entered a nonnumeric value such as OK, which would cause an error when the expression is evaluated. Although the example has no error checking, REXX has various ways to do checking, and a serious program certainly should have appropriate checks.

Since the algebraic expression involves division, the result will probably not be integral. REXX takes care of the decimal part automatically, even though no declarations were used to distinguish between integral, fixed point, or floating point numbers. The default precision that REXX supports is implementation dependent, but frequently it is nine digits (apart from the exponent, if any). If more or less precision is required for a particular purpose, it can be requested. The maximum precision that REXX supports depends on the implementation, but can be very large, even thousands of digits.

The last interesting line in the example is say TEMPERATURE is 1 CENTIGRADE 'DEGREES C.' The part of the clause after SAY is actually an expression consisting of the concatenation of two literal strings with a variable value. The value of CENTIGRADE is a computed number, but, because it occurs in a character string expression, it is automatically converted to the printable character representation of the number. Concatenation of strings is implicit in the expression; no explicit operator is required. The string concatenation automatically includes a blank between each operand as a convenience. The result displayed by this instruction might be, for instance,

TEMPERATURE IS 37.7777778 DEGREES C.

This would be the result of converting 100 degrees F. The result has been expressed with exactly nine digits of accuracy and has even been rounded up appropriately. No complicated formatting directions are required to produce this output, so such common forms of output are simple and natural to write. However, there are ways to display the answer with less precision if desired.

Concatenation works the way it does in order that the form of the expression in the program resembles the final output as closely as possible (i.e., with blanks inserted). In case concatenation without intervening blank is required, an explicit operator (" | |") can be used. Thus,

SAY 'TEMPERATURE IS '||CENTIGRADE||' DEGREES C.'

would produce the same results. Notice that the blanks have simply been moved inside the literal strings. In many cases (and this is one of them), the explicit operator can be dispensed with, so that

SAY "TEMPERATURE IS 'CENTIGRADE' DEGREES C.'

also produces the same results. REXX parsing rules still allow this expression to be resolved into three tokens (literal, symbol, literal) with an implied concatenation operation between tokens. But because there is no blank between the tokens, none is added by the concatenation operator. Although the detailed rules of how REXX handles such expressions are somewhat complicated to fully enumerate, the net result is intuitively just what it should be, with a minimum of required symbols.


All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

IBM Mainframe Topics