"parser" — Python 解析木にアクセスする
**************************************

"parser" モジュールは Python の内部パーサとバイトコード・コンパイラへ
のインターフェイスを提供します。このインターフェイスの第一の目的は、
Python コードから Python の式の解析木を編集したり、これから実行可能な
コードを作成したりできるようにすることです。これは任意の Python コード
の断片を文字列として構文解析や変更を行うより良い方法です。なぜなら、構
文解析がアプリケーションを作成するコードと同じ方法で実行されるからです
。その上、高速です。

注釈: Python 2.5 以降、抽象構文木 (AST) の生成・コンパイルの段階に割
  り込む には "ast" モジュールを使うのがずっとお手軽です。The "parser"
  module exports the names documented here also with 「st」 replaced
  by 「ast 」; this is a legacy from the time when there was no other
  AST and has nothing to do with the AST found in Python 2.5.  This is
  also the reason for the functions』 keyword arguments being called
  *ast*, not *st*. The 「ast」 functions have been removed in Python
  3.

このモジュールについて注意すべきことが少しあります。それは作成したデー
タ構造を利用するために重要なことです。この文書は Python コードの解析木
を編集するためのチュートリアルではありませんが、 "parser" モジュールを
使った例をいくつか示しています。

もっとも重要なことは、内部パーサが処理する Python の文法についてよく理
解しておく必要があるということです。言語の文法に関する完全な情報につい
ては、 Python 言語リファレンス を参照してください。標準の Python ディ
ストリビューションに含まれるファイル "Grammar/Grammar" の中で定義され
ている文法仕様から、パーサ自身は作成されています。このモジュールが作成
する ST オブジェクトの中に格納される解析木は、下で説明する "expr()" ま
たは "suite()" 関数によって作られるときに内部パーサから実際に出力され
るものです。 "sequence2st()" が作る ST オブジェクトは忠実にこれらの構
造をシミュレートしています。言語の形式文法が改訂されるために、 「正し
い」 と考えられるシーケンスの値が Python のあるバージョンから別のバー
ジョンで変化することがあるということに注意してください。しかし、
Python のあるバージョンから別のバージョンへテキストのソースのままコー
ドを移せば、目的のバージョンで正しい解析木を常に作成できます。ただし、
インタープリタの古いバージョンへ移行する際に、最近の言語コンストラクト
をサポートしていないことがあるという制限だけがあります。ソースコードが
常に前方互換性があるのに対して、一般的に解析木はあるバージョンから別の
バージョンへの互換性がありません。

"st2list()" または "st2tuple()" から返されるシーケンスのそれぞれの要素
は単純な形式です。文法の非終端要素を表すシーケンスは常に一より大きい長
さを持ちます。最初の要素は文法の生成規則を識別する整数です。これらの整
数は C ヘッダファイル "Include/graminit.h" と Python モジュール
"symbol" の中の特定のシンボル名です。シーケンスに付け加えられている各
要素は、入力文字列の中で認識されたままの形で生成規則の構成要素を表して
います: これらは常に親と同じ形式を持つシーケンスです。この構造の注意す
べき重要な側面は、 "if_stmt" の中のキーワード "if" のような親ノードの
型を識別するために使われるキーワードがいかなる特別な扱いもなくノードツ
リーに含まれているということです。例えば、 "if" キーワードはタプル
"(1, 'if')" と表されます。ここで、 "1" は、ユーザが定義した変数名と関
数名を含むすべての "NAME" トークンに対応する数値です。行番号情報が必要
なときに返される別の形式では、同じトークンが "(1, 'if', 12)" のように
表されます。ここでは、 "12" が終端記号の見つかった行番号を表しています
。

終端要素は同じ方法で表現されますが、子の要素や識別されたソーステキスト
の追加は全くありません。上記の "if" キーワードの例が代表的なものです。
終端記号のいろいろな型は、 C ヘッダファイル "Include/token.h" と
Python モジュール "token" で定義されています。

ST オブジェクトはこのモジュールの機能をサポートするために必要ありませ
んが、三つの目的から提供されています: アプリケーションが複雑な解析木を
処理するコストを償却するため、Python のリストやタプル表現に比べてメモ
リ空間を保全する解析木表現を提供するため、解析木を操作する追加モジュー
ルを C で作ることを簡単にするため。ST オブジェクトを使っていることを隠
すために、簡単な 「ラッパー」 クラスを Python で作ることができます。

"parser" モジュールは二、三の別々の目的のために関数を定義しています。
もっとも重要な目的は ST オブジェクトを作ることと、 ST オブジェクトを解
析木とコンパイルされたコードオブジェクトのような他の表現に変換すること
です。しかし、 ST オブジェクトで表現された解析木の型を調べるために役に
立つ関数もあります。

参考:

  "symbol" モジュール
     解析木の内部ノードを表す便利な定数。

  "token" モジュール
     便利な解析木の葉のノードを表す定数とノード値をテストするための関
     数。


ST オブジェクトを作成する
=========================

ST オブジェクトはソースコードあるいは解析木から作られます。ST オブジェ
クトをソースから作るときは、"'eval'" と "'exec'" 形式を作成するために
別々の関数が使われます。

parser.expr(source)

   まるで "compile(source, 'file.py', 'eval')" への入力であるかのよう
   に、 "expr()" 関数はパラメータ *source* を構文解析します。解析が成
   功した場合は、 ST オブジェクトは内部解析木表現を保持するために作成
   されます。そうでなければ、適切な例外を発生させます。

parser.suite(source)

   まるで "compile(source, 'file.py', 'exec')" への入力であるかのよう
   に、 "suite()" 関数はパラメータ *source* を構文解析します。解析が成
   功した場合は、 ST オブジェクトは内部解析木表現を保持するために作成
   されます。そうでなければ、適切な例外を発生させます。

parser.sequence2st(sequence)

   この関数はシーケンスとして表現された解析木を受け取り、可能ならば内
   部表現を作ります。木が Python の文法に合っていることと、すべてのノ
   ードが Python のホストバージョンで有効なノード型であることを確認し
   た場合は、 ST オブジェクトが内部表現から作成されて呼び出し側へ返さ
   れます。内部表現の作成に問題があるならば、あるいは木が正しいと確認
   できないならば、 "ParserError" 例外を発生します。この方法で作られた
   ST オブジェクトが正しくコンパイルできると決めつけない方がよいでしょ
   う。 ST オブジェクトが "compilest()" へ渡されたとき、コンパイルによ
   って送出された通常の例外がまだ発生するかもしれません。これは
   ("MemoryError" 例外のような)構文に関係していない問題を示すのかもし
   れないし、 "del f(0)" を解析した結果のようなコンストラクトが原因で
   あるかもしれません。このようなコンストラクトは Python のパーサを逃
   れますが、バイトコードインタープリタによってチェックされます。

   終端トークンを表すシーケンスは、"(1, 'name')" 形式の二つの要素のリ
   ストか、または "(1, 'name', 56)" 形式の三つの要素のリストです。三番
   目の要素が存在する場合は、有効な行番号だとみなされます。行番号が指
   定されるのは、入力木の終端記号の一部に対してです。

parser.tuple2st(sequence)

   これは "sequence2st()" と同じ関数です。このエントリポイントは後方互
   換性のために維持されています。


ST オブジェクトを変換する
=========================

作成するために使われた入力に関係なく、ST オブジェクトはリスト木または
タプル木として表される解析木へ変換されるか、または実行可能なオブジェク
トへコンパイルされます。解析木は行番号情報を持って、あるいは持たずに抽
出されます。

parser.st2list(ast[, line_info])

   This function accepts an ST object from the caller in *ast* and
   returns a Python list representing the equivalent parse tree.  The
   resulting list representation can be used for inspection or the
   creation of a new parse tree in list form.  This function does not
   fail so long as memory is available to build the list
   representation.  If the parse tree will only be used for
   inspection, "st2tuple()" should be used instead to reduce memory
   consumption and fragmentation.  When the list representation is
   required, this function is significantly faster than retrieving a
   tuple representation and converting that to nested lists.

   *line_info* が真ならば、トークンを表すリストの三番目の要素として行
   番号情報がすべての終端トークンに含まれます。与えられた行番号はトー
   クン *が終わる* 行を指定していることに注意してください。フラグが偽
   または省略された場合は、この情報は省かれます。

parser.st2tuple(ast[, line_info])

   This function accepts an ST object from the caller in *ast* and
   returns a Python tuple representing the equivalent parse tree.
   Other than returning a tuple instead of a list, this function is
   identical to "st2list()".

   *line_info* が真ならば、トークンを表すリストの三番目の要素として行
   番号情報がすべての終端トークンに含まれます。フラグが偽または省略さ
   れた場合は、この情報は省かれます。

parser.compilest(ast, filename='<syntax-tree>')

   The Python byte compiler can be invoked on an ST object to produce
   code objects which can be used as part of an "exec" statement or a
   call to the built-in "eval()" function. This function provides the
   interface to the compiler, passing the internal parse tree from
   *ast* to the parser, using the source file name specified by the
   *filename* parameter. The default value supplied for *filename*
   indicates that the source was an ST object.

   ST オブジェクトをコンパイルすることは、コンパイルに関する例外を引き
   起こすことになるかもしれません。例としては、 "del f(0)" の解析木に
   よって発生させられる "SyntaxError" があります: この文は Python の形
   式文法としては正しいと考えられますが、正しい言語コンストラクトでは
   ありません。この状況に対して発生する "SyntaxError" は、実際には
   Python バイトコンパイラによって通常作り出されます。これが "parser"
   モジュールがこの時点で例外を発生できる理由です。解析木のインスペク
   ションを行うことで、コンパイルが失敗するほとんどの原因をプログラム
   によって診断することができます。


ST オブジェクトに対する問い合わせ
=================================

ST が式または suite として作成されたかどうかをアプリケーションが決定で
きるようにする二つの関数が提供されています。これらの関数のどちらも、
ST が "expr()" または "suite()" を通してソースコードから作られたかどう
か、あるいは、 "sequence2st()" を通して解析木から作られたかどうかを決
定できません。

parser.isexpr(ast)

   When *ast* represents an "'eval'" form, this function returns true,
   otherwise it returns false.  This is useful, since code objects
   normally cannot be queried for this information using existing
   built-in functions.  Note that the code objects created by
   "compilest()" cannot be queried like this either, and are identical
   to those created by the built-in "compile()" function.

parser.issuite(ast)

   This function mirrors "isexpr()" in that it reports whether an ST
   object represents an "'exec'" form, commonly known as a 「suite.」
   It is not safe to assume that this function is equivalent to "not
   isexpr(ast)", as additional syntactic fragments may be supported in
   the future.


例外とエラー処理
================

parser モジュールは例外を一つ定義していますが、Python ランタイム環境の
他の部分が提供する別の組み込み例外を発生させることもあります。各関数が
発生させる例外の情報については、それぞれ関数を参照してください。

exception parser.ParserError

   parser モジュール内部で障害が起きたときに発生する例外。普通の構文解
   析中に発生する組み込みの "SyntaxError" ではなく、一般的に妥当性確認
   が失敗した場合に引き起こされます。例外の引数としては、障害の理由を
   説明する文字列である場合と、 "sequence2st()" へ渡される解析木の中の
   障害を引き起こすシーケンスを含むタプルと説明用の文字列である場合が
   あります。モジュール内の他の関数の呼び出しは単純な文字列値を検出す
   ればよいだけですが、 "sequence2st()" の呼び出しはどちらの例外の型も
   処理できる必要があります。

普通は構文解析とコンパイル処理によって発生する例外を、関数
"compilest()" 、 "expr()" および "suite()" が発生させることに注意して
ください。このような例外には組み込み例外 "MemoryError" 、
"OverflowError" 、 "SyntaxError" および "SystemError" が含まれます。こ
うした場合には、これらの例外が通常その例外に関係する全ての意味を伝えま
す。詳細については、各関数の説明を参照してください。


ST オブジェクト
===============

ST オブジェクト間の順序と等値性の比較がサポートされています。
("pickle" モジュールを使った) ST オブジェクトのピクルス化もサポートさ
れています。

parser.STType

   "expr()" 、 "suite()" と "sequence2st()" が返すオブジェクトの型。

ST オブジェクトは次のメソッドを持っています:

ST.compile([filename])

   "compilest(st, filename)" と同じ。

ST.isexpr()

   "isexpr(st)" と同じ。

ST.issuite()

   "issuite(st)" と同じ。

ST.tolist([line_info])

   Same as "st2list(st, line_info)".

ST.totuple([line_info])

   Same as "st2tuple(st, line_info)".


例: "compile()" のエミュレーション
==================================

たくさんの有用な演算を構文解析とバイトコード生成の間に行うことができま
すが、もっとも単純な演算は何もしないことです。このため、 "parser" モジ
ュールを使って中間データ構造を作ることは次のコードと等価です

   >>> code = compile('a + 5', 'file.py', 'eval')
   >>> a = 5
   >>> eval(code)
   10

"parser" モジュールを使った等価な演算はやや長くなりますが、 ST オブジ
ェクトとして中間内部解析木が維持されるようにします:

   >>> import parser
   >>> st = parser.expr('a + 5')
   >>> code = st.compile('file.py')
   >>> a = 5
   >>> eval(code)
   10

ST とコードオブジェクトの両方が必要なアプリケーションでは、このコード
を簡単に利用できる関数にまとめることができます:

   import parser

   def load_suite(source_string):
       st = parser.suite(source_string)
       return st, st.compile()

   def load_expression(source_string):
       st = parser.expr(source_string)
       return st, st.compile()
