LoginSignup
12
10

More than 5 years have passed since last update.

TeXの改行とスペース

Last updated at Posted at 2014-01-07

TeXの処理系は他のプログラム言語とはスペースや改行の扱い方が異なるらしいが、それをよく理解しないままTeXのマクロなどを記述していた。そこで改めてTeXが改行やスペースをどのように扱うのかについて、TeX by TopicのChapter1, 2あたりを読むなどして分かったこと書くことにする。
TeX by Topicは和文組版でよく用いられるpTeX系の内部に関しては述べられていない。そこで和文に関してはLuaTeX-jaのドキュメントを参考にした。

改行とスペース

そもそもどのようなことを問題としているのかというだが、例えば次のようなものを何かTeXの処理系でコンパイルすることを考える。

This is a pen.
I like it.

スクリーンショット 2014-01-07 16.43.36.png

よく見ると、一行目の pen. と二行目の I like の間にあった改行が、スペースへ化けたと分かる。
また次のように、

This is         a         pen.

などと、大量のスペースを注入したとしても、

スクリーンショット 2014-01-04 17.43.19.png

という感じで、一部のスペースは無視される。
このように、TeXは記述したスペースや改行が全て無視されるというわけでもなければ、全て成果物に表われるというわけでもない。

TeXの入力処理

TeX by TopicではTeXの入力処理は 有限オートマトン であるとしている。ただしTeX by Topicは和文組版について全く述べられていないので、ここではLuaTeX-jaのドキュメントを参考に、pTeX系のオートマトンを述べることにした。

アルファベット

TeXは入力される文字を一文字ずつ、カテゴリーコードという文字に割り当てられた数字によって分類する。カテゴリーコードについてはTeX Wikiなどに詳細(?)がある。

ただ、TeXの状態遷移を表わすのであれば、とりあえず次のように分類すればことが足りると思う。なのでアルファベット(記号)を次のようにする。

  • \:バックスラッシュ
  •  :半角スペース
  • \n:改行記号
  • %:コメント文字
  • C:半角英字(a-z, A-Z)
  • G:グループの開始と終了({, }
  • O\,  , \n, %以外の半角文字
  • J:日本語文字(あ、イ、宇……)

5つの状態

pTeXは次の5つの状態を持つ。(TeX by Topicでは状態 CS は書かれていないが、こちらの説明がやりやすいと思うので追加した。)

状態 N:新規行
TeXが始まった時、または何らかの状態から、\nによって新しい行が始まった時の状態
状態 K:和文の行中
何らかの状態から、日本語文字Jが出現した時の状態(pTeX系にのみ存在)
状態 M:英文の行中
何らかの状態から文字C, Oが出現した時の状態
状態 S:スキップスペース
何らかの状態からスペース の出現などによって、以降のスペースを読み飛ばす時の状態
状態 CS:コントロールシークエンス
何らかの状態から\の出現によって、コントロールシークエンス(マクロなど)を構成する時の状態

TeXソースコードにおけるスペースや改行は、このオートマトンの状態によって処理が変わる。

状態遷移と改行などの扱い

各状態と、その状態によって改行やスペースがどのように扱われるのか述べる。

状態 N :新規行

TeXはこの状態から始まり、新しい行へ入った際にこの状態へ遷移する。この状態では、

  • 全てのスペース が無視される
  • 改行\nを行うと改段落\parが挿入される

状態 K :和文の行中

何か和文文字Jが出現した際にこの状態へ遷移する。この状態では、

  • スペース が出現すると、スペースを表示して状態 S へ遷移する
  • 改行\nがあると、何も出力せずに状態 N へ遷移する

つまり、スペースは表示され、改行は状態を遷移させるだけで表示に影響は与えない。例えば次のような文章を与える。

スペース の        テスト
改行したが、前の行に書いた文字との間に
スペースはない。

スクリーンショット 2014-01-05 17.12.23.png

最初の行はよく見ると「の」の前後にスペースが挿入されているが、たくさんスペースを連続して書いても、状態 S へ遷移してスペースを読み飛ばすので、「の」と「テスト」の間に大量の隙間が出来ることはない。
また、状態 K においてはグループ文字Gが表われても状態 M へ遷移しない。なので、

グループを開始させて改行し{
直後にグループを閉じて}
さらに改行した。

スクリーンショット 2014-01-05 20.12.09.png

としても、改行の部分にスペースが挿入されない。

状態 M :英文の行中

英字Cの他に、例えば{, }といったグループに関する文字や、数字などによって状態 M へ遷移する。
"This is a pen."の例で挙げたように、英文の場合は和文と異なり改行によってスペースが挿入される。

  • スペース が出現すると、スペースを表示して状態 S へ遷移する
  • 改行\nがあると、スペースを表示して状態 N へ遷移する

従って、例えば次のような記述では、

This is a pen,{
I like it}
very much.

スクリーンショット 2014-01-05 20.18.14.png

などと、改行の度にスペースが挿入される。

ただこの時にコメント文字%が出現して次のようになった場合を考える。

This is a pen.%
I like it.

スクリーンショット 2014-01-06 1.09.04.png

このように%が出現した後改行した場合、その後に改行\nがあったとしてもコメントアウトされているものとされる。従って改行によるスペースの挿入も行われず、状態 M のまま次の行を処理する。従ってスペースの挿入などが行われない。

状態 S :スキップスペース

次のような時に状態 S へ遷移する。

  • スペース の後
  • 状態 CS の後(一部例外あり)

この状態の時、スペースと改行は次のようになる。

  • スペース を無視する(何も表示せず、状態もそのまま)
  • 改行\nがあると、何もせず状態 N へ遷移する

つまりこの状態においては、連続するスペースが全て無視される。

状態 CS :コントロールシークエンス

文字\の後にこの状態へと遷移する。TeX by Topicにはコントロールシークエンス( control sequence )として、次の2つを全てまとめたものであると述べている。

コントロールシンボル(control symbol
\の後に、英字以外の一字,%などが続くもの
コントロールワード(control word
\の後に、英字Cあるいは日本語文字Jが一字以上続くもの

つまり、\smallといったものはコントロールワードであり、\%\,がコントロールシンボルとなる。状態 CS はこの二つで動作が異なる。

コントロールシンボル

\の後にC以外のものが続くもの場合は、その一字を読んだ後状態 M へ遷移する。例えば次のようなものを考える。

コントロールシンボル\%
の直後に改行を入れる。

スクリーンショット 2014-01-05 20.49.34.png

このように%記号の直後に半角スペースが挿入されていることから、状態 M へ遷移したことが分かる。(分かりやすくするためスペースの部分に色を付けた。)

ただし例外があり、\ \+半角スペース、コントロールスペースと呼ばれる)の場合は状態 S へ遷移する。

コントロールワード

コントロールワードの場合は、\に続く英字Cあるいは日本語文字Jを全て読んだ後に状態 S へ遷移する。従って、

  • コントロールワードの後にあるスペースは無視される
  • コントロールワードの直後にある改行は何も表示せず、状態を N へ遷移させる

となる。例えば次のようにコントロールワードの直後にいくつかのスペースを挿入する。

\def\hoge{ほげ}

コントロールワード\hoge         % 大量のスペース
の直後に大量のスペースを入れる。

スクリーンショット 2014-01-05 21.00.12.png

このように\hogeの後に入れたスペースは表示されない。

引数を取るコントロールワード

コントロールワードの中には、次のように引数を取るものがある。

\def\hoge#1{(#1)が吸い込まれた}

\hoge       の直後にはスペースが入っている。

スクリーンショット 2014-01-05 23.36.02.png

図の通り、\hogeの直後にある大量のスペースは状態 CS\hogeを処理した直後に状態 S へと遷移し、そこでスペースは消滅した。その後に引数の処理を行ったためスペースの直後にある「の」が引数となった。
また、境界なしの場合は引数と引数の間にある全てのスペースや改行が無視される。

ただし、コントロールワードが引数を取る際は、コントロールワードがどのように引数を取るかによって、スペースなどの処理が分かれる。

境界なし引数(Undelimited parameters)
\def\hoge#1#2{...}のように、引数と引数の間に境界を明示しない
境界あり引数(Delimited parameters)
\def\hoge#1, #2{...}のように、引数と引数の間に境界となる文字列を明示する

境界なし引数

まずは境界なし引数の場合は、コントロールワードの直後にあるスペースと改行が状態 S によって無視され、その後引数の確保になる。

\def\hoge#1#2{(#1,#2)が吸い込まれた}

\hoge
  A
  B
という感じ。

スクリーンショット 2014-01-07 16.15.50.png

このように、 "A"の後にある改行や状態 M による改行で挿入されるスペースは無視されているが、"B"の後にある改行(状態 M における改行で挿入されるスペース)は残っている。つまり、引数と引数の間に境界がない場合、引数の間にあるスペースや改行は無視される。

境界あり引数

ここで、境界となる文字列を明示すると次のようになる。

\def\hoge#1,#2and#3{(#1,#2,#3)が吸い込まれた}

\hoge A , B and C
という感じ。

スクリーンショット 2014-01-07 16.19.12.png

このように境界文字列で挟まれた部分についてはスペースなどが無視されない。(ただ、スペースによって状態が S へ遷移するので連続するスペースは一つ分になるなどする)

まとめ

結論としては、

  • 状態 M の時に改行するとスペースが挿入される可能性がある

ということになる。なので、

  • 和文(状態 K )の改行は無視される
  • コントロールワードの直後にあるスペースや改行は無視される
  • コントロールワードの引数は、境界を明示しているのかどうかで振る舞いが違うが、場合によっては改行によるスペースなどが入る可能性がある
12
10
0

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
12
10