kopia lustrzana https://github.com/micropython/micropython
Merge 3622ed5cb1
into 01c31ea804
commit
88d38f9b81
|
@ -2513,6 +2513,9 @@ static void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||||
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
|
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
|
||||||
// an empty tuple
|
// an empty tuple
|
||||||
EMIT_ARG(build, 0, MP_EMIT_BUILD_TUPLE);
|
EMIT_ARG(build, 0, MP_EMIT_BUILD_TUPLE);
|
||||||
|
} else if (MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
|
||||||
|
// a lone ID
|
||||||
|
compile_node(comp, pns->nodes[0]);
|
||||||
} else {
|
} else {
|
||||||
assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
|
assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
|
||||||
pns = (mp_parse_node_struct_t *)pns->nodes[0];
|
pns = (mp_parse_node_struct_t *)pns->nodes[0];
|
||||||
|
|
16
py/parse.c
16
py/parse.c
|
@ -237,6 +237,8 @@ typedef struct _parser_t {
|
||||||
mp_parse_tree_t tree;
|
mp_parse_tree_t tree;
|
||||||
mp_parse_chunk_t *cur_chunk;
|
mp_parse_chunk_t *cur_chunk;
|
||||||
|
|
||||||
|
uint32_t cur_view;
|
||||||
|
|
||||||
#if MICROPY_COMP_CONST
|
#if MICROPY_COMP_CONST
|
||||||
mp_map_t consts;
|
mp_map_t consts;
|
||||||
#endif
|
#endif
|
||||||
|
@ -957,6 +959,9 @@ static void push_result_rule(parser_t *parser, size_t src_line, uint8_t rule_id,
|
||||||
// need to keep parenthesis for ()
|
// need to keep parenthesis for ()
|
||||||
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, RULE_testlist_comp)) {
|
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, RULE_testlist_comp)) {
|
||||||
// need to keep parenthesis for (a, b, ...)
|
// need to keep parenthesis for (a, b, ...)
|
||||||
|
} else if (MP_PARSE_NODE_IS_ID(pn) && MP_PARSE_IS_PARSING_ARGLIST(parser)) {
|
||||||
|
// Keep parentheses around single IDs that are function arguments
|
||||||
|
// since they may be keyword arguments.
|
||||||
} else {
|
} else {
|
||||||
// parenthesis around a single expression, so it's just the expression
|
// parenthesis around a single expression, so it's just the expression
|
||||||
return;
|
return;
|
||||||
|
@ -1044,6 +1049,8 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
|
||||||
parser.tree.chunk = NULL;
|
parser.tree.chunk = NULL;
|
||||||
parser.cur_chunk = NULL;
|
parser.cur_chunk = NULL;
|
||||||
|
|
||||||
|
parser.cur_view = 0x0;
|
||||||
|
|
||||||
#if MICROPY_COMP_CONST
|
#if MICROPY_COMP_CONST
|
||||||
mp_map_init(&parser.consts, 0);
|
mp_map_init(&parser.consts, 0);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1234,12 +1241,21 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
|
||||||
default: {
|
default: {
|
||||||
assert((rule_act & RULE_ACT_KIND_MASK) == RULE_ACT_LIST);
|
assert((rule_act & RULE_ACT_KIND_MASK) == RULE_ACT_LIST);
|
||||||
|
|
||||||
|
if (rule_id == RULE_arglist && !MP_PARSE_IS_PARSING_ARGLIST(&parser)) {
|
||||||
|
parser.cur_view |= MP_PARSE_PARSING_ARGLIST;
|
||||||
|
}
|
||||||
|
|
||||||
// n=2 is: item item*
|
// n=2 is: item item*
|
||||||
// n=1 is: item (sep item)*
|
// n=1 is: item (sep item)*
|
||||||
// n=3 is: item (sep item)* [sep]
|
// n=3 is: item (sep item)* [sep]
|
||||||
bool had_trailing_sep;
|
bool had_trailing_sep;
|
||||||
if (backtrack) {
|
if (backtrack) {
|
||||||
list_backtrack:
|
list_backtrack:
|
||||||
|
|
||||||
|
if (rule_id == RULE_arglist) {
|
||||||
|
parser.cur_view &= ~MP_PARSE_PARSING_ARGLIST;
|
||||||
|
}
|
||||||
|
|
||||||
had_trailing_sep = false;
|
had_trailing_sep = false;
|
||||||
if (n == 2) {
|
if (n == 2) {
|
||||||
if (i == 1) {
|
if (i == 1) {
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
|
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
|
|
||||||
|
#define MP_PARSE_PARSING_ARGLIST (0x1)
|
||||||
|
#define MP_PARSE_IS_PARSING_ARGLIST(parser) (((parser)->cur_view) & MP_PARSE_PARSING_ARGLIST)
|
||||||
|
|
||||||
struct _mp_lexer_t;
|
struct _mp_lexer_t;
|
||||||
|
|
||||||
// a mp_parse_node_t is:
|
// a mp_parse_node_t is:
|
||||||
|
|
|
@ -8,3 +8,5 @@ def g(x):
|
||||||
f(4 * x)
|
f(4 * x)
|
||||||
|
|
||||||
g(3)
|
g(3)
|
||||||
|
a = 3
|
||||||
|
g((a)) # Making sure the extra parentheses cause no issues
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
# Test function call keyword argument syntax
|
||||||
|
|
||||||
|
def test_syntax(code):
|
||||||
|
try:
|
||||||
|
eval(code)
|
||||||
|
except SyntaxError:
|
||||||
|
print("SyntaxError in '{}'".format(code))
|
||||||
|
|
||||||
|
def f(a):
|
||||||
|
return a
|
||||||
|
|
||||||
|
# Should throw syntax errors.
|
||||||
|
test_syntax("f((a)=2)")
|
||||||
|
test_syntax("f(a()=2)")
|
||||||
|
test_syntax("f(a or b=2)")
|
||||||
|
test_syntax("f(2, (a)=3)")
|
||||||
|
test_syntax("f((a) = 1, (b) = 5)")
|
||||||
|
test_syntax("f((a, b) = 1)")
|
||||||
|
test_syntax("f(f(), (a)=2)")
|
Ładowanie…
Reference in New Issue