# 5 `tokenize` -- Pythonソースのためのトークナイザ

`tokenize`モジュールでは、Python で実装された Python ソースコードの字句解析器を提供します。さらに、このモジュールの 字句解析器はコメントもトークンとして返します。このため、この モジュールはスクリーン上で表示する際の色付け機能 (colorizers) を含む ``清書出力器 (pretty-printer)'' を実装する上で便利です。

第一のエントリポイントはジェネレータです:

`generate_tokens`( | readline)

  `generate_tokens()` ジェネレータは一つの引数readline を必要とします。この引数は呼び出し可能オブジェクトで、組み込みファイル オブジェクトにおける `readline()` メソッドと同じインタフェース を提供していなければなりません ( 3.9 節を参照して ください)。この関数は呼び出しのたびに入力内の一行を文字列で返さなければ なりません。

  ジェネレータは 5 要素のタプルを返し、タプルは以下のメンバ: トークン型; トークン文字列; ソースコード中でトークンが始まる行と列を示す 整数の2要素のタプル`(srow, scol)`; ソースコード中で トークンが終わる行と列を示す整数の2要素のタプル `(srow, scol)`; そして、トークンが見つかった行、から なります。渡される行は論理行です; 連続する行は一行に含められ ます。 バージョン 2.2 で 新たに追加 された仕様です。

後方互換性のために古いエントリポイントが残されています:

`tokenize`( | readline[, tokeneater])

  `tokenize()`関数は二つのパラメータを取ります: 一つは入力ストリームを表し、もう一つは`tokenize()`のための 出力メカニズムを与えます。

  最初のパラメータ、readline は、組み込みファイルオブジェクト の`readline()`メソッドと同じインタフェイスを提供する呼び出し 可能オブジェクトでなければなりません ( 3.9 節を参照)。 この関数は呼び出しのたびに入力内の一行を文字列で返さなければ なりません。 もしくは、readline を呼び出し可能オブジェクトで `StopIteration` を送出することで補完を知らせるものと することもできます。 バージョン 2.5 で 変更 された仕様: `StopIteration` サポートの追加

  二番目のパラメータtokeneaterも呼び出し可能オブジェクトで なければなりません。この関数は各トークンに対して一度だけ呼び出され、 `generate_tokens()` が生成するタプルに対応する 5 つの引数 をとります。

`token` モジュールの全ての定数は`tokenize` でも 公開されており、これに加え、以下の二つのトークン値が `tokenize()` の tokeneater 関数に渡される可能性があります:

`COMMENT`
  コメントであることを表すために使われるトークン値です。

`NL`
  終わりではない改行を表すために使われるトークン値。NEWLINEトークンは Pythonコードの論理行の終わりを表します。NLトークンはコードの論理行が 複数の物理行にわたって続いているときに作られます。

もう一つの関数がトークン化プロセスを逆転するために提供されています。 これは、スクリプトを字句解析し、トークンのストリームに変更を加え、変更された スクリプトを書き戻すようなツールを作成する際に便利です。

`untokenize`( | iterable)

  トークンの列を Python ソースコードに変換します。iterable は少なくとも 二つの要素、トークン型およびトークン文字列、からなるシーケンスを返します。 その他のシーケンスの要素は無視されます。

  再構築されたスクリプトは一つの文字列として返されます。得られる結果はもう一度 字句解析すると入力と一致することが保証されるので、変換がロスレスであり ラウンドトリップできることは間違いありません。この保証はトークン型および トークン文字列に対してのものでトークン間のスペース(コラム位置)のようなものは 変わることがあり得ます。 バージョン 2.5 で 新たに追加 された仕様です。

スクリプト書き換えの例で、浮動小数点数リテラルを Decimal オブジェクトに 変換します:

    def decistmt(s):
        """Substitute Decimals for floats in a string of statements.

        >>> from decimal import Decimal
        >>> s = 'print +21.3e-5*-.1234/81.7'
        >>> decistmt(s)
        "print +Decimal ('21.3e-5')*-Decimal ('.1234')/Decimal ('81.7')"

        >>> exec(s)
        -3.21716034272e-007
        >>> exec(decistmt(s))
        -3.217160342717258261933904529E-7

        """
        result = []
        g = generate_tokens(StringIO(s).readline)   # tokenize the string
        for toknum, tokval, _, _, _  in g:
            if toknum == NUMBER and '.' in tokval:  # replace NUMBER tokens
                result.extend([
                    (NAME, 'Decimal'),
                    (OP, '('),
                    (STRING, repr(tokval)),
                    (OP, ')')
                ])
            else:
                result.append((toknum, tokval))
        return untokenize(result)