stringstack
processessing strings the forth way: on a string stack
\ Stingstack uh 2015-10-02 here : have ( <spaces>ccc<spaces> -- flag ) BL WORD FIND NIP ; have under 0= [IF] : under ( n0 n1 -- n1 n0 n1 ) SWAP OVER ; [THEN] have CELL- 0= [IF] : cell- ( addr1 -- addr2 ) 1 CELLS - ; [THEN] : lplace ( a-addr len a-addr' -- ) \ Put the string given by C-ADDR LEN as long counted string at \ address C-ADDR' ( 2DUP >R >R CELL+ SWAP CHARS MOVE R> R> ! ; ) OVER >R ROT OVER CELL+ R> CHARS MOVE ! ; : length ( a-addr1 -- a-addr2 u ) DUP CELL+ SWAP @ ; : (" \ ( ccc<)> -- ) \ for string stack comments POSTPONE ( ; IMMEDIATE VARIABLE "stack : "ptr ( -- addr ) "stack @ ; : "top ( -- addr ) "ptr @ ; : "allot ( len -- ) HERE SWAP ALLOT HERE "stack ! HERE , , ; BASE @ DECIMAL 1000 CHARS "allot BASE ! : "clear ( -- ) "ptr DUP ! ; : "skip ( addr0 -- addr1 ) length CHARS + ; : ?overflow ( addr -- addr ) DUP "ptr CELL+ @ U< ABORT" overflow" ; : "push ( addr len -- ) (" -- s ) "top OVER - CELL- ?overflow DUP "ptr ! lplace ; : ?empty ( addr -- addr ) DUP "ptr = ABORT" empty" ; : "th ( +n -- addr ) (" s -- s ) "top BEGIN ?empty SWAP ?DUP WHILE 1- SWAP "skip REPEAT ; : "count ( -- addr len ) (" s -- s ) 0 "th length ; : "length ( -- len ) 0 "th @ ; : "@ ( addr -- ) (" -- s ) length "push ; : "drop ( -- ) (" s -- ) "count + "ptr ! ; : "pop ( -- addr len ) (" s -- ) "count "drop ; : "pick ( +n -- ) (" sn ... s0 -- sn ... s0 sn ) "th "@ ; : "roll ( +n -- ) (" sn ... s0 -- sn-1 ... s0 sn ) "th DUP "@ "top under - "pop + SWAP CMOVE> ; : "dup ( -- ) (" s -- s s ) 0 "pick ; : "over ( -- ) (" s0 s1 -- s0 s1 s0 ) 1 "pick ; : "-roll ( +n -- ) (" sn ... s0 -- s0 sn ... s1 ) "th "skip DUP "count + under - "top SWAP "dup CMOVE "pop ROT OVER - CELL- lplace ; : "swap ( -- ) (" s0 s1 -- s1 s0 ) 1 "roll ; : "rot ( -- ) (" s0 s1 s2 -- s1 s2 s0 ) 2 "roll ; : "depth ( -- +n ) (" sn-1 ... s0 -- sn-1 ... s0 ) 0 "top BEGIN DUP "ptr - WHILE "skip SWAP 1+ SWAP REPEAT DROP ; : "join ( -- ) (" s0 s1 -- s2 ) "top DUP >R "pop dup "length + R> ! OVER "ptr ! CELL+ CMOVE> ; : "joins ( n -- ) (" s0 s1 .. sn -- s ) 0 ?DO "join LOOP ; : "extract ( +n0 +n1 -- ) (" s0 -- s1 ) "pop ROT UMIN ROT OVER UMIN ROT OVER + -ROT - "push ; : "split ( +n -- ) (" s0 -- s1 s2 ) "dup 0 SWAP DUP "length "extract "swap "extract ; : "" ( -- ) (" -- s ) 0 0 "push ; : c"push ( char -- ) (" -- s) HERE 1 "push "count DROP C! ; : " ( ccc<"> -- ) (" -- s ) STATE @ IF POSTPONE S" POSTPONE "push EXIT THEN [CHAR] " WORD COUNT "push ; IMMEDIATE : "expect ( +n -- ) (" -- s ) HERE OVER "push "count ACCEPT "pop DROP SWAP "push ; : ". (" s -- ) "pop TYPE ; : ".s ( -- ) (" -- ) "top BEGIN "depth WHILE CR ". REPEAT "ptr ! ; : "Constant (" s -- ) CREATE "pop HERE OVER CHARS CELL+ ALLOT lplace DOES> ( -- addr ) "@ ; : "Variable ( +n -- ) CREATE DUP , 0 , ALLOT DOES> ( -- addr ) CELL+ ; : ?fits ( addr -- addr ) DUP CELL- @ "length U< ABORT" too long" ; : "! ( addr -- ) (" s -- ) ?fits "pop ROT lplace ; : "compare ( -- n ) (" s0 s1 -- ) "pop "pop compare negate ; : "= ( -- f ) (" s0 s1 -- ) "compare 0= ; : "< ( -- f ) (" s0 s1 -- ) "compare 0< ; : "<= ( -- f ) (" s0 s1 -- ) "compare DUP 0< SWAP 0= OR ; : "append ( c -- ) (" s0 -- s1 ) c"push "swap "join ; \ high-level functions \ substring-search : n"search (" s1 s2 -- s1 s2 ) ( n0 -- n1 tf ) 1 "th length rot /string 0 "th length SEARCH ROT DROP DUP >R IF 1 "th @ SWAP - THEN R> ; : "search (" s1 s2 -- s1 ) ( -- n1 tf ) 0 n"search "drop ; \ split at delimiter : "positions (" s1 s2 -- s1 ) ( -- n1 n2 ... nn n ) 0 0 BEGIN (" s1 s2 ) ( n1 ... nn n ) SWAP n"search WHILE (" s1 s2 ) ( n1 ... n nn ) SWAP OVER 1+ SWAP 1+ REPEAT DROP "drop ; : "delimiter-split (" s0 delim -- s1 ... sn ) ( -- n ) "length >R "positions R> OVER >R SWAP BEGIN ( n1 n2 ... ni delim-len i ) DUP WHILE ( n1 n2 ... ni delim-len i ) ROT "split OVER "swap "split "drop "swap 1- REPEAT ( delim-len i ) 2DROP R> 1+ ; \ join with delimiter : "delimiter-join (" s1 s2 ... sn delim -- s ) ( n -- ) BEGIN DUP 1- WHILE "swap "over "swap "join 2 "roll "swap "join "swap 1- REPEAT "drop DROP ; : "substitute (" s1 s2 s3 -- s1' ) ( -- ) 2 "roll 2 "roll "length "search IF ( l p ) "split "swap "split "drop 2 "roll 2 "roll "join "join EXIT THEN "swap "drop DROP ; \ --------- testing ------------- marker *test* : empty-stack ( i*x -- ) BEGIN depth ?dup WHILE 0< IF 0 ELSE drop THEN REPEAT ; : error ( c-addr u -- ) cr type source type cr empty-stack ; Variable context-depth Variable actual-depth base @ hex 20 Constant #stack base ! Create actual-results #stack cells allot : >actual-results ( i -- addr ) cells actual-results + ; : %depth ( -- u ) depth context-depth @ - ; : { ( -- ) depth context-depth ! ; : -> ( i*x -- ) \ record depth and stack content %depth dup actual-depth ! dup #stack > Abort" Test-Stack size exceeded - increase #stack" ?dup 0= IF exit THEN 0 DO I >actual-results ! LOOP ; : } ( i*x -- ) \ compare stack (expected) contents with saved actual content %depth actual-depth @ = IF %depth ?dup IF 0 DO I >actual-results @ - IF S" *** Incorrect result: " error LEAVE THEN LOOP THEN ELSE S" *** Wrong number of results: " error THEN ; { 3 4 + -> 7 } { " a" "depth "drop -> 1 } { " a" "dup "depth "clear -> 2 } { " a" "dup "= -> -1 } { " a" " b" "join " ba" "= -> -1 } { : txt " str" ; " str" txt "= -> -1 } { " abcdef" 1 3 "extract " bc" "= -> -1 } { CHAR z " a" "append " az" "= -> -1 } { " abc" " aaa" "< -> 0 } { " abc" " abc" "<= -> -1 } { " first" " second" "join " secondfirst" "= -> -1 } { " third" " second" " first" " , " 3 "delimiter-join " first, second, third" "= -> -1 } { " ab,cd" " ," "search "drop -> 2 -1 } { " ab,cd" " x" "search "drop -> 5 0 } { " ab,cd,ef,gh" " ," "positions "drop -> 2 5 8 3 } { " ab,cd,ef,gh" " ," "delimiter-split " -" "delimiter-join " ab-cd-ef-gh" "= -> -1 } { " aaa$bbb" " $" " xxx" "substitute " aaaxxxbbb" "= -> -1 } *test* \ --------- done testing ------------- cr .( Stringstack successfully loaded. ) here swap - . .( Bytes)
by UlrichHoffmann
Versions
Tags
forth-94, forth-2012strings, forth-2012, strings
Dependencies
None