Next: , Previous: Changecom, Up: Input Control


7.4 単語(word)の字句構造を変更する

マクロchangewordとそれに関連する機能すべてが実験段階にあります。 GNU m4をインストールする際 configure--enable-changewordオプションを与えたときだけ この機能を使用することができます。 これから先、この機能が変更されたり、削除されてしまうことさえありえます。 したがって、この機能に依存した使い方はしないで下さい。 この機能について意見を寄せていただくときは バグを報告するときと同じ方法で行ってください。

m4によって処理されるファイルは、クォートされた文字列、 単語(潜在的なマクロ名)、そして単純なトークン(その他の単一の文字すべて) に分割されます。 初めに単語は次の正規表現によって定義されています。

     [_a-zA-Z][_a-zA-Z0-9]*

changewordを使えばこの正規表現を変更できます。 たとえば数字が詰まったファイルに置換をかけたい場合など、 m4の字句構成規則を緩めると便利なときもあるでしょう。

     changeword(`[_a-zA-Z0-9]+')
     define(1, 0)
     ⇒1

字句構成規則を厳しくすると 組み込みマクロのうちいくつかが使えなくなってしまうことが多いので、 緩める場合ほど便利にはなりません。 次の例のように、間違って組み込みマクロを呼んでしまうのを避けるために 使うことはできるでしょう。

     define(`_indir', defn(`indir'))
     changeword(`_[_a-zA-Z0-9]*')
     esyscmd(foo)
     _indir(`esyscmd', `ls')

m4は単語を一文字ずつ組み立てていくので、 changewordに渡すことができる正規表現には制限があります。 それは、もし指定した正規表現が‘foo’を受理するのなら その正規表現は‘f’と‘fo’も受理するものでなければならないというものです。

changewordには、もう一つ機能があります。 指定した正規表現の中にカッコ\( \)でくくられた部分表現が1つ以上存在する 場合、最初のカッコでくくられた部分表現の外側にあるテキストが、 シンボルを表引きする前に捨てられます。

     changecom(`/*', `*/')
     changeword(`#\([_a-zA-Z0-9]*\)')
     #esyscmd(ls)

こうすると、m4はすべてのマクロの呼び出しの先頭に ‘#’記号を必要とするようになるので、 m4でシェルスクリプトを処理するときに shiftコマンドがm4に飲み込まれてしまわないようにできます。 また種々の一般的な単語を失うことなくプレーンテキストを 処理できるようになります。

m4のマクロ置換はテキストに基づいていますが、 TeXのものはトークンに基づいています。 changewordによって、この違いを浮き彫りにすることができます。 たとえば次の例は同じアイデアをTeXとm4で表現したものです。 初めはTeX バージョンからです。

     \def\a{\message{Hello}}
     \catcode`\@=0
     \catcode`\\=12
     @a
     
     
     
     

つぎにm4バージョンです。

     define(a, `errprint(`Hello')')
     changeword(`@\([_a-zA-Z0-9]*\)')
     @a
     
     
     

TeXの例において、最初の行はマクロaが‘Hello’メッセージを 表示するように定義しています。 2行目は<\>の代わりに<@>をエスケープ文字として使えるように 定義しています。 3行目は<\>をエスケープ文字ではなく通常の表示可能文字として 定義しています。 4行目はマクロaを呼び出しています。 したがって、このファイルに対してTeXを走らせると ‘Hello’メッセージを表示します。

m4の例をm4に与えると‘errprint(Hello)’を表示します。 この理由はTeXはマクロが定義されたときにマクロ定義の字句解析 を行うのに対し、m4は単純にテキストを保存しておき、 字句解析は実際にマクロが使われるまで後回しにするからです。

changewordを使用すると、 m4の速度が7倍ほど遅くなることに注意してください。