Island Life

2014/01/19

行継続

行指向の文法、つまり改行が単なる空白文字より大きな区切りを意味する文法において、 編集上の都合から見た目の行を折り返したい場合がある。 多くの場合は、行末に「次の行に継続する」ことを指示する文字を置くことで実現される。 行末バックスラッシュが多いのはUnixとC文化かな。 Common Lispのformat文字列では~。Fortranは&。Texinfoは@。 Visual Basicではアンダースコアだったっけ。

一方Vim Scriptでは、行末に文字を置くのではなく、継続する行の先頭に文字を置くよ、 という話を読んだ。

本当にキモい Vim script - 行継続編

さて、では一方 Vim script は、と言うと…

let g:quickrun_config = {
\   '_': {
\     'input': '=%{b:input}', 'cmdopt': '%{b:cmdopt}', 'args': '%{b:args}',
\     'runner': 'vimproc',
\     'runner/vimproc/updatetime': 500,
\   },
\ }

viとの互換性が理由だそうだ。

が、「次の行の方に前行からの継続を示すマーカがある」という文法を扱ったことが 何回かあるような気がしたので考えてみた。

RFC822のヘッダは原則1行で完結するけれど、次の行が空白文字で始まっている場合は それが継続行とみなされる。

Subject: Long subject line
  can be folded
  like this.

WiLiKiのマークアップは、行頭の ~ で前の行からの継続を示す。

強調などのマークアップは行をまたげないので、'''長い行をこんなふうに
~強調したかったら行継続を使う'''。

なぜこうしたのか忘れちゃったけど、wikiマークアップは「行頭にあること」 で意味を持つものが多いのでそれに合わせたのかも。

プログラミング言語で「次行行頭」にマーカを置く例はなかなか見つからない。 COBOLが "-" を「リテラルを前の行から継続」に使ってるけれど、 '-'を書くカラムが決まってるから「行頭」と言えるかどうか。

http://cobol.404i.com/basics.php

000340       DISPLAY 'This might be a very long string that
000350-    'needs to be continued onto the next line'

この表記を見てFTPのリプライ行継続マーカ (あれも-だ) を思い出したが、 FTPの方は「次に続く行がある場合」につけるので、「行末継続文字」グループの 親戚みたいなもんだろう。

★ ★ ★

技術的な観点では、「前の行から続いているよ」というマーカよりは、 「まだ行が続くよ」の方がパーザが書きやすい。前者では 次の行を読んでみないと今の行が終わるかどうかわからないので、 先読み、もしくはバッファリングが必要になる。

ただ、人間が普通のテキストを読み書きする際には、「まだ続くよ」マーカは あまり使われない。「行」が意味を持つ文章で、組版の都合でどうしても 行途中で折り返さないとならない時は、継続行がインデントで示されるのが普通だ。

Their sense thus weak, lost with their fears thus
  strong,
Made senseless things begin to do them wrong;
For briers and thorns at their apparel snatch,
Some sleeves, some hats, from yielders all things
  catch.

これは手元にあったペーパーバックからフォーマットをそのまま引用したものだけど、 "strong" や "catch"が前行からの継続であることは自然にわかる。 RFC822形式はある意味「人間にとって自然な記法」と言えるかもしれない。

「行の継続」だけでなくもう少しスコープを広げると、 結局先読みやバッファリングが必要になる構文はそこそこある。

  • Makefileのタブを使う文法は今となっては古くさいけれど、あの行頭タブは ひとつのルールのブロックを継続するマーカと言える。
  • インデント指向な文法でも、次の行のインデントを読んでみないと 今のブロックが終わるかどうかはわからない。

なので、パーザの書きやすさを理由に「次の行に続くよ」式文法を採用する意味は あまり大きくないかもしれない。

★ ★ ★

行継続構文についてもうひとつ考えるべき問題は、行をくっつけた時の「糊」の部分を どうするか、である。トークンの区切りとしての空白は何個あっても意味が変わらないので ただ行をくっつけるだけで良いが、リテラルの中で改行している場合は空白の個数が 意味を持ってくる。

「ただくっつける」という動作の場合、リテラル中に余分な空白を入れたくなければ、 次の行を行頭から始めないとならない:

  str = "This is a string \
literal"

けれども、意味的にインデントを揃えたいと思うのが人情だろう:

  str = "This is a string \
         literal."

このため、「次に来る行の行頭の空白を全て無視する」としている仕様もある。 Schemeの文字列リテラルや、Common Lispのformat文字列の ~がそうだ。

(define str "This is a string \
             litreral.")

しかしこれはこれで、「出力の行頭に一定数のスペースを含めたい」って時に ややこしい。例えばこんな出力が欲しいとき:

Usage: command [-a arg] [-b arg] file ...
Options:
   -a arg    Blah blah blah
   -b arg    Blah blah blah

物理行の先頭でインデントしててもその空白が食われてしまうので、 必要な空白の前に空白でない何かを置いとかないとならない:

(define (usage)
  (display "Usage: command [-a arg] [-b arg] file ...\
            \nOptions:\
            \n  -a arg    Blah blah blah\
            \n  -b arg    Blah blah blah\
            \n"))

Common Lispのformat文字列では「次の行の空白を保存する」という オプションもあるが、プログラムテキスト上の意味的なインデントと 出力に含めたいインデントを区別できないので、ちょっと足りてない感じだ。

「後続行に、前から続く行であることを示すマーカを入れる」という文法であれば、 空白文字以外のマーカを使うことでこの問題を解決できる。 たとえば仮想的に、行頭の\s*~が「前の行からの継続」を示す、 という文法があるなら、こんなふうに書けるだろう。

(define (usage)
  (display "Usage: command [-a arg] [-b arg] file ...\n
           ~Options:\n
           ~  -a arg    Blah blah blah\n
           ~  -b arg    Blah blah blah\n
           ~"))

リテラルに関してこれに近いことをやっていた言語があったような気もするのだけど 思い出せない。

なお、「人間にとって自然」に見えるRFC822の行折り返しだが、空白文字の扱いについて 微妙な点がある。英文の慣習では、\s*\n\s+ がひとつの空白に置換され、 RFC822もそれに沿っているわけだが、この文法だと「空白を含めずに折り返す」 というケースが書けない。Subjectヘッダの扱いに関して困った覚えがある。 (MIMEを用いても、各MIMEエンコーディングは物理行内で完結しないとならないので、仕様に厳密に従うと行継続の空白が残ってしまうのだ。実際のメールクライアントはそのへんヒューリスティックに対応しているっぽいが。 (追記2014/01/20 06:06:20 UTC)これは私の誤解だった。rfc2047の6.2節にてこのケースへの対応が示されている。コメント欄参照。) なので、「継続を示すマーカ」は空白文字とか区別できる方がいい。

特に結論めいたものはないけれど、新たな文法を考えるなら、 少なくともリテラルの行継続については、「行頭の <空白>* <非空白文字のマーカ>」というのは 案外良い選択なんではないかな、と思った。

Tag: Programming

2014/01/18

ピアノレッスン115回目

今週はゆっくり、正確さを重視してさらっていった。効果絶大。

  • Kapustin: Concerto Etude Op40-1
    • MM==112くらい。とてもクリアになってgood。ミスタッチを減らす。
  • Ravel: Ondine
    • クライマックスまではとても良くなったが、その後は練習が足りてないね。

Tag: Piano

2014/01/11

ピアノレッスン114回目

  • Kapustin: Concerto Etude Op40-1
    • Jazzyなノリを保ったまま徐々に速くできるようになってきた。でもまだ安全に弾けるのはMM=108くらい。楽譜指定は144である。本人の録音は少し遅くて138くらいだと思うのだが、 極めてクリアに弾いているのでそれほど速い感じがしない。 自分は今のところ120が限界で、弾いてるとめっちゃ速くて目がまわりそうなんだが 録音したのを聴いてみると遅く聞こえる。このギャップを何とか埋めたい。
  • Ravel: Ondine 伴奏が強すぎる。メロディ、メロディ。

Tag: Piano

2014/01/01

blogっぽいののソース

2010年の元旦に、 それまでWiLiKi:Shiroにメモしていた日々の記録を こちらのblogっぽいの(WiLiKiをカスタマイズしたもの)に移した。 しばらく使ってみていけそうだったらWiLiKiのサンプルとして公開しようと 思ってたんだけど、pratcical-scheme.net固有の諸々が埋め込んであったりして ちゃんと分離するのが面倒でついつい先延ばしにしているうちに4年も経ってしまった。

ここでまた先延ばしにすると次に気づいた時には10年くらい経っていそうなので、 えいやっと形を整えて何とかWiLiKiのリポジトリに放り込んだ。

もう自前のスクリプトでblogやろうなんて時代じゃないだろうけど、 WiLiKiのいじりかたのサンプルにはなるかも。

試したい人のためにごく簡単にセットアップ方法を冒頭に書いてある。 ログインしてエントリの編集をしてみると、基本的なところはWiLiKiそのまんまという ことがよくわかると思う。コメント欄とかも自動で出るわけじゃなくて、 いちいち $$comment マクロを書いているのだ。実は。 他にも「blogスクリプト」として見ると機能がたりないところはいくらでもあると思うんで、 「WiLiKiマークアップで書きたい」とか 「マクロをGaucheで書きたい」と思う人でなければあまり使う意味は無いだろう。

Tags: Programming, Gauche, WiLiKi

2013/12/29

思い出した、8051だった

ジャンク部品で8bit PCを組み立てて遊んでいた頃、 憧れた周辺機器のひとつはプリンタだった(もうひとつはHDD)。 ある日アキバで放出品、仕様無しのドットインパクトプリンタを見つけて買った。 何かの専用プリンタで、 インタフェースはセントロでもRS-232Cでもなく、 簡単なマニュアルはついてたかもしれないが、プロトコルとかはドキュメントされてなかったはず。 多分1000円とか2000円とかそんなもんだったと思う。当時の財力を考えると。

中を開けてみるとワンチップマイコンとROMがあって、 幸いROMはソケットに刺さってたので抜き取って読み出せた。 ワンチップマイコンの方は型番を調べて、仕様を手に入れた。 (今ならネットでいくらでも調べられるが、当時どうやったのかもう覚えてない。) 逆アセンブラを作って吸い出したコードを喰わせ、 プロトコルを解析して自作PCにつないだ。 すごい音だったので夜間の使用は禁止された。

このワンチップマイコンが何だったか忘れていたんだけど、 この記事をきっかけに思い出した。型番を見たらああそうか、と記憶が蘇った。

なんと今はMicro SD内に組み込まれてbad blockの管理をやっているらしい。

Tags: PC, Computer

More entries ...