Skip to content

Commit

Permalink
Parse named expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhalter committed Jun 2, 2019
1 parent 5430415 commit a7aa23a
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 5 deletions.
8 changes: 7 additions & 1 deletion conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
collect_ignore = ["setup.py"]

VERSIONS_2 = '2.6', '2.7'
VERSIONS_3 = '3.3', '3.4', '3.5', '3.6', '3.7'
VERSIONS_3 = '3.3', '3.4', '3.5', '3.6', '3.7', '3.8'


@pytest.fixture(scope='session')
Expand Down Expand Up @@ -155,3 +155,9 @@ def works_ge_py3(each_version):
def works_ge_py35(each_version):
version_info = parse_version_string(each_version)
return Checker(each_version, version_info >= (3, 5))


@pytest.fixture
def works_ge_py38(each_version):
version_info = parse_version_string(each_version)
return Checker(each_version, version_info >= (3, 8))
8 changes: 5 additions & 3 deletions parso/python/grammar38.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ assert_stmt: 'assert' test [',' test]

compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt
async_stmt: 'async' (funcdef | with_stmt | for_stmt)
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
while_stmt: 'while' test ':' suite ['else' ':' suite]
if_stmt: 'if' namedexpr_test ':' suite ('elif' namedexpr_test ':' suite)* ['else' ':' suite]
while_stmt: 'while' namedexpr_test ':' suite ['else' ':' suite]
for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
try_stmt: ('try' ':' suite
((except_clause ':' suite)+
Expand All @@ -83,6 +83,7 @@ with_item: test ['as' expr]
except_clause: 'except' [test ['as' NAME]]
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT

namedexpr_test: test [':=' test]
test: or_test ['if' or_test 'else' test] | lambdef
test_nocond: or_test | lambdef_nocond
lambdef: 'lambda' [varargslist] ':' test
Expand All @@ -108,7 +109,7 @@ atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [testlist_comp] ']' |
'{' [dictorsetmaker] '}' |
NAME | NUMBER | strings | '...' | 'None' | 'True' | 'False')
testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] )
testlist_comp: (namedexpr_test|star_expr) ( comp_for | (',' (namedexpr_test|star_expr))* [','] )
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
subscriptlist: subscript (',' subscript)* [',']
subscript: test | [test] ':' [test] [sliceop]
Expand All @@ -134,6 +135,7 @@ arglist: argument (',' argument)* [',']
# multiple (test comp_for) arguments are blocked; keyword unpackings
# that precede iterable unpackings are blocked; etc.
argument: ( test [comp_for] |
test ':=' test |
test '=' test |
'**' test |
'*' test )
Expand Down
6 changes: 5 additions & 1 deletion parso/python/tokenize.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,13 @@ def _create_token_collection(version_info):

Bracket = '[][(){}]'

special_args = [r'\r\n?', r'\n', r'[:;.,@]']
special_args = [r'\r\n?', r'\n', r'[;.,@]']
if version_info >= (3, 0):
special_args.insert(0, r'\.\.\.')
if version_info >= (3, 8):
special_args.insert(0, ":=?")
else:
special_args.insert(0, ":")
Special = group(*special_args)

Funny = group(Operator, Bracket, Special)
Expand Down
4 changes: 4 additions & 0 deletions test/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,7 @@ def check(node):
check(child)

check(parse("if foo:\n bar", version=each_version))


def test_named_expression(works_ge_py38):
works_ge_py38.parse("(a := 1, a + 1)")

0 comments on commit a7aa23a

Please sign in to comment.