Python/スクリプト解析を読む
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
[[Pythonを読む]]
#contents
*PyParser_ParseFileObject (Parser/parsetok.c) [#l2c3f89c]
ファイルを指定したときに呼び出されるPyParser_ParseFileObj...
#code(C){{
node *
PyParser_ParseFileObject(FILE *fp, PyObject *filename,
const char *enc, grammar *g, int...
const char *ps1, const char *ps2,
perrdetail *err_ret, int *flags)
{
struct tok_state *tok;
if (initerr(err_ret, filename) < 0)
return NULL;
if ((tok = PyTokenizer_FromFile(fp, enc, ps1, ps2)) =...
err_ret->error = E_NOMEM;
return NULL;
}
#ifndef PGEN
Py_INCREF(err_ret->filename);
tok->filename = err_ret->filename;
#endif
return parsetok(tok, g, start, err_ret, flags);
}
}}
*parsetok (Parser/parsetok.c) [#rdce3b52]
parsetok関数は長いです。エラー処理をばさっと削ると以下の...
#code(C){{
static node *
parsetok(struct tok_state *tok, grammar *g, int start, pe...
int *flags)
{
parser_state *ps;
node *n;
ps = PyParser_New(g, start);
for (;;) {
char *a, *b;
int type;
size_t len;
char *str;
int col_offset;
type = PyTokenizer_Get(tok, &a, &b);
len = b - a; /* XXX this may compute NULL - NULL */
str = (char *) PyObject_MALLOC(len + 1);
if (len > 0)
strncpy(str, a, len);
str[len] = '\0';
if (a >= tok->line_start)
col_offset = Py_SAFE_DOWNCAST(a - tok->line_s...
Py_intptr_t, in...
else
col_offset = -1;
if ((err_ret->error =
PyParser_AddToken(ps, (int)type, str,
tok->lineno, col_offset,
&(err_ret->expected))) != ...
if (err_ret->error != E_DONE) {
PyObject_FREE(str);
err_ret->token = type;
}
break;
}
}
if (err_ret->error == E_DONE) {
n = ps->p_tree;
ps->p_tree = NULL;
}
PyParser_Delete(ps);
done:
PyTokenizer_Free(tok);
return n;
}
}}
パーサを作り、トーカナイザからトークンを取得して追加、終...
**PyParser_New (Parser/parser.c) [#bbe749ea]
#code(C){{
PyParser_New(grammar *g, int start)
{
parser_state *ps;
if (!g->g_accel)
PyGrammar_AddAccelerators(g);
ps = (parser_state *)PyMem_MALLOC(sizeof(parser_state...
ps->p_grammar = g;
ps->p_tree = PyNode_New(start);
s_reset(&ps->p_stack);
(void) s_push(&ps->p_stack, PyGrammar_FindDFA(g, star...
return ps;
}
}}
DFAとあります。つまり、スクリプトからノードに変換するには...
grammer、その実体は_PyParser_GrammarはPython/graminit.cに...
**PyParser_AddToken (Parser/parser.c) [#be144651]
PyParser_AddTokenではトークンと現在の状態(どの文法要素を...
-非終端記号の場合はpush
-終端記号に来たらshift
-受理状態のままの場合はpopしてスタックが空になったらOK
という構文解析の基本が行われていると思っておけばよいです。
pushでは現在のスタックトップのノードに子ノードを追加して...
#code(C){{
static int
push(stack *s, int type, dfa *d, int newstate, int lineno...
{
int err;
node *n;
n = s->s_top->s_parent;
assert(!s_empty(s));
err = PyNode_AddChild(n, type, (char *)NULL, lineno, ...
if (err)
return err;
s->s_top->s_state = newstate;
return s_push(s, d, CHILD(n, NCH(n)-1));
}
}}
shiftではpushは行われないので現在のスタックトップにノード...
#code(C){{
static int
shift(stack *s, int type, char *str, int newstate, int li...
{
int err;
assert(!s_empty(s));
err = PyNode_AddChild(s->s_top->s_parent, type, str, ...
if (err)
return err;
s->s_top->s_state = newstate;
return 0;
}
}}
*構文解析してみる [#i3c050f6]
静的にコードを眺めるだけだとよくわからないので例によって...
#code(Python){{
[n for n in range(10) if n * n > 10]
}}
次のような感じになるはずです。
single_input
simple_stmt
small_stmt
expr_stmt
testlist_star_expr
test
or_test
and_test
not_test
comparison
expr
xor_expr
and_expr
shift_expr
arith_expr
term
factor
power
atom_expr
atom
testlist_comp
test
or_test
and_test
not_test
compa...
expr
x...
...
...
...
...
...
...
...
...
...
comp_for
exprlist
expr
xor_expr
and_e...
shi...
a...
...
...
...
...
...
...
or_test
and_test
not_test
compa...
expr
x...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
comp_iter
comp_if
test_no...
or_test
and...
n...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
NEWLINE
長いわ!演算子の優先順位の都合でかなり深いノードになって...
*おわりに [#j1b37ae4]
というわけでスクリプト解析まで来ました。シンプルなスクリ...
終了行:
[[Pythonを読む]]
#contents
*PyParser_ParseFileObject (Parser/parsetok.c) [#l2c3f89c]
ファイルを指定したときに呼び出されるPyParser_ParseFileObj...
#code(C){{
node *
PyParser_ParseFileObject(FILE *fp, PyObject *filename,
const char *enc, grammar *g, int...
const char *ps1, const char *ps2,
perrdetail *err_ret, int *flags)
{
struct tok_state *tok;
if (initerr(err_ret, filename) < 0)
return NULL;
if ((tok = PyTokenizer_FromFile(fp, enc, ps1, ps2)) =...
err_ret->error = E_NOMEM;
return NULL;
}
#ifndef PGEN
Py_INCREF(err_ret->filename);
tok->filename = err_ret->filename;
#endif
return parsetok(tok, g, start, err_ret, flags);
}
}}
*parsetok (Parser/parsetok.c) [#rdce3b52]
parsetok関数は長いです。エラー処理をばさっと削ると以下の...
#code(C){{
static node *
parsetok(struct tok_state *tok, grammar *g, int start, pe...
int *flags)
{
parser_state *ps;
node *n;
ps = PyParser_New(g, start);
for (;;) {
char *a, *b;
int type;
size_t len;
char *str;
int col_offset;
type = PyTokenizer_Get(tok, &a, &b);
len = b - a; /* XXX this may compute NULL - NULL */
str = (char *) PyObject_MALLOC(len + 1);
if (len > 0)
strncpy(str, a, len);
str[len] = '\0';
if (a >= tok->line_start)
col_offset = Py_SAFE_DOWNCAST(a - tok->line_s...
Py_intptr_t, in...
else
col_offset = -1;
if ((err_ret->error =
PyParser_AddToken(ps, (int)type, str,
tok->lineno, col_offset,
&(err_ret->expected))) != ...
if (err_ret->error != E_DONE) {
PyObject_FREE(str);
err_ret->token = type;
}
break;
}
}
if (err_ret->error == E_DONE) {
n = ps->p_tree;
ps->p_tree = NULL;
}
PyParser_Delete(ps);
done:
PyTokenizer_Free(tok);
return n;
}
}}
パーサを作り、トーカナイザからトークンを取得して追加、終...
**PyParser_New (Parser/parser.c) [#bbe749ea]
#code(C){{
PyParser_New(grammar *g, int start)
{
parser_state *ps;
if (!g->g_accel)
PyGrammar_AddAccelerators(g);
ps = (parser_state *)PyMem_MALLOC(sizeof(parser_state...
ps->p_grammar = g;
ps->p_tree = PyNode_New(start);
s_reset(&ps->p_stack);
(void) s_push(&ps->p_stack, PyGrammar_FindDFA(g, star...
return ps;
}
}}
DFAとあります。つまり、スクリプトからノードに変換するには...
grammer、その実体は_PyParser_GrammarはPython/graminit.cに...
**PyParser_AddToken (Parser/parser.c) [#be144651]
PyParser_AddTokenではトークンと現在の状態(どの文法要素を...
-非終端記号の場合はpush
-終端記号に来たらshift
-受理状態のままの場合はpopしてスタックが空になったらOK
という構文解析の基本が行われていると思っておけばよいです。
pushでは現在のスタックトップのノードに子ノードを追加して...
#code(C){{
static int
push(stack *s, int type, dfa *d, int newstate, int lineno...
{
int err;
node *n;
n = s->s_top->s_parent;
assert(!s_empty(s));
err = PyNode_AddChild(n, type, (char *)NULL, lineno, ...
if (err)
return err;
s->s_top->s_state = newstate;
return s_push(s, d, CHILD(n, NCH(n)-1));
}
}}
shiftではpushは行われないので現在のスタックトップにノード...
#code(C){{
static int
shift(stack *s, int type, char *str, int newstate, int li...
{
int err;
assert(!s_empty(s));
err = PyNode_AddChild(s->s_top->s_parent, type, str, ...
if (err)
return err;
s->s_top->s_state = newstate;
return 0;
}
}}
*構文解析してみる [#i3c050f6]
静的にコードを眺めるだけだとよくわからないので例によって...
#code(Python){{
[n for n in range(10) if n * n > 10]
}}
次のような感じになるはずです。
single_input
simple_stmt
small_stmt
expr_stmt
testlist_star_expr
test
or_test
and_test
not_test
comparison
expr
xor_expr
and_expr
shift_expr
arith_expr
term
factor
power
atom_expr
atom
testlist_comp
test
or_test
and_test
not_test
compa...
expr
x...
...
...
...
...
...
...
...
...
...
comp_for
exprlist
expr
xor_expr
and_e...
shi...
a...
...
...
...
...
...
...
or_test
and_test
not_test
compa...
expr
x...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
comp_iter
comp_if
test_no...
or_test
and...
n...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
NEWLINE
長いわ!演算子の優先順位の都合でかなり深いノードになって...
*おわりに [#j1b37ae4]
というわけでスクリプト解析まで来ました。シンプルなスクリ...
ページ名: