Python 源代码 - 更新语法
Python Source Code - Update Grammar
我正在研究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);
}
[...]
您可以验证下一个令牌(函数、class 或异步)是否已验证,然后调用负责的方法 (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[=59 中存在的相同验证码=] 用于分析:
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
随着语法和词法解析器的变化,编译器是否应该将标记解释为有效,我哪里错了?
id: int = 1
不是 annassign
。 : int = 1
部分是 annassign
。 (即使行终止符也不算作 annassign
的一部分。)在 Python 语法中没有专门用于带注释的赋值语句的非终结符;你可能得写一个。
我正在研究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);
}
[...]
您可以验证下一个令牌(函数、class 或异步)是否已验证,然后调用负责的方法 (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[=59 中存在的相同验证码=] 用于分析:
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
随着语法和词法解析器的变化,编译器是否应该将标记解释为有效,我哪里错了?
id: int = 1
不是 annassign
。 : int = 1
部分是 annassign
。 (即使行终止符也不算作 annassign
的一部分。)在 Python 语法中没有专门用于带注释的赋值语句的非终结符;你可能得写一个。