新規投稿は記事一覧のフォームからお願いします
> 最短で次の週末あたりには、手抜きバージョンが動き始めているかも。
> ラインバッファを文字列として取得するってところからわからない。ごめんなさい。「取得」は不正確でした。 「ラインバッファの『文字列』化」と言うべきところでした。 どういうことかと言うと,文字列操作関数は対象が「文字列」でないと, 最悪暴走する可能性があるんですね。「文字列」とは釈迦に説法ですが, 終端にヌル(00h)がある文字キャラクタの並びです。ラインバッファは 他のバッファと異なり,もともと終端にヌルがありません。そのため ラインバッファの終端にヌルを意図的に埋め込んで「文字列」にします。 そして,使い終わったら行編集のキャンセルコマンドをかませます。> はたまた、ラインバッファのアドレスを直接、文字列関数に渡す?要は,これになります。他のバッファに転送するわけではありません。 次のサンプルは対象とするコードの行番号正当性をチェックするだけのもの。 上限の値が16ビットに微妙に収まる範囲のようですので,より正確な判定は もう少し仕様を固めてからでよいかと思いました。 = Test *mad for vz! 1 ^\ "Bas_chk" ?. ; #^ ;ファイルの先頭からなら生かす #< e-, ;エラーのフラグ(仮) (e) ;; ==== メインのループ :L &n (r+1)??{ e+, >E } ;行番号取得,不正なら終了 #28 wa..19.2-, ;ラインバッファの文字列化 a=wa..18, ;ラインバッファ先頭アドレス (a) &Sw(a) b=r, ;行番号の桁数 (b) c=a.0, ;行頭キャラクタ (c) #54 ;行編集のキャンセル (b>5)?>E ;行番号が5桁を超えるエラー (b==5)?{ (c-$30>6)?>E } ;5桁の場合で先頭が6を超えるエラー ;; (上限を確認するか or 丸めるか) #> #d (r)??>L (e)?{ ;; ==== エラーの処理 :E &m("行番号不正またはファイルの最後") } :Z ;; ==== Quit &d #] . * 第一段階のチェックが終わったら,次は飛び先番号の洗い出しという手順かと。
> > 要は上限を超えるときの挙動をあらかじめ決めておきたい、ということです。
> それ,先に言ってくださいよ。(^^;
> &Sw(p) : 文字列pのスペース/タブまでの文字数
> こんなのが如何にも使えそうじゃないですか?
> 行番号の値が上限値を越えていても,処理の中で丸めてしまえばよくないですか?
> 要は上限を超えるときの挙動をあらかじめ決めておきたい、ということです。
> 「1文字ごとに cd で見ていく」
> ・半角数字で始まっていない行がある
> ・行頭の半角数字を数値として取得
> したときに上限値を越えている
> ぅぉぉ、こういうのがほしかったんですよ。
まずはじめに。> 一方で、ジャンプ先が実在しない場合は、変換例の> 110行目のように、変換が発生しないようにしたい。実機でもこういう仕様だった> と記憶しています。タッチアンドゴーで実家に行き、ちょっとN88-BASICの仕様を確認してきました。 滞在時間5分。 結果、記憶違いもあって。 飛び先の部分の変換が発生しないという部分は正解でしたが、行番号の変換自体 は行われていました。そして、「Undefined line number」なるエラーを吐く。 このエラーは、例えばGOTOの飛び先がないときに発生するエラーなんで、わりと よく見かけるものですが、まさかプログラムの実行時以外で見かけるとは覚えて いなかった。 もうひとつ、RENUMコマンドの引数って「新行番号、旧行番号、増分」なんです が、それぞれの引数は省略可能。そして増分を省略した場合のデフォルトは10。 ここで、先に例に出した4行のプログラムで「RENUM 65520」とかやると、最後 の行の行番号はデフォルトの最大値の65529を越えてしまいます。この場合は 「Illegal function call」エラーとなります。こちらはマニュアルにも明記 してあります。今回検討しているマクロでは、サブセット版であればこの上限値 は別の値でもいいでしょう。 ということで> 増分が1000番刻みって,あまりにも非現実的な気がするこれはおっしゃるとおり。 ただ、「増分が1000」ではなく「初期値が65500」でもいいのですが、要は上限を 超えるときの挙動をあらかじめ決めておきたい、ということです。 そして、その挙動としては、変換を全くはじめることなくマクロが終了すること を希望しています。> そもそも増分をどこで設定するのでしょう。これは、#5731にも書きましたが、マクロのコード内にハードコーディング。 絶対にないと思いますが、将来的には可変にしたい。> > また、BASICとして正当ではない行がある場合。> この判定は,無理ということはないですか?テキスト処理だけで行うと無理かもしれない。だけど、#5731に書いた正統性要件 だけでもチェックしたい。つまり ・半角数字で始まっていない行がある ・行頭の半角数字を数値として取得したときに上限値を越えている (上限値は別途定義) ・行頭の半角数字列のあとが半角空白でもタブでもない これらいずれかの要件を満たす行が1つでもある場合は処理を開始したくない。 ということで、このチェックに当たって私が考えた方法が 「1文字ごとに cd で見ていく」 なのです。というか、これしか思いつかなかった。 もちろん、他にもっと良い方法があればご教示いただきたい。> > 行番号の上限チェック。> 行数と増分の積というわけではないのですか?たぶんそれでいくと思うのですが、何か見落としがあることが怖い。> > 初期値の取得> 例えば,初期値と増分を決めておいてはいけないのですか?上にも書きましたが、増分はマクロコード埋め込みでよいと思っております。 が、初期値については、BASICのコードから、すなわち処理対象ファイルから取得 したい。そして、どうやって取得するかというと、ファイル先頭の行の行番号を 採用するということで。って、このへんのことは#5731にも書いていましたね。> 「カーソル位置の数字列を数値として取得するには」(VZマクロFAQ)ぅぉぉ、こういうのがほしかったんですよ。 とても参考になります。
> RENUMコマンドって、コードの中のGOTO文なんかの飛び先まで書き換えてくれる
> 最終仕様のものまで一気に作ってしまおうか、という気もする。
> ただ、条件判定で気になるのが、仮に増分を1000番刻みの場合、行番号が32000の
> 次は33000になるわけですが、素直に作ると、なんとなく比較が破綻しそうな値。
> また、BASICとして正当ではない行がある場合。
> 数字のあとに英字や記号がくっついている場合も処理中止。
> 論理行の要件チェック。
> 行番号の上限チェック。
> 初期値の取得
> そもそも「桃栗三年」と言いますしね。欲を出してはいけない。
よそ様で話題に出ていたネタです。長いです。90行を越えてしまった。 いにしえのN88-BASICには、行番号が必須です。 プログラムを作っている最中は行番号の並びなんてぐちゃぐちゃになってしまう ことも多々ありますが、ある程度固まったら、例えば10番おきとかにきれいに 整列させたいという希望があります。 これ、BASICのインタプリタ環境にいるときはRENUMコマンド一発で行けますが、 Vzでコードを書いているときは、なかなか一筋縄ではいかない。なぜというに、 RENUMコマンドって、コードの中のGOTO文なんかの飛び先まで書き換えてくれる のですが、これをVzマクロでやろうとするとなかなか大変。 この大変そうなものに挑戦しようと思いました。が、ほとんど思っただけ。 きちんと仕様を考えてたらとんでもないことがいろいろ発覚したので、まず最初 はサブセットで動くもの。とはいえ、できるかどうかわからない最終的な仕様を 目指して拡張性のあるものを作るくらいなら、最終仕様のものまで一気に作って しまおうか、という気もする。 いろいろな例外条件はあるのですが、基本的な外部仕様というか、こういう入力 がこうなってくれる必要がある、という例を以下に示します。 まず変換元。 100 IF A=B THEN 130 ELSE 150 130 GOTO 200 150 GOSUB 330:END 330 REM SUBROUTINE これを変換するとこうなってほしいという変換後。 100 IF A=B THEN 110 ELSE 120 110 GOTO 200 120 GOSUB 130:END 130 REM SUBROUTINE ジャンプ先が実在する行番号は、行番号の付け替えに伴い、コードの中身も置き 換わってくれることが必須。一方で、ジャンプ先が実在しない場合は、変換例の 110行目のように、変換が発生しないようにしたい。実機でもこういう仕様だった と記憶しています。 ところで、上記で「最初はサブセット」なんてことを書きました。フルセットに しない理由は、N88-BASICの仕様では、行番号の最大値は65529。そんなに大きな 行数のプログラムを作ったことがないので知りませんでした。が、なかなか微妙 な値です。とはいえ、もし簡単にこの値を使ったコードが実現できるのならば、 一気に作りたい。 さて、ここまでは事前の仕様検討で気がついた点です。 ここから実際のマクロを作りながら仕様を検討したら、次々と問題点が発覚。 まずは行番号の上限値。 たとえば、仮にサブセットとして上限値は32700でもいいのですが、処理を始める 前に上限を突破するかを確認し、もし突破するようならメインルーチンに入る前 に中止したい。これは初期値と増分と論理行数がわかれば計算できそう。 ただ、条件判定で気になるのが、仮に増分を1000番刻みの場合、行番号が32000の 次は33000になるわけですが、素直に作ると、なんとなく比較が破綻しそうな値。 ここはサブセットならではの制限をかける必要がありそう。 あるいはフルセットにするか。 また、BASICとして正当ではない行がある場合。 この場合、このファイルはN88-BASICのコードではないという理由で変換開始前に 処理停止。要は、途中まで変換して、そこでやめた、ということは回避したい。 この正当性の要件ですが、とりあえず思いつくものとしては、行番号で始まって いない論理行。空行がある場合も、これは行番号が付されていないわけですから 当然処理中止。また、行頭は数字でも、数字の並びのあとが半角空白かタブでは ない場合、つまり数字のあとに英字や記号がくっついている場合も処理中止。 ということで、私の考えたマクロのラフスケッチが以下のとおり。 初期設定 増分はハードコーディング 初期値は、開いているファイル自体の最初の行の行頭から取得 ファイル正常性確認 初期値、増分、論理行数から上限チェック 全ての行の行頭が数値であることのチェック メインループ 終了処理 ここでいくつか質問。 まず、論理行の要件チェック。 ループまわして各行チェック、というのはわかります。 そして、1文字ごとに cd で見ていくのが確実ですが、そうではない、なんか楽 な方法はないものか、と。 そして、行番号の上限チェック。 初期値の取得はカーソルをファイル先頭に移動させて &n ですが、論理行数って カーソルをファイル末尾に移動して ln というのが常套手段でしょうかね。 そして、モロモロ掛け算とか足し算とかで、さて上限値を超えたときのチェック はどうすればよいでしょうか。 さらに、将来的なフルセットの場合、行番号の初期値は40000だった、というもの にも対応させたいわけですが、これって &n では対応できませんよね。ならどう すればよいか、ということについてもアイディアをお伺いできればと思います。