You're first I run into saying that who isn't a mainframe programmer. It was an interesting language in summaries I read but I never really dug into it. What was good about Rexx for writing parsers?
I've worked for a big financial corp. I was in one of their mainframe teams for a year or so [1]. There's still a lot I don't know but I sure know Rexx is the most fun you can have on a mainframe. It's kind of like the polar opposite of JCL, or getting stuck on a TSO command line.
The first reason why Rexx is great for parsing is the fact that variables equal themselves. There's no "string" data type. If you type "myvar" then that's the name and the contents of your variable (unless you assign it another value):
DO INDEX = 1 TO 10 BY 2
SAY HELLO
END
/* Outputs:
HELLO
HELLO
HELLO
HELLO
HELLO
***
*/
Skipping the assignment reduces clutter and makes it very easy to see what you're dealing with. Unless you mess it up later, obviously.
Second, for parsing, Rexx has a keyword instruction called ...(drumroll)... PARSE that essentially implements pattern-matching, of some sort, probably as a regular automaton like regexes but without the regex syntax which is actually really nice. Instead, you define a pattern as a string with literals and variables and the special symbol '.' (a period) to indicate any token, (that's similar to the regex '.' but it matches between spaces).
Here's an example from my notes from that time (spaces delimit literals and variables) [2]:
/* Fun with patterns at the REXXREPL*/
BANDS = 'SLAYER, BATHORY, MOTORHEAD, VENOM'
PARSE VAR BANDS ABAND ', ' BEST ', ' REST
SAY ABAND
SLAYER
SAY BEST
BATHORY
SAY REST
MOTORHEAD, VENOM
PARSE VAR BANDS . ', ' BEST ', ' REST /* Skipped Slayer */
SAY BEST
BATHORY
SAY REST
MOTORHEAD, VENOM
You can also use numbers to indicate positions in a string (absolute, in the example below, but there's also relative ones):
DIGITS = '11001011'
PARSE VAR DIGITS FIRSTTWO 3 NEXTFOUR 7 LAST
SAY FIRSTTWO
11
SAY NEXTFOUR
0010
SAY LAST
11
On top of that, Rexx has "compound variables", a data structure that (to me) resembles a tree and lets you compose hierarchical structures. For instance, here's part of a program that reads in JCL files (formatted to a standard format with another Rexx program so that everything of the same kind is in the same column) and stores their DD, dataset, step and program names in such a structure:
/*PARSE JOBNAME OFF FIRST LINE IN JCL FILE*/
PARSE VAR CA.1 '//' JOBNAME .
/*PARSE OTHER NAMES INTO A STEM CALLED 'MATCHES.'
EACH TYPE OF NAME GOES INTO ITS OWN TAIL
TAILS FOR DDNAMES AND DATASET NAMES ARE INDEXED IN TANDEM
SAME FOR TAILS WITH STEP AND PROGRAM NAMES
IN OTHER WORDS, MATCHES. IS STRUCTURED AS FOLLOWS:
TAIL INDEX CONTENTS
---------- --------
MATCHES.DDNAMES.N N'TH DD NAME FOUND IN JCL FILE
MATCHES.DSNAMES.N DATASET NAME FOR N'TH DD NAME
MATCHES.STEPNAMES.M N'TH STEP NAME
MATCHES.PROGNAMES.M PROGRAM NAME FOR N'TH STEP NAME
SO, TO GET THE DATASET NAME THAT CORRESPONDS
TO THE 5TH DD AND DATASET NAME
FOUND IN THE JCL FILE, YOU LOOK INTO:
MATCHES.DDNAMES.5
MATCHES.DSNAMES.5
*/
DO INDEX = 2 TO CA.0 BY 1
PARSE VAR CA.INDEX '//' DDNAME . 'DSN=' DSNAME ','
/* IF DD NAME IS EMPTY, DON'T ASSUME DDNAME='DD'*/
IF DDNAME = 'DD' THEN
DDNAME = ''
PARSE VAR CA.INDEX '//' STEPNAME . 'EXEC' PROGNAME ','
IF DSNAME ¬= ''
THEN
MATCHES.DDNAMES.INDEX = DDNAME
MATCHES.DSNAMES.INDEX = DSNAME
IF PROGNAME ¬= ''
THEN
MATCHES.STEPNAMES.INDEX = STEPNAME
MATCHES.PROGNAMES.INDEX = PROGNAME
END
(The above will probably make more sense if you've seen a jcl script before).
The point is that all of that is very hard to do with COBOL, and, I believe, impossible with JCL [3]. In Rexx on the other hand, it's a doozy.
I also note that all of the above is nice to have in any language and that not very many of the languages popular outside of mainframes let you parse strings that easily, without explicitly calling a regex library or such.
_______________
[1] I raised hell until they put me in one of those teams. I could get plenty of experience with Spring and Hibernate outside of that corp. Since I was there, I figured I might as well learn something I couldn't learn anywhere else as easily. Still, people looked to me as if I was mad. "You want to be on a mainframe team? Why?".
Dude. Big computers. Millions of users. What the hell?
[2] Note that the "REXXREPL" in my comment is a Rexx program running on TSO (the Z/OS command line, ish):
/* REXX INTERPRET */
REPLPROMPT = "SAY '>>'"
INTERPRET REPLPROMPT
DO FOREVER
PULL USERINPUT
IF USERINPUT = "END" THEN EXIT 0
INTERPRET USERINPUT ; END
The INTERPRET instruction is another funky bit of Rexx that's real cool to have on a mainframe.
[3] Though I'm sure there's someone, somewhere still on this planet who would laugh in my face for saying that. But probably no more than four or five people.
Appreciate the examples. Yeah, that looks almost like a 4GL compared to regular mainframe programming. A lot more powerful.
"Since I was there, I figured I might as well learn something I couldn't learn anywhere else as easily. Still, people looked to me as if I was mad. "You want to be on a mainframe team? Why?". Dude. Big computers. Millions of users. What the hell?"
I like your style. Same excuse I had for trying (but failing sigh) to get onto a team with SGI NUMA machines. They were confused about why I'd want to do tedious work tweaking numerical applications. For 256 CPU's and 3TB of RAM in one machine? Obviously...?
Note: I imagined it had time in between jobs and a quota system not designed with people like me in mind, too. ;)