ホーム>source

私はPythonのソースコードについて少し勉強していて、文法の変更を実践することにしたので、バージョン3.7のソースコードをダウンロードしました。

私はPEP 0306のガイドラインに従っています:
https://www.python.org/dev/peps/pep-0306/

Hackernoonの例から:
https://hackernoon.com/modifying-the-python-language-in-7-minutes-b94b0a99ce14

このアイデアは、デコレータの構文の改善から生まれました(これは単なる研究の一例であり、同じことを行う他の方法があることは既に知っています)。

@test
def mydef (self):
    pass

Grammar/Grammarファイルの行に従って、完全に機能します。

decorated: decorators (classdef | funcdef | async_funcdef)

ここでの目標は、例から始めて、宣言を受け入れるようにデコレーターを変更することです。

@test
id: int = 1

文法を分析すると、次のようなannassignが見つかりました。

annassign: ':' test ['=' test]
# or even use small_stmt

トークンを表すid:int = 1、トークンを次のように変更しました:

decorated: decorators (classdef | funcdef | async_funcdef | annassign)

(PEP 0306に続いて)行ったことast.c そして識別されたast_for_decorated メソッド、およびコードの取得:

[...]
assert(TYPE(CHILD(n, 1)) == funcdef ||
       TYPE(CHILD(n, 1)) == async_funcdef ||
       TYPE(CHILD(n, 1)) == classdef);
if (TYPE(CHILD(n, 1)) == funcdef) {
  thing = ast_for_funcdef(c, CHILD(n, 1), decorator_seq);
} else if (TYPE(CHILD(n, 1)) == classdef) {
  thing = ast_for_classdef(c, CHILD(n, 1), decorator_seq);
} else if (TYPE(CHILD(n, 1)) == async_funcdef) {
  thing = ast_for_async_funcdef(c, CHILD(n, 1), decorator_seq);
}
[...]

次のトークン(関数、クラス、または非同期)の検証があることを確認してから、責任あるメソッド(ast_for)を呼び出します。 そこで、ast.cに基づいて変更を行いました。

[...]
assert(TYPE(CHILD(n, 1)) == funcdef ||
       TYPE(CHILD(n, 1)) == async_funcdef ||
       TYPE(CHILD(n, 1)) == annassign ||
       TYPE(CHILD(n, 1)) == classdef);
if (TYPE(CHILD(n, 1)) == funcdef) {
  thing = ast_for_funcdef(c, CHILD(n, 1), decorator_seq);
} else if (TYPE(CHILD(n, 1)) == annassign) {
  thing = ast_for_annassign(c, CHILD(n, 1));
} else if (TYPE(CHILD(n, 1)) == classdef) {
  thing = ast_for_classdef(c, CHILD(n, 1), decorator_seq);
} else if (TYPE(CHILD(n, 1)) == async_funcdef) {
  thing = ast_for_async_funcdef(c, CHILD(n, 1), decorator_seq);
}
[...]

私が作成したことに注意してくださいast_for_annassign メソッド。同じ検証コードが含まれています。ast_for_expr_stmt アナッシング用:

static stmt_ty 
ast_for_annassign(struct compiling *c, const node *n)
{
    REQ(n, expr_stmt);
    expr_ty expr1, expr2, expr3;
    node *ch = CHILD(n, 0);
    node *deep, *ann = CHILD(n, 1);
    int simple = 1;
    /* we keep track of parens to qualify (x) as expression not name */
    deep = ch;
    while (NCH(deep) == 1) {
        deep = CHILD(deep, 0);
    }
    if (NCH(deep) > 0 && TYPE(CHILD(deep, 0)) == LPAR) {
        simple = 0;
    }
    expr1 = ast_for_testlist(c, ch);
    if (!expr1) {
        return NULL;
    }
    switch (expr1->kind) {
        case Name_kind:
            if (forbidden_name(c, expr1->v.Name.id, n, 0)) {
                return NULL;
            }
            expr1->v.Name.ctx = Store;
            break;
        case Attribute_kind:
            if (forbidden_name(c, expr1->v.Attribute.attr, n, 1)) {
                return NULL;
            }
            expr1->v.Attribute.ctx = Store;
            break;
        case Subscript_kind:
            expr1->v.Subscript.ctx = Store;
            break;
        case List_kind:
            ast_error(c, ch,
                      "only single target (not list) can be annotated");
            return NULL;
        case Tuple_kind:
            ast_error(c, ch,
                      "only single target (not tuple) can be annotated");
            return NULL;
        default:
            ast_error(c, ch,
                      "illegal target for annotation");
            return NULL;
    }
    if (expr1->kind != Name_kind) {
        simple = 0;
    }
    ch = CHILD(ann, 1);
    expr2 = ast_for_expr(c, ch);
    if (!expr2) {
        return NULL;
    }
    if (NCH(ann) == 2) {
        return AnnAssign(expr1, expr2, NULL, simple,
                         LINENO(n), n->n_col_offset, c->c_arena);
    }
    else {
        ch = CHILD(ann, 3);
        expr3 = ast_for_expr(c, ch);
        if (!expr3) {
            return NULL;
        }
        return AnnAssign(expr1, expr2, expr3, simple,
                         LINENO(n), n->n_col_offset, c->c_arena);
    }
}

これで、テスト(configure/make -j/make install)、python3.7、および次のことができました。

File "__init__.py", line 13
id: int = 1
^
SyntaxError: invalid syntax

文法とレキシカルパーサーの変更により、コンパイラはトークンを有効と解釈する必要がありますが、どこが間違っていますか?

あなたの答え
  • 解決した方法 # 1

    id: int = 1   annassign ではありません 。ザ・ウィズウィズ  一部は : int = 1 です 。 (ラインターミネータも annassign の一部としてカウントされません 。)注釈付き割り当てステートメント専用のPython文法には非終端記号はありません。あなたはそれを書かなければならないかもしれません。

    annassign

  • 前へ java - JPAクエリ:サブクエリをグループ化条件に結合する
  • 次へ java - インテントを使用して別のアクティビティにデータを渡すことは可能ですが、その特定のアクティビティを開始することはできませんか?