新規投稿は記事一覧のフォームからお願いします
#5753 のとしきさんのマクロを見直しました。 あれ? 正規表現を使っているのに RX+ が無い? としきさん、RX+ 派だったの? (^^; ということで、めざらさんのマクロから部品を拝借して、マクロの冒頭に mp[=2, ps[, RX[+, Ec[+, ;★ ;検索モード,正規表現,英大/小文字同一視有効 この行を追加 GOSUB ルーチンの後ろに #56 "THEN\([ \t]+\)" &?("%d",o) "$$" #m ;★ これ以降コピペして追加 "THEN\1" &?("%d",n) #m "ay" #56 "THEN\([ \t]+\)" &?("%d",o) "\([^0-9]\)" #m "THEN\1" &?("%d",n) "\2" #m "ay" #56 "ELSE\([ \t]+\)" &?("%d",o) "$$" #m "ELSE\1" &?("%d",n) #m "ay" #56 "ELSE\([ \t]+\)" &?("%d",o) "\([^0-9]\)" #m "ELSE\1" &?("%d",n) "\2" #m "ay">w:u Ec], RX], ps], mp], . ;★ 追加 * これらを追加、変更したら正常に動作するようになりました。 10 A=10:GOSUB 4000'10 30 INPUT A'30 200 IF A$=CHR$(13) THEN 3000 ELSE 200'200 210 'if a$=chr$(13) then 3000 else 200 '210 300 GOTO 30'300 3000 END'3000 4000 FOR I=1 TO A:NEXT'4000 4200 RETURN'4200 ↓ ↓ ↓ 10 A=10:GOSUB 70'10 20 INPUT A'30 30 IF A$=CHR$(13) THEN 60 ELSE 30'200 40 'if a$=chr$(13) THEN 60 ELSE 30 '210 50 GOTO 20'300 60 END'3000 70 FOR I=1 TO A:NEXT'4000 80 RETURN'4200 コメント行も変換されますが、むしろこの方がいいかも。 それにしても、RX+かぁ・・・ ハッ!! RX78・・・ガンダムネタか? #「ようやくわかりましたよ、シャア少佐。よしんばこのネタを打ち漏らしても、 我が見方の方に引き寄せる、二段構えの作戦ですな」
> そもそも「コメント行」がどこなのかわからないし,そんなの知らんし。
> さらに,飛び先に前置された命令にどんなものがあるか知らされていません。
> つまり仕様ですね。
> > > (4) VZ側でのワードサーチは無視されます。
> やっぱりそっちか~。となると手がない。一括置換式はギブアップかな~。
> konnoさんが誠実な人であるのは間違いがないところでしょう。根がいい加減なのでなるべく誠実なふりをしているとバレてるかもしれんが。(^^;> > NP2でN88BASIC を使って RENUM や中間語に変換してみました。> これ、変換に使ったツールの記述はありますが、変換後をどうやって表示している> のかがよくわからない。文字化けっぽい表記になっている、というのもあって。VZで開いて見えたイメージをテキストにしたのです。ここの人達ならわかるかと。(^^;> ということで引っ張り出してきたのが、ASCIIの出版した「PC-Techkonw 8800」> という本。ISBN4-87148-292-8。archive.orgにあるかなぁ。ググったら MSX2のがありました。\(^^)/ https://archive.org/details/MSX2TechnicalHandBookFE1986/mode/2up> この本には、ROM内のルーチンのどのアドレスに何をするコードがあるか、と> いう表も載っていて、それによると、RENUMを行うルーチンは75DDH~7673Hに> あるとか。なんと、150バイト。もちろん、どこかよそのサブルーチンを呼んで> いるのかもしれませんが、でもRENUMでも使うような汎用性のあるルーチンて> ちょっと思いつかないので、これで全部のような気もする。マシン語ならそのくらいで出来るかもしれませんね。 せっかくなので私も DEBUG の結果を張っておきます。 3D6A:0100 FE 15 00 0A 00 01 41 00-F1 0F 0A 3A A4 01 0E A0 ......A....:.... 3D6A:0110 0F 00 27 31 30 00 0E 00-1E 00 01 A7 01 41 00 00 ..'10........A.. 3D6A:0120 27 33 30 00 24 00 C8 00-02 A8 01 41 00 24 F1 FF '30.$......A.$.. 3D6A:0130 9C 28 0F 0D 29 01 D6 01-0E B8 0B 01 3A 99 01 0E .(..).......:... 3D6A:0140 C8 00 00 27 32 30 30 00-2E 00 D2 00 01 00 27 69 ...'200.......'i 3D6A:0150 66 20 61 24 3D 63 68 72-24 28 31 33 29 20 74 68 f a$=chr$(13) th 3D6A:0160 65 6E 20 33 30 30 30 20-65 6C 73 65 20 32 30 30 en 3000 else 200 3D6A:0170 09 27 32 31 30 00 10 00-2C 01 02 A3 01 0E 1E 00 .'210...,....... 3D6A:0180 00 27 33 30 30 00 0D 00-B8 0B 01 9A 00 27 33 30 .'300........'30 3D6A:0190 30 30 00 19 00 A0 0F 01-9E 01 49 00 F1 11 01 DA 00........I..... 3D6A:01A0 01 41 00 3A B7 00 27 34-30 30 30 00 0D 00 68 10 .A.:..'4000...h. 3D6A:01B0 01 C6 00 27 34 32 30 30-00 1A 00 00 00 00 00 00 ...'4200........ 10 A=10:GOSUB 4000'10 30 INPUT A'30 200 IF A$=CHR$(13) THEN 3000 ELSE 200'200 210 'if a$=chr$(13) then 3000 else 200 '210 300 GOTO 30'300 3000 END'3000 4000 FOR I=1 TO A:NEXT'4000 4200 RETURN'4200
お忙しいのにこちらばかり盛り上がって申し訳ない。 まだ学校が始まっていないので,超絶ヒマしてます。 その一方で畑仕事のエンジンはかからないままです。 週末以降に次の v0.20 を試してみてください。初版は破棄します。 = likereno v0.20 = by H_ear #if 0 Like RENUM #endif * mad for vz! 1 ^\ "" ?. #^ #< a=10, ;増分値 (a) &n b=c=r, ;番号付開始値を取得 (b/c) 可変 (r+1)??{ &m(41) . } ;準備ができていないなら終了 mp[=2, ps[, RX[+, ;検索モード,正規表現有効 &01 ps=r, mi[-, ;挿入有効 :L ; ---- main loop ---- #t &?("%u",b) &#M(1) ;戻る位置をマーク ; ---- 飛び先の処理 ; #56 &?("[\s\t]%u",c) #m &?("♭%u",b) #m "ay" ; v0.10 × ; \x は \w を無効化するため マッチした番号を &n で都度確認 #F &?("[\s\t]%u",c) #m #^ #< :J #c (r)?{ ;見つからなければ &#U(1) >N ;戻って次行へ }?{ ;見つかったら #f &n ;番号の照合 (r==c)?{ ;一致すれば #t &?("♯%u",b) ;飛び先に書き換える+処理印 } >J ;次を探す } :N #> #d ;通常は r==-1 なら停止だが &n c=r, ;旧行番号を取得 (c) (r+1)?{ b+=a, >L } ;&n の値が不正になるので無視 :Q ; ---- 飛び先有効化 ---- #56 "♯" #m "" #m "ay" :z ; ---- exit ---- mi], RX], ps], mp], &d #] . 01: ; ---- buffer ---- (5+$)."$(10,0)$[16]" *> 単にGOTOやGOSUBの頭にフラグという意味で"F"をつけるだけでもいいこのあたりは好きずきでしょうね。わたしは昔から一時文字使用派です。 確か,最初の実用仕事マクロでも使った手でした。骨身に染みてる。 FGO(Fateか)なんてキーワードがなきゃいいですが……でも, カーソル移動とか発生しませんか?> アルゴリズムを見るといずれも、旧行番号と新行番号の対応表を作る最初はそうするものかなぁ……と思って,旧番号抽出マクロを作っては みたのですが,ひどく面倒だったので付け替え単位にしました。 あと,ひとつ。重要な仕様の再確認なのですが…… goto gosub だけでよいのですか? then とか else は? わたしはキーワードに束縛されないように組んでいるけど,気になる。
> > 命令や関数の前後は、必ずしも空白文字で区切らなくてもよい。
> やだねぇ、こういう細かいところにこだわるオタクって。
> > (4) VZ側でのワードサーチは無視されます。
konnoさんが誠実な人であるのは間違いがないところでしょう。 ですが、この発言に関しては、ちょっと混乱を招くというか、資料的価値に 欠けるというか。> NP2でN88BASIC を使って RENUM や中間語に変換してみました。これ、変換に使ったツールの記述はありますが、変換後をどうやって表示している のかがよくわからない。文字化けっぽい表記になっている、というのもあって。 ということで引っ張り出してきたのが、ASCIIの出版した「PC-Techkonw 8800」 という本。ISBN4-87148-292-8。archive.orgにあるかなぁ。 対象がPC-8801なので、PC-9801とは異なっているかもしれませんが、中間言語の 一覧が掲載されていたりします。これによると、例えば FOR 82H NEXT 83H GOTO 89H GOSUB 8DH IF 8BH PRINT 91H などとなっているそうです。 また、プログラムの格納状況の具体例も載っています。 サンプルのプログラムは以下。> 100 FOR I=0 TO 20 STEP .5> 110 PRINT I,SQR(I)> 120 NEXT Iこれの中間言語での格納状況が以下。> 8000 00 18 00 64 00 82 20 49 F1 11 20 DC 20 0F 14 20> 8010 DF 20 1D 00 00 00 80 00 27 00 6E 00 20 91 20 49> 8020 2C FF 87 28 49 29 00 2F 00 78 00 83 20 49 00 00> 8030 00転記に当たって間違いがあるかもしれません。 例えば、最初の「64 00」が行番号の100を表し、その次の82HはFORの中間言語。 行番号200は「6E 00」だけど、そこには字下げがあるから空白文字の20Hが 入っていて、その次にPRINTを表す91Hがある。 みたいな感じになっています。 この本には、ROM内のルーチンのどのアドレスに何をするコードがあるか、と いう表も載っていて、それによると、RENUMを行うルーチンは75DDH~7673Hに あるとか。なんと、150バイト。もちろん、どこかよそのサブルーチンを呼んで いるのかもしれませんが、でもRENUMでも使うような汎用性のあるルーチンて ちょっと思いつかないので、これで全部のような気もする。 また、バッファとかワークエリアの一覧の表の掲載もあるけど、見た範囲では、 RENUM用のバッファって見つからない。やはり、あんまりその手のバッファを 使わないアルゴリズムであろうことが予想される。 ちなみに、PC-98用のTechknowを謳っている書籍はBNN社から発刊されている と聞いています。さらにいうと、archive.orgに収録されているらしい。 もしかしたら、こちらには中間言語のもっと詳しくてわかりやすい説明が 載っているかもしれません。ないかもしれませんが。
ちょっと興味が湧いて、PC-8201について調べてみました。 結果、Wikipediaの「PC-8201」の項には> BASIC N82-BASIC(N-BASICをベースという記述がありました。 次に、同じくWikipediaの「N-BASIC」の項には> 命令や関数の前後は、必ずしも空白文字で区切らなくてもよい。と明記してありました。なるほど。 そういえばそうだったような記憶もあるようなないような。 ん、その直後、いささか誤解を招くような記述がある。> > FORTRAN=ATOK5> と記述すると、> 「変数『FORTRAN』に、変数『ATOK5』の値を代入する命令(LET文)」> ではなく、「『TRAN』という変数を、変数『A』の値を初期値、変数『K5』> の値を終値としてループを回す命令(FOR文)」として解釈された。この記述で間違いではないのかもしれませんが、間違いかもしれない。 なぜというに、変数名は2文字でしか識別されないので、正確には 「『TR』という変数を、変数『A』の値を初期値、変数『K5』の値を終値 としてループを回す命令(FOR文)」 として解釈されるはず。 やだねぇ、こういう細かいところにこだわるオタクって。
> = likereno.def = by H_earちょっと意地悪なリストで試してみました。(^^; 10 a=1 '10 20 'input a '20 40 'a$=input$(1)'40 150 a$=inkey$ '150 200 if a$=chr$(13) then 3000 else 150 '200 210 'if a$=chr$(13) then 3000 else 150 '200 300 goto 40 '300 400 'goto 40 '400 3000 end '3000 これの結果は 10 a=1 '10 20 'input a '20 30 'a$=input$(1)'40 40 a$=inkey$ '150 50 if a$=chr$(13) then 700 else 40 '200 60 'if a$=chr$(13) then 700 else 40 '200 70 goto 30 '300 80 'goto 30 '400 90 end '3000 うーん、コメント行が除外出来ない? マクロが読めない。(>_<) ちなみにとしきさんのマクロはここが違います。 50 if a$=chr$(13) then 3000 else 150 '200 60 'if a$=chr$(13) then 3000 else 150 '200 70 goto 40 '300 80 'goto 40 '400 THEN ELSE を GOTO ルーチンに倣ってコピペしても駄目でした。(>_<)> 同様のキーワードで,ナマで検索するときちんとワードサーチが効いており,> そういうことにはならない。マクロのバグ? VZのバグ? 【謎】VWX.DOC には> ■ 制限事項など> (4) VZ側でのワードサーチは無視されます。とありますが、違う話なのかな?
チェックなしで,いきなり実行するものです。 飛び先番号の前に空白があることが必要で,これは「仕様」です。 = likereno.def = by H_ear #if 0 Like RENUM #endif * mad for vz! 1 ^\ "" ?. #^ #< a=10, ;増分値 (a) &n b=c=r, ;番号付開始値を取得 (b/c) 可変 (r+1)??{ &m(41) . } ;準備ができていないなら終了 mp[=2, ps[, RX[+, ;検索モード,正規表現有効 &01 ps=r, mi[-, Ew[+, ;挿入,ワードサーチ有効 :L ; ---- main loop ---- #t &?("%u",b) #56 &?("[\s\t]%u",c) #m &?("♭%u",b) #m "ay" #> #d ;通常は r==-1 なら停止だが &n c=r, ;旧行番号を取得 (c) (r+1)?{ b+=a, >L } ;&n の値が不正になるので無視 :Q ; ---- 飛び先有効化 ---- #56 "♭" #m " " #m "ay" :z ; ---- exit ---- Ew], mi], RX], ps], mp], &d #] . 01: ; ---- buffer ---- (5+$)."$(10,0)$[16]" * これ,一見うまく動いているように思われるわけですが,ワードサーチ有効 にもかかわらず,例えば 330 の行を 150 に変換するという場合に 3300 が あったりすると,goto 3300 が goto 1500 になってしまいます。【謎】 同様のキーワードで,ナマで検索するときちんとワードサーチが効いており, そういうことにはならない。マクロのバグ? VZのバグ? 【謎】 ワードサーチが効かないと,どうにも仕様がない。お手上げじゃ。
NP2でN88BASIC を使って RENUM や中間語に変換してみました。 1000 'SQR.bas E8^C=$03E8=1000 1060 '入力待ち .^D=$042E=1070 1090 if a$="" then 1070 B^D=$0442=1090 ^N=then .^D=$042E=1070 行番号は ^@+16進数に、ラベルとしての番号は16進数+^@ のような感じかな。 以下は RENUM したソースと中間語の一部 10 'SQR.bas ^@$0A=10 ^@^T 20 'screen 0 ^@^T =20 ^@^R 30 PRINT " input "; ^@^^ 30 ^@$0A 40 INPUT A ^@( =40 ^@ 50 PRINT " SQR(";A;")";SQR(A) ^@2 =50 ^@^H 60 ' ^@< =60 ^@^P 70 '入力待ち ^@F =70 ^@^[ 80 PRINT " push eny key "; ^@P =80 ^@^O 90 A$=INPUT$(1) ^@Z =90 ^@^Z 100 IF A$="" THEN 80 ^@d =100 ^Aヨ^A^N=then P^@=80 ^@$09 110 CLS:END ^@n =110 先頭は行番号で、端は改行? ^@^@ と思いきや、謎のコードが挟まってたり? 100 IF A$="" THEN 80 ↓ ^@d^@^Aィ^AA^@$F1""^Aヨ^A^NP^@ 中間語 ↓ ^@d = 100 ^Aィ^A = IF A^@$F1"" = A$="" ^Aヨ^A^N = then P^@ = 80 RENUM はやっぱり中間語で検索しながら番号を置き換えているんでしょうね。 これ見るとスペースは要らないように思えますね。 重複防止の仕組みはわからないけど。
> どうやって判別するのか。これ、どんな方式でやろうと、ついて回る問題
> それよりも,Konno さんの例で挙げれば,Ec(検索時の英大/小文字の同一視)を有効(デフォルトは無効)にしておくことに注意すべきかもしれません。
> > このロジックでは、一旦変換した行番号が再変換の対象になりうる
> それを「最悪」と。
> ただ、許容してほしい(ウソ&笑)。なぜなら、以下のようなのを見たことが
> あったからです。
> 文字化けはともかく、よくこのソースを投稿するよなぁ、そしてそれをそのまま
> 掲載するよなぁ、と思ったことがありました。
としきさん 了解です。お題は、N88-Basic 用 renum ですからね。 ただ、許容してほしい(ウソ&笑)。なぜなら、以下のようなのを見たことが あったからです。 文字化け退治の試みは一切しておらず、失礼なのですが。 ただし改行だけ入れました。たとえば、行番号10は、1論理行でした。20も。 GALACTIC ARMY for PC-8201 (B-mag, 1985/01, p.143) 10 CLEAR256,61970!:DEFINTA-:DIMF(3),A(3,8),UXC3),UY(3),Al$(3),U$(1),C$(6) :T$." "+CHR$(30)+CHRS(29)+CHR$(l32):U$(1)." "+CHR$(31)+CHRS(29)+CHR$(144) :M$." "+CHR$(131)+" ":C$(1l." "+CHR$(31)+STRING$(2,29)+CHR$(139) 20 C$C2)=LEFT$(C$(l),4)+CHR$(137):C$(3).LEFTICCIC1),4)+CHR$(135) :C$(4)." "+CHR$(31)+CHR$(13"3):C$(5l.LEFTS(C$(4),2)+CHRS(137) :C$(6).LEFT$CC$(4),2)+CHRSC135):AD!=61970!:GOSU8330 文字化けはともかく、よくこのソースを投稿するよなぁ、そしてそれをそのまま 掲載するよなぁ、と思ったことがありました。
> 後方変換なら問題ないのかなぁ。
> なので私はテスターに徹しようと思います。(^^;
> 例えば100から始まって990までで終わっているプログラムを1000からに変換する、みたいな
> vwxの常駐確認とか?
> RXとかの設定も念のためにするべき?
> このロジックでは、一旦変換した行番号が再変換の対象になりうる
> とりあえず、私のきちんと動かないバージョンはできました。良いのが出来たら私もお世話になるかもしれないので試してみました。(^^; 以前素数でやった PN88-02.BAS です。 2024/04/03 21:03 4,173 PN88-02.BAS 初期値が必要なので、先頭に 100 ' を挿入して実行してみました。 1000 'prime88.bas 2024-03-22 ↓ 110 'prime88.bas 2024-03-22 結果は 1365 s=I:gosub 3200:s=n ↓ 480 s=I:gosub 3200:s=n 3110 if xx <> lastx then 3080 'loop1 ↓ 1450 if xx <> lastx then 3080 'loop1 このように、gosub 文が変換されませんでした。 小文字だったからでしょうね。 まぁ普通は対象外ですよね。(^^;> すぐにわかることですが、このロジックでは、一旦変換した行番号が再変換の> 対象になりうるわけです。なので、ここはやっぱり素直に変換表を作るような> ロジックにする必要がある。私は別ファイルに書き出すものと思っていました。それだと GOTO GOSUB が問題か。 後方変換なら問題ないのかなぁ。具体的には何も考えていないもので。(^^; なので私はテスターに徹しようと思います。(^^;
> ちょっと思ってるのと違った。この + は要ります?可読性向上のための桁そろえ、というのがあるかもしれないと考えました。 とりあえず、私のきちんと動かないバージョンはできました。 きちんと動かないことは理解していますが、条件がそろうと動くこともある、 といった感じ。 = renum.def i:初期値 initial num a:増分 addition n:新行番号 new num o:旧行番号 old num *m 1 ^^ "renum.def" ;初期設定 ;vwxの常駐確認とか? a=10, n=o=0, ;RXとかの設定も念のためにするべき? #^ #< ;カーソルを先頭行の行頭にして &n i=r, ;初期値取得 ;メインループ ;先頭行は行番号の変更なし :w ;while(次の行に動ければ) #> #d ;次の行にカーソルを移動し #d (r==-1)?>u ;その結果が最終行ならループ脱出 #< &n o=r, ;旧行番号取得 n=i+(ln-1)*a, ;新行番号算出 #t ;旧行番号削除 &?("%d",n) ;新行番号出力 #56 "GOTO\([ \t]+\)" &?("%d",o) "$$" #m "GOTO\1" &?("%d",n) #m "ay" #56 "GOTO\([ \t]+\)" &?("%d",o) "\([^0-9]\)" #m "GOTO\1" &?("%d",n) "\2" #m "ay" #56 "GOSUB\([ \t]+\)" &?("%d",o) "$$" #m "GOSUB\1" &?("%d",n) #m "ay" #56 "GOSUB\([ \t]+\)" &?("%d",o) "\([^0-9]\)" #m "GOSUB\1" &?("%d",n) "\2" #m "ay">w:u * すぐにわかることですが、このロジックでは、一旦変換した行番号が再変換の 対象になりうるわけです。なので、ここはやっぱり素直に変換表を作るような ロジックにする必要がある。 逆にいうと、例えば100から始まって990までで終わっているプログラムを 1000からに変換する、みたいな感じで再変換が発生しないような変換だと、 なんとなくうまく動いているっぽい。もちろん、意図的に考慮していない 部分はいっぱいありますが、意図せざる考慮漏れというのがあれば、これで あぶりだせたらちょっとはうれしいかも。 ということで、めざらさんに提示していただいたコード、これから読解して いきます。