Python源代码 - 更新语法

Jon*_*nny 8 python grammar cpython python-2.7 python-3.x

我正在研究一下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
Run Code Online (Sandbox Code Playgroud)

它完美地运行,遵循语法/语法文件的行:

decorated: decorators (classdef | funcdef | async_funcdef)
Run Code Online (Sandbox Code Playgroud)

现在的目标是将装饰器更改为接受声明,从示例开始:

@test
id: int = 1
Run Code Online (Sandbox Code Playgroud)

分析语法,我找到了annassign,它将是:

annassign: ':' test ['=' test]
# or even use small_stmt
Run Code Online (Sandbox Code Playgroud)

给定表示id:int = 1的标记,我将标记更改为:

decorated: decorators (classdef | funcdef | async_funcdef | annassign)
Run Code Online (Sandbox Code Playgroud)

完成(遵循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);
}
[...]
Run Code Online (Sandbox Code Playgroud)

您可以验证是否有下一个标记(函数,类或异步)的验证,然后调用负责的方法(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);
}
[...]
Run Code Online (Sandbox Code Playgroud)

请注意,我创建了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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在是时候测试(configure/make -j/make install),python3.7和:

File "__init__.py", line 13
id: int = 1
^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)

随着语法和词法解析器的改变,编译器是否应该将令牌解释为有效,哪里出错?

use*_*ica 2

id: int = 1不是一个annassign. 该: int = 1零件是一个annassign. (甚至行终止符也不算作 的一部分annassign。)Python 语法中没有专门用于带注释的赋值语句的非终结符;你可能需要写一篇。