I my previous post, I said that I had written a little app in COBOL, and was interested in re-writing it in Forth. I am using gforth, which is an ANS Forth.
The problem I am first trying to tackle is converting numeric text into numbers. So, given s” 1963″, I should be able to put the number 1963 on the stack. Here is my attempt so far:
: 'space 32 ; : space0 dup 'space = if drop '0 then ; : >digit space0 '0 - ; create str : str++ str @ 1+ str ! ; : sd str @ c@ >digit + str++ ; : sd10 sd 10 * ; : i9999 0 sd10 sd10 sd10 sd ; : set-str drop str ! ;
I have the variable str to point to the current position in text. str++ moves that pointer along. space0 converts spaces to ASCII ‘0, which is used by >digit to convert ASCII characters to numbers. It assumes that each ASCII character is a digit. I do not check that.
So, to convert text to an integer, you take an ASCII characters, convert then to numbers, and add it to the accumulated valued multiplied by 10.
Upon reflection, the above code could probably be better rewritten as
: sd 10 * sd ;
meaning that i9999 can be simplified to
: i9999 0 sd10 sd10 sd10 sd10 ;
The choice of the word i9999 might seem a bit puzzling at first, but it is meant to look a little a COBOL PIC statement. Maybe a word like PIC-9999 might have been better. Or perhaps just 9(4). The beauty of Forth is that you can actually define that to be a valid word, and it looks exactly like a COBOL PIC declarator.
It is now possible to parse a string like “1963” and produce the correct answer:
s" 1963" set-str i9999 . cr
Now that we have that in place, we can parse decimals as integer representations relatively easily:
: i9999.99 i9999 10 * str++ sd10 sd ;
Again, out word looks like a PIC statement.
So when we type
s" 1963.45" set-str i9999.99 . cr
we obtain the output 196345
It seems that Forth programming has an interesting property: you start in a deep hole, but you gain momentum quickly as you near the surface. I also note that one can perhaps be more generalised than in COBOL. For example, I don’t think there’s a neat way for COBOL to cope with input that has explicit decimal points in them. The way I solved the problem was to have separate integral and fractional variables, and meld them together using a computation. Hardly ideal! In Forth, I can just type str++ in my code to skip over where the decimal point is.
It’s interesting, and I’m going to take my experimentation with Forth further. There’s work involved that could be taken for granted in COBOL, but I guess that once you have everything in place, you can re-use it for other projects.
I suspect that a lot of people are put of Forth because you have to start from the atomic level. As the saying goes: you can do anything you like with Forth, but you have to do it yourself.