| ページ一覧 | ブログ | twitter |  書式 | 書式(表) |

MyMemoWiki

差分

ナビゲーションに移動 検索に移動
184 バイト追加 、 2020年2月16日 (日) 04:31
編集の要約なし
==[[Python PLY ]] (Pythonによる構文解析)==
[[Python]] |
{{amazon|4774138959}}
===PLY ([[Python ]] Lex-Yacc) ===
*http://www.dabeaz.com/ply/
*[http://www.dabeaz.com/ply/ply.html PLY 3.0 Document]
===概要===
====PLY-3.0 要件====
*[[Python 2、Python ]] 2、[[Python]] 3 互換。ただし、Python2系で、2互換。ただし、[[Python]]2系で、2.4 以降推奨
====紹介====
*Pure Pythonによる、[http://ja.wikipedia.org/wiki/Yacc lex|http://ja.wikipedia.org/wiki/Lex] および [yacc] の実装
*2つのツールは協調して作業を行う
=====lex.py=====
*モジュールは入力されたテキストを 正規表現により定義された字句のコレクションに分解する。[[正規表現]]により定義された字句のコレクションに分解する。
*次の有効なトークンを入力ストリームから返す、token()関数を、外部にインターフェースとして提供する。
=====yacc.py=====
*自由文法として定義された言語の構文を評価する。自由文法として定義された[[言語]]の構文を評価する。*LR で解析を行い、LALR(1) (デフォルト) もしくは SLR アルゴリズムでパースする。[[アルゴリズム]]でパースする。
*lex.py の token()を繰り返し呼び出し、トークンを参照し、文法ルールを呼び出す。
*出力は、大抵、抽象構文木(AST)となる。
# トークンリスト 常に必須
tokens = (
'NUMBERNUMBE[[R]]',
'PLUS',
'MINUS',
'TIMES',
'DIVIDE',
'LPARENLPA[[R]]EN', 'RPAREN[[R]]PA[[R]]EN',
)
# 正規表現による簡単なトークンのルール[[正規表現]]による簡単なトークンのルール
t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_DIVIDE = r'/'
t_LPAREN t_LPA[[R]]EN = r'\(' t_RPAREN t_[[R]]PA[[R]]EN = r'\)'
# 正規表現とアクションコード[[正規表現]]とアクションコード def t_NUMBERt_NUMBE[[R]](t):
r'\d+'
t.value = int(t.value)
=====結果=====
LexToken(NUMBERNUMBE[[R]],3,2,1)
LexToken(PLUS,'+',2,3)
LexToken(NUMBERNUMBE[[R]],4,2,5)
LexToken(TIMES,'*',2,7)
LexToken(NUMBERNUMBE[[R]],10,2,9)
LexToken(PLUS,'+',3,14)
LexToken(MINUS,'-',3,16)
LexToken(NUMBERNUMBE[[R]],20,3,17)
LexToken(TIMES,'*',3,20)
LexToken(NUMBERNUMBE[[R]],2,3,21)
====LexToken====
|-
|value
|語彙 正規表現がマッチした文字列[[正規表現]]がマッチした文字列
|-
|lineno
print "type=%s, value=%s, lineno=%s, lexpos=%s" % (tok.type, tok.value, tok.lineno, tok.lexpos)
=====結果=====
type=NUMBERNUMBE[[R]], value=3, lineno=2, lexpos=1
type=PLUS, value=+, lineno=2, lexpos=3
type=NUMBERNUMBE[[R]], value=4, lineno=2, lexpos=5
type=TIMES, value=*, lineno=2, lexpos=7
type=NUMBERNUMBE[[R]], value=10, lineno=2, lexpos=9
type=PLUS, value=+, lineno=3, lexpos=14
type=MINUS, value=-, lineno=3, lexpos=16
type=NUMBERNUMBE[[R]], value=20, lineno=3, lexpos=17
type=TIMES, value=*, lineno=3, lexpos=20
type=NUMBERNUMBE[[R]], value=2, lineno=3, lexpos=21
====トークンリスト====
*yacc.py にて、終端を特定するのにも使われる。
====トークンの仕様====
*トークンの仕様は、正規表現によって定められる。トークンの仕様は、[[正規表現]]によって定められる。
*これらのルールは、特別なプレフィックス t_ で宣言する。
*正規表現による、簡単なトークンの例 [[正規表現]]による、簡単なトークンの例
t_PLUS = r'\+'
*アクションを実行する必要がある場合、関数にできる(文字列を整数に変換する例)
*関数を使う場合、正規表現ルールは、ドキュメント文字列で指定する関数を使う場合、[[正規表現]]ルールは、ドキュメント文字列で指定する
*関数は常に LexToken を1つ引数としてとる
def t_NUMBERt_NUMBE[[R]](t):
r'\d+'
t.value = int(t.value)
====予約語の取り扱い====
*予約語を取り扱うには、マッチさせる特別な識別子を1つ用意し、以下のようにすることで、正規表現の記述を大幅に削減できる予約語を取り扱うには、マッチさせる特別な識別子を1つ用意し、以下のようにすることで、[[正規表現]]の記述を大幅に削減できる
# 予約語
return t
<blockquote>予約語に対して、以下のようにルールを記述できる</blockquote>
t_FOR t_FO[[R]] = r'for' t_PRINT t_P[[R]]INT = r'print'
これらのルールは、"forget" or "printed" など、予約語を含む語彙にも一致してしまう。
====トークンの値====
*lexからトークンが戻されるとき、トークンは value属性を持ちます
*通常、value属性はマッチしたテキストですが、任意のPythonオブジェクトと結びつけることができます通常、value属性はマッチしたテキストですが、任意の[[Python]]オブジェクトと結びつけることができます
*たとえば、識別子名と情報をソートされたシンボルテーブルから得たい場合、以下のようにします。
def t_ID(t):
====トークンの破棄====
*コメントのような破棄するトークンは、値を返さないことで定義する。
def t_COMMENTt_[[COM]]MENT(t):
r'\#.*'
pass
# 値を返さないと、トークンは破棄される
*"ignore_" プレフィックスを利用してもよい
t_ignore_COMMENT t_ignore_[[COM]]MENT = r'\#.*'
====行番号と位置情報====
*デフォルトでは、lex.pyは行番号について関知しない
====lexer を構築して利用する====
*lexer(字句解析機)を構築するには、lex.lex()関数を利用する
*[[Python ]] のリフレクション(またはイントロスペクション) を使って、正規表現のルールを lexerの呼び出しと構築コンテキストの外側から読み込む。
*lexerが作られると、2つのメソッドで制御できるようになる
=====lexer.input(data)=====
def p_factor_num(p):
'factor : NUMBERNUMBE[[R]]'
p[0] = p[1]
def p_factor_expr(p):
'factor : LPAREN LPA[[R]]EN expression RPAREN[[R]]PA[[R]]EN'
p[0] = p[2]
[[File:1058_yacc_test01.jpg]]
=====説明=====
*このサンプルでは、すべての構文ルールがPythonの関数によって定義されており、その関数のドキュメント文字列は適切な文脈自由の構文の仕様を含んでいる。このサンプルでは、すべての構文ルールが[[Python]]の関数によって定義されており、その関数のドキュメント文字列は適切な文脈自由の構文の仕様を含んでいる。
*関数本体のステートメントは構文の意味があらわすアクションをルールとして実装している。
*それぞれの関数はひとつの引数 p を受け取る。
p[0] = p[1] + p[3]
6.2 Combining Grammar Rule [[R]]ule Functions
====文法ルールを合成する====

案内メニュー