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])) {
|
||||
// an empty 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 {
|
||||
assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
|
||||
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_chunk_t *cur_chunk;
|
||||
|
||||
uint32_t cur_view;
|
||||
|
||||
#if MICROPY_COMP_CONST
|
||||
mp_map_t consts;
|
||||
#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 ()
|
||||
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, RULE_testlist_comp)) {
|
||||
// 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 {
|
||||
// parenthesis around a single expression, so it's just the expression
|
||||
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.cur_chunk = NULL;
|
||||
|
||||
parser.cur_view = 0x0;
|
||||
|
||||
#if MICROPY_COMP_CONST
|
||||
mp_map_init(&parser.consts, 0);
|
||||
#endif
|
||||
|
@ -1234,12 +1241,21 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
|
|||
default: {
|
||||
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=1 is: item (sep item)*
|
||||
// n=3 is: item (sep item)* [sep]
|
||||
bool had_trailing_sep;
|
||||
if (backtrack) {
|
||||
list_backtrack:
|
||||
|
||||
if (rule_id == RULE_arglist) {
|
||||
parser.cur_view &= ~MP_PARSE_PARSING_ARGLIST;
|
||||
}
|
||||
|
||||
had_trailing_sep = false;
|
||||
if (n == 2) {
|
||||
if (i == 1) {
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
|
||||
#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;
|
||||
|
||||
// a mp_parse_node_t is:
|
||||
|
|
|
@ -8,3 +8,5 @@ def g(x):
|
|||
f(4 * x)
|
||||
|
||||
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