In my post describing how Fleet Forth handles the text stream I did not show the source for Fleet Forth's WORD . I thought it might be a distraction. Here is the source for Fleet Forth's WORD .
Code: Select all
2VARIABLE HISTORY
: WORD ( C -- HERE )
'STREAM \ Return address and count of remaining text stream.
BLK 2@ HISTORY 2! \ Save the contents of BLK and >IN to HISTORY.
DUP >IN +! \ Use count from 'STREAM to push >IN past text stream.
2PICK SKIP ( delimiter address count )
ROT 2PICK -ROT SCAN ( address address2 count2 )
1- 0 MAX NEGATE >IN +! \ Use count from SCAN to pull >IN to correct offset.
OVER - >HERE ;
'STREAM returns the address and length of the remaining text stream.
After the history is saved for use by WHERE and THRU , >IN is set to point just past the text stream.
SKIP returns the address in the text stream of the sought after text and the length of the remaining text stream.
A copy of this address is saved under the address length and delimiter needed by SCAN .
SCAN returns the address of the delimiter after the sought after text and the length of the remaining text stream. One is subtracted from the length. The maximum of this value and zero is subtracted from >IN to put the offset past the delimiter but no further than the end of the text stream.
All that remains are the addresses of the start of the sought text and the address of the delimiter after the sought text. These are converted to the address and count.
Before >HERE is executed, the address of the string and count are on the stack. The address in the text stream, just like Ansi Forth's PARSE-WORD .
>HERE stores this string at HERE as a counted string with a trailing blank. >HERE is a code word for speed.
I could have defined WORD like this:
Code: Select all
2VARIABLE HISTORY
: PARSE-WORD ( C -- ADR CNT )
'STREAM \ Return address and count of remaining text stream.
BLK 2@ HISTORY 2! \ Save the contents of BLK and >IN to HISTORY.
DUP >IN +! \ Use count from 'STREAM to push >IN past text stream.
2PICK SKIP ( delimiter address count )
ROT 2PICK -ROT SCAN ( address address2 count2 )
1- 0 MAX NEGATE >IN +! \ Use count from SCAN to pull >IN to correct offset.
OVER - ;
: WORD ( C -- HERE )
PARSE-WORD >HERE ;
However, I saw no need for PARSE-WORD . Fleet Forth's find primitives require the address of a counted string rather than the address of a string and a count and CREATE needs a counted string at HERE .
Fleet Forth's 'TEXT returns the address of the string in the text stream and the length. It is like Ansi Forth's PARSE with one difference. If the delimiter is not found in the text stream 'TEXT aborts with an error message.
Code: Select all
: 'TEXT ( C -- ADR CNT )
DUP>R LIT [ HERE >A 0 , ] C! \ Store delimiter in ABORT" string.
'STREAM 2DUP R> ( ADR LEN ADR LEN C )
SCAN 0= ( ADR LEN ADR2 FLAG )
[ HERE 3 + A> ! ] \ If text stream exhausted after SCAN
ABORT" MISSING" \ then the delimiter was not found
NIP OVER - ( ADR CNT )
DUP 1+ >IN +! ;
'STREAM returns the address and length of the remaining text stream. A copy of the delimiter is stored in the inline string used by ABORT" . After SCAN executes, the address and length 'STREAM placed on the data stack is still there as well as the address of the first occurrence of the delimiter and the length of the text stream after this point. If this length is zero, the delimiter was not found so abort with an error message.
The length returned by 'STREAM is no longer needed so it is NIPped off the data stack and the two addresses are used to calculate the length of the string returned by 'TEXT . A copy of this length plus one is added to >IN .
[Edit: Corrected an error.]