0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

MLFEでstrtokもどきを実装する

Last updated at Posted at 2022-06-11

はじめに

自作のアセンブリ言語環境にて自作言語を動かすという夢があるので実装しました。
シリーズ化します(断言)。

strtok

char *strtok(s, ct) strtokではctからの文字によって区切られるトークンがsの中で探される。

プログラミング言語C 第2版 314頁より引用

かみ砕いて言うなら、まず初めにsに区切りたい文字列、ctに区切り文字列を指定し、区切り文字によって区切られた文字列のポインタを返す、二回目以降はsにNULLを設定し呼び出すことで次々と区切られた文字列のポインタが渡されるような挙動をします。

もどきなので実装するものの区切り文字は1つしか指定できませんが、まあ自分はスペースが区切れれば良いので良いとします。
(2022/09/24追記 string.hstrtokは区切り文字の間が空だったときそこを無視して次を読みに行こうとしますが、今回実装するものは間が空だったときNULLで埋められた領域を返却するという挙動をします。コメント欄参照)

フローチャート

厳密なフローチャートではありませんが、プログラムと合わせてみていただければわかりやすいのではと思います。

プログラム

; int* strtok(int* sadr, char delimit)
;   sadr(GR1)     : src string adr, local_char
;   delimit(GR2)  : delimiter char
;   ret(GR0)      : token string adr
;   l_temp(GR3)   : local temporary reg
;   l_sidx(GR4)   : local string index reg
;   l_bidx(GR5)   : local buf index reg

;CONST
STCNONE DC      1                   ; CONST 1
STCNNUL DC      0                   ; CONST NULL
;VAR
STAIDX  DC      0                   ; StrTok Addr InDeX
STSSA   DC      0                   ; StrTok Src String Addr
STSTBF  DS      256                 ; StrTok Str Token BuF
STSTBFL DC      256                 ; StrTok Str Token BuF Length
STFNL   DC      0                   ; StrTok Flag NulL

STRTOK  RPUSH   1, 6
        CPA     GR1, STCNNUL        ; if sadr = NULL
        JZE     STSANL              ;   then STSANL
        LAD     GR3, 0              ; 
        ST      GR3, STAIDX         ; STAIDX = 0
        ST      GR3, STFNL          ; STFNL  = 0
        ST      GR1, STSSA          ; STSSA  = sadr
        JUMP    STBFINI             ; jump StrTok Buf INItialize
STSANL  LD      GR3, STSSA          ; 
        CPA     GR3, STCNNUL        ; if STSSA = NULL
        JNZ     STBFINI             ;   else STBFINI
        LD      GR0, NULL           ; ret NULL
        JUMP    STFIN               ; jump STFIN
STBFINI LAD     GR3, 0              ; l_temp = 0
        LD      GR4, STAIDX         ; l_sidx = STAIDX
        LAD     GR5, 0              ; l_bidx = 0
STBFINL ST      GR3, STSTBF, GR5    ; STSTBF[l_bidx] = l_temp
        ADDA    GR5, STCNONE        ; l_bidx++
        CPA     GR5, STSTBFL        ; if l_bidx = STSTBFL
        JZE     STLPHD              ;   then STLPHD
        JUMP    STBFINL             ; jump STBFINL
STLPHD  LAD     GR5, 0              ; l_bidx = 0
STLPBD  LD      GR1, STSSA          ; l_c = STSSA[l_sidx]
        ADDA    GR1, GR4            ;
        LD      GR1, 0, GR1         ;
        CPA     GR1, GR2            ; if l_c = delimit
        JZE     STADLMT             ;   then STADLMT
        CPA     GR1, STCNNUL        ; if l_c = NULL
        JZE     STANL               ;   then STANL
        ST      GR1, STSTBF, GR5    ; STSTBF[l_bidx] = l_c
        ADDA    GR5, STCNONE        ; l_bidx++
        ADDA    GR4, STCNONE        ; l_sidx++
        JUMP    STLPBD              ; jump STLPBD
STADLMT ADDA    GR4, STCNONE        ; l_sidx++
        LAD     GR0, STSTBF         ; return STSTBF
        JUMP    STEND               ; jump STEND
STANL   LD      GR3, STFNL          ; if STFNL = NULL
        CPA     GR3, STCNNUL        ;
        JZE     STAFNL              ;   then STAFNL
        LAD     GR0, 0              ; return 0
        JUMP    STEND               ; jump STEND
STAFNL  LAD     GR3, 1              ; STFNL = TRUE
        ST      GR3, STFNL          ; 
        LAD     GR0, STSTBF         ; return STSTBF
        JUMP    STEND               ; jump STEND
STEND   ST      GR4, STAIDX         ; STAIDX = l_sidx
STFIN   RPOP    1, 6
        RET

利用例

実際に動かしてみます。STRTOKは省略します。

PGM     START
        LAD     GR1, SRC
        LAD     GR2, ' '
        
        CALL    STRTOK
        CALL    PRTAD
        
        LD      GR1, NULL
LOOP    CALL    STRTOK
        CPA     GR0, NULL
        JZE     LOOPEND
        CALL    PRTAD
        JUMP    LOOP
LOOPEND RET
        
; int* strtok(int* sadr, char delimit)
; 省略


PRTAD   OUT     ='[', =1
        RPUSH   0, 3
        LAD     GR2, 0
        LAD     GR3, '\n'
        CPA     GR0, =0
        JZE     PRTADER
PRTADLP LD      GR1, 0, GR0
        CPA     GR1, NULL
        JZE     PRTADED
        WRITE   GR2, GR1
        ADDA    GR0, =1
        JUMP    PRTADLP
PRTADED RPOP    0, 3
        OUT     =']\n', =2
        RET
PRTADER RPOP    0, 3
        OUT     =']0\n', =3
        RET

SRC     DC      'Hello world  !\0'
NULL    DC      '\0'

        END

strtok.feという名前で保存し実行してみると、

> python mlfe.py strtok.fe
[Hello]
[world]
[]
[!]

ちゃんと動いてますね、区切り文字が連続で存在する場所では返却値のポインタはヌル文字で埋め尽くされた領域のポインタを返し、ヌル文字が見つかったら返却値はヌルになってます。

おわりに

皆様も低レベルなプログラミング言語で、Cの標準ライブラリの機能を作ってみてはいかが?土日に暇つぶしにお勧めです。
それではさようなら。

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?