23.2. "shlex" --- 単純な字句解析
********************************

バージョン 1.5.2 で追加.

**ソースコード:** Lib/shlex.py

======================================================================

"shlex" クラスは Unix シェルを思わせる単純な構文に対する字句解析器を簡
単に書けるようにします。このクラスはしばしば、 Python アプリケーション
のための実行制御ファイルのような小規模言語を書く上で便利です。

Python 2.7.3 以前はこのモジュールは今のところ Unicode 入力をサポートし
ていませんでした。

"shlex" モジュールは以下の関数を定義します。

shlex.split(s[, comments[, posix]])

   シェル類似の文法を使って、文字列 *s* を分割します。 *comments* が
   "False" (デフォルト値) の場合、受理した文字列内のコメントを解析しま
   せん ("shlex" インスタンスの "commenters" メンバの値を空文字列にし
   ます)。この関数はデフォルトでは POSIX モードで動作し、 *posix* 引数
   が false の場合は non-POSIX モードで動作します。

   バージョン 2.3 で追加.

   バージョン 2.6 で変更: *posix* パラメータを追加。

   注釈: "split()" 関数は "shlex" クラスのインスタンスを利用するので
     、 *s* に "None" を渡すと標準入力から分割する文字列を読み込みます
     。

"shlex" モジュールは以下のクラスを定義します。

class shlex.shlex([instream[, infile[, posix]]])

   "shlex" クラスとサブクラスのインスタンスは、字句解析器オブジェクト
   です。初期化引数を与えると、どこから文字を読み込むかを指定できます
   。指定先は "read()" メソッドと "readline()" メソッドを持つファイル/
   ストリーム類似オブジェクトか、文字列でなくてはいけません（文字列が
   受理されるようになったのは Python 2.3 以降）。引数が与えられなけれ
   ば、 "sys.stdin" から入力を受け付けます。第 2 引数は、ファイル名を
   表す文字列で、 "infile" メンバの値の初期値を決定します。 *instream*
   引数が省略された場合や、この値が "sys.stdin" である場合、第2引数の
   デフォルト値は "stdin" になります。 *posix* 引数は Python 2.3 で導
   入されました。これは動作モードを定義します。 *posix* が真でない場合
   （デフォルト）、 "shlex" インスタンスは互換モードで動作します。
   POSIX モードで動作中、 "shlex" は、できる限り POSIX シェルの解析規
   則に似せようとします。

参考:

  "ConfigParser" モジュール
     Windows ".ini" ファイルに似た設定ファイルのパーザ。


23.2.1. shlex オブジェクト
==========================

"shlex" インスタンスは以下のメソッドを持っています:

shlex.get_token()

   トークンを一つ返します。トークンが "push_token()" で使ってスタック
   に積まれていた場合、トークンをスタックからポップします。そうでない
   場合、トークンを一つ入力ストリームから読み出します。読み出し即時に
   ファイル終了子に遭遇した場合、 "eof" (非 POSIX モードでは空文字列
   ("''")、POSIX モードでは "None") が返されます。

shlex.push_token(str)

   トークンスタックに引数文字列をスタックします。

shlex.read_token()

   生 (raw) のトークンを読み出します。プッシュバックスタックを無視し、
   かつソースリクエストを解釈しません (通常これは便利なエントリポイン
   トではありません。完全性のためにここで記述されています)。

shlex.sourcehook(filename)

   "shlex" がソースリクエスト (下の "source" を参照してください) を検
   出した際、このメソッドはその後に続くトークンを引数として渡され、フ
   ァイル名と開かれたファイル類似オブジェクトからなるタプルを返すとさ
   れています。

   通常、このメソッドはまず引数から何らかのクオートを剥ぎ取ります。処
   理後の引数が絶対パス名であった場合か、以前に有効になったソースリク
   エストが存在しない場合か、以前のソースが ("sys.stdin" のような) ス
   トリームであった場合、この結果はそのままにされます。そうでない場合
   で、処理後の引数が相対パス名の場合、ソースインクルードスタックにあ
   る直前のファイル名からディレクトリ部分が取り出され、相対パスの前の
   部分に追加されます (この動作は C 言語プリプロセッサにおける
   "#include "file.h"" の扱いと同様です) 。

   これらの操作の結果はファイル名として扱われ、タプルの最初の要素とし
   て返されます。同時にこのファイル名で "open()" を呼び出した結果が二
   つ目の要素になります (注意: インスタンス初期化のときとは引数の並び
   が逆になっています！)

   このフックはディレクトリサーチパスや、ファイル拡張子の追加、その他
   の名前空間に関するハックを実装できるようにするために公開されていま
   す。 'close' フックに対応するものはありませんが、shlex インスタンス
   はソースリクエストされている入力ストリームが EOF を返した時には
   "close()" を呼び出します。

   ソーススタックをより明示的に操作するには、 "push_source()" および
   "pop_source()" メソッドを使ってください。

shlex.push_source(stream[, filename])

   入力ソースストリームを入力スタックにプッシュします。ファイル名引数
   が指定された場合、以後のエラーメッセージ中で利用することができます
   。 "sourcehook()" メソッドが内部で使用しているのと同じメソッドです
   。

   バージョン 2.1 で追加.

shlex.pop_source()

   最後にプッシュされた入力ソースを入力スタックからポップします。字句
   解析器がスタック上の入力ストリームの EOF に到達した際に利用するメソ
   ッドと同じです。

   バージョン 2.1 で追加.

shlex.error_leader([file[, line]])

   このメソッドはエラーメッセージの論述部分を Unix C コンパイラエラー
   ラベルの形式で生成します; この書式は "'"%s", line %d: '" で、 "%s"
   は現在のソースファイル名で置き換えられ、 "%d" は現在の入力行番号で
   置き換えられます (オプションの引数を使ってこれらを上書きすることも
   できます)。

   このやり方は、 "shlex" のユーザに対して、Emacs やその他の Unix ツー
   ル群が解釈できる一般的な書式でのメッセージを生成することを推奨する
   ために提供されています。

"shlex" サブクラスのインスタンスは、字句解析を制御したり、デバッグに使
えるような public なインスタンス変数を持っています:

shlex.commenters

   コメントの開始として認識される文字列です。コメントの開始から行末ま
   でのすべてのキャラクタ文字は無視されます。標準では単に "'#'" が入っ
   ています。

shlex.wordchars

   複数文字からなるトークンを構成するためにバッファに蓄積していくよう
   な文字からなる文字列です。標準では、全ての ASCII 英数字およびアンダ
   ースコアが入っています。

shlex.whitespace

   空白と見なされ、読み飛ばされる文字群です。空白はトークンの境界を作
   ります。標準では、スペース、タブ、改行 (linefeed) および復帰
   (carriage-return) が入っています。

shlex.escape

   エスケープ文字と見なされる文字群です。これは POSIX モードでのみ使わ
   れ、デフォルトでは "'\'" だけが入っています。

   バージョン 2.3 で追加.

shlex.quotes

   文字列引用符と見なされる文字群です。トークンを構成する際、同じクオ
   ートが再び出現するまで文字をバッファに蓄積します (すなわち、異なる
   クオート形式はシェル中で互いに保護し合う関係にあります)。標準では、
   ASCII 単引用符および二重引用符が入っています。

shlex.escapedquotes

   "quotes" のうち、 "escape" で定義されたエスケープ文字を解釈する文字
   群です。これは POSIX モードでのみ使われ、デフォルトでは "'"'" だけ
   が入っています。

   バージョン 2.3 で追加.

shlex.whitespace_split

   この値が "True" であれば、トークンは空白文字でのみで分割されます。
   たとえば "shlex" がシェル引数と同じ方法で、コマンドラインを解析する
   のに便利です。

   バージョン 2.3 で追加.

shlex.infile

   現在の入力ファイル名です。クラスのインスタンス化時に初期設定される
   か、その後のソースリクエストでスタックされます。エラーメッセージを
   構成する際にこの値を調べると便利なことがあります。

shlex.instream

   "shlex" インスタンスが文字を読み出している入力ストリームです。

shlex.source

   このメンバ変数は標準で "None" を取ります。この値に文字列を代入する
   と、その文字列は多くのシェルにおける "source" キーワードに似た、字
   句解析レベルでのインクルード要求として認識されます。すなわち、その
   直後に現れるトークンをファイル名として新たなストリームを開き、その
   ストリームを入力として、EOF に到達するまで読み込まれます。新たなス
   トリームの EOF に到達した時点で "close()" が呼び出され、入力は元の
   入力ストリームに戻されます。ソースリクエストは任意のレベルの深さま
   でスタックしてかまいません。

shlex.debug

   このメンバ変数が数値で、かつ "1" またはそれ以上の値の場合、 "shlex"
   インスタンスは動作に関する冗長な進捗報告を出力します。この出力を使
   いたいなら、モジュールのソースコードを読めば詳細を学ぶことができま
   す。

shlex.lineno

   ソース行番号 (遭遇した改行の数に 1 を加えたもの) です。

shlex.token

   トークンバッファです。例外を捕捉した際にこの値を調べると便利なこと
   があります。

shlex.eof

   ファイルの終端を決定するのに使われるトークンです。非 POSIX モードで
   は空文字列 ("''") 、POSIX モードでは "None" が入ります。

   バージョン 2.3 で追加.


23.2.2. 解析規則
================

非 POSIX モードで動作中の "shlex" は以下の規則に従おうとします。

* ワード内の引用符を認識しない ("Do"Not"Separate" は単一ワード
  "Do"Not"Separate" として解析されます)

* エスケープ文字を認識しない

* 引用符で囲まれた文字列は、引用符内の全ての文字リテラルを保持する

* 閉じ引用符でワードを区切る (""Do"Separate" は、 ""Do"" と
  "Separate" であると解析されます)

* "whitespace_split" が "False" の場合、wordchar、 whitespace または
  quote として宣言されていない全ての文字を、単一の文字トークンとして返
  す。 "True" の場合、 "shlex" は空白文字でのみ単語を区切る。

* 空文字列 ("''") で EOF を送出する

* 引用符に囲んであっても、空文字列を解析しない

POSIX モードで動作中の "shlex" は以下の解析規則に従おうとします。

* 引用符を取り除き、引用符で単語を分解しない (""Do"Not"Separate"" は
  単 一ワード "DoNotSeparate" として解析されます)

* 引用符で囲まれないエスケープ文字群 ("'\'" など) は直後に続く文字の
  リ テラル値を保持する

* "escapedquotes" でない引用符文字 (""'"" など) で囲まれている全ての
  文 字のリテラル値を保持する

* 引用符に囲まれた "escapedquotes" に含まれる文字 ("'"'" など) は、
  "escape" に含まれる文字を除き、全ての文字のリテラル値を保持する。エ
  スケープ文字群は使用中の引用符、または、そのエスケープ文字自身が直後
  にある場合のみ、特殊な機能を保持する。他の場合にはエスケープ文字は普
  通の文字とみなされる。

* "None" で EOF を送出する

* 引用符に囲まれた空文字列 ("''") を許す
