=====================================
Import statements
=====================================

import a, b
import b.c as d
import a.b.c

---

(module
  (import_statement
    (dotted_name (identifier))
    (dotted_name (identifier)))
  (import_statement
    (aliased_import
      (dotted_name (identifier) (identifier))
      (identifier)))
  (import_statement
    (dotted_name (identifier) (identifier) (identifier))))

=====================================
Import-from statements
=====================================

from a import b
from a import *
from a import (b, c)
from a.b import c
from . import b
from .. import b
from .a import b
from ..a import b

---

(module
  (import_from_statement
    (dotted_name (identifier))
    (dotted_name (identifier)))
  (import_from_statement
    (dotted_name (identifier))
    (wildcard_import))
  (import_from_statement
    (dotted_name (identifier))
    (dotted_name (identifier))
    (dotted_name (identifier)))
  (import_from_statement
    (dotted_name (identifier) (identifier))
    (dotted_name (identifier)))
  (import_from_statement
    (relative_import (import_prefix))
    (dotted_name (identifier)))
  (import_from_statement
    (relative_import (import_prefix))
    (dotted_name (identifier)))
  (import_from_statement
    (relative_import
      (import_prefix)
      (dotted_name (identifier)))
      (dotted_name (identifier)))
  (import_from_statement
    (relative_import
      (import_prefix)
      (dotted_name (identifier)))
      (dotted_name (identifier))))

=====================================
Future import statements
=====================================

from __future__ import print_statement
from __future__ import python4
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
---

(module
  (future_import_statement (dotted_name (identifier)))
  (future_import_statement (dotted_name (identifier)))
  (future_import_statement
    (dotted_name (identifier))
    (dotted_name (identifier))
    (dotted_name (identifier))
    (dotted_name (identifier))))

=====================================
Print statements
=====================================

print a
print b, c
print 0 or 1, 1 or 0,
print 0 or 1

---

(module
  (print_statement (identifier))
  (print_statement (identifier) (identifier))
  (print_statement
    (boolean_operator (integer) (integer))
    (boolean_operator (integer) (integer)))
  (print_statement
    (boolean_operator (integer) (integer))))

=====================================
Print statements with redirection
=====================================

print >> a
print >> a, "b", "c"

---

(module
  (print_statement (chevron (identifier)))
  (print_statement (chevron (identifier)) (string) (string)))

=====================================
Assert statements
=====================================

assert a
assert b, c

---

(module
  (assert_statement (identifier))
  (assert_statement (identifier) (identifier)))

=====================================
Expression statements
=====================================

a
b + c
1, 2, 3
1, 2, 3,

---

(module
  (expression_statement (identifier))
  (expression_statement (binary_operator (identifier) (identifier)))
  (expression_statement (integer) (integer) (integer))
  (expression_statement (integer) (integer) (integer)))

=====================================
Delete statements
=====================================

del a[1], b[2]

---

(module
  (delete_statement (expression_list
    (subscript (identifier) (integer))
    (subscript (identifier) (integer)))))

=====================================
Control-flow statements
=====================================

while true:
  pass
  break
  continue

---

(module
  (while_statement
    condition: (identifier)
    body: (block
      (pass_statement)
      (break_statement)
      (continue_statement))))

=====================================
Return statements
=====================================

return
return a + b, c
return not b

---

(module
  (return_statement)
  (return_statement (expression_list
    (binary_operator (identifier) (identifier))
    (identifier)))
  (return_statement (not_operator (identifier))))

=====================================
If statements
=====================================

if a:
  b
  c

---

(module
  (if_statement
    condition: (identifier)
    consequence: (block
      (expression_statement (identifier))
      (expression_statement (identifier)))))

=====================================
If else statements
=====================================

if a:
  b
elif c:
  d
else:
  f

if a:
  b
else:
  f

if a: b

if a: b; c

---

(module
  (if_statement
    condition: (identifier)
    consequence: (block
      (expression_statement (identifier)))
    alternative: (elif_clause
      condition: (identifier)
      consequence: (block
        (expression_statement (identifier))))
    alternative: (else_clause
      body: (block
        (expression_statement (identifier)))))
  (if_statement
    condition: (identifier)
    consequence: (block
      (expression_statement (identifier)))
    alternative: (else_clause
      body: (block
        (expression_statement (identifier)))))
  (if_statement
    condition: (identifier)
    consequence: (block
      (expression_statement (identifier))))
  (if_statement
    condition: (identifier)
    consequence: (block
      (expression_statement (identifier))
      (expression_statement (identifier)))))

=====================================
Nested if statements
=====================================

if a:
  if b:
    c
  else:
    if e:
      f
g

---

(module
  (if_statement
    condition: (identifier)
    consequence: (block
      (if_statement
        condition: (identifier)
        consequence: (block
          (expression_statement (identifier)))
        alternative: (else_clause
          body: (block
            (if_statement
              condition: (identifier)
              consequence: (block
                (expression_statement (identifier)))))))))
  (expression_statement (identifier)))

=====================================
While statements
=====================================

while a:
  b

while c:
  d
else:
  e
  f

---

(module
  (while_statement
    condition: (identifier)
    body: (block
      (expression_statement (identifier))))
  (while_statement
    condition: (identifier)
    body: (block
      (expression_statement (identifier)))
    alternative: (else_clause
      body: (block
        (expression_statement (identifier))
        (expression_statement (identifier))))))

=====================================
For statements
=====================================

for line, i in lines:
  print line
  for character, j in line:
    print character
else:
  print x

for x, in [(1,), (2,), (3,)]:
  x

---

(module
  (for_statement
    left: (pattern_list (identifier) (identifier))
    right: (identifier)
    body: (block
      (print_statement
        argument: (identifier))
      (for_statement
        left: (pattern_list (identifier) (identifier))
        right: (identifier)
        body: (block
          (print_statement
            argument: (identifier)))))
    alternative: (else_clause
      body: (block
        (print_statement
          argument: (identifier)))))
  (for_statement
    left: (pattern_list (identifier))
    right: (list (tuple (integer)) (tuple (integer)) (tuple (integer)))
    body: (block
      (expression_statement (identifier)))))

=====================================
Try statements
=====================================

try:
  a
except b:
  c
except d as e:
  f
except g, h:
  i
except:
  j

try:
  a
except b:
  c
  d
else:
  e
finally:
  f

---

(module
  (try_statement
    body: (block
      (expression_statement (identifier)))
    (except_clause (identifier)
      (block
        (expression_statement (identifier))))
    (except_clause (identifier) (identifier)
      (block
        (expression_statement (identifier))))
    (except_clause (identifier) (identifier)
      (block
        (expression_statement (identifier))))
    (except_clause
      (block
        (expression_statement (identifier)))))
  (try_statement
    body: (block
      (expression_statement (identifier)))
    (except_clause (identifier)
      (block
        (expression_statement (identifier))
        (expression_statement (identifier))))
    (else_clause body: (block
      (expression_statement (identifier))))
    (finally_clause (block
      (expression_statement (identifier))))))

=====================================
With statements
=====================================

with a as b:
  c

with (open('d') as d,
      open('e') as e):
  f

---

(module
  (with_statement
    (with_clause
      (with_item (identifier) (identifier)))
    (block
      (expression_statement (identifier))))
  (with_statement
    (with_clause
      (with_item (call (identifier) (argument_list (string))) (identifier))
      (with_item (call (identifier) (argument_list (string))) (identifier)))
    (block
      (expression_statement (identifier)))))

=====================================
Async Function definitions
=====================================

async def a():
  b

async def c(d):
  e

async def g(g, h,):
  i

async def c(a: str):
  a

async def c(a: b.c):
  a

async def d(a: Sequence[T]) -> T:
  a

async def i(a, b=c, *c, **d):
  a

async def d(a: str) -> None:
  return None

async def d(a:str="default", b=c) -> None:
  return None

---

(module
  (function_definition
    name: (identifier)
    parameters: (parameters)
    body: (block
      (expression_statement (identifier))))
  (function_definition
    name: (identifier)
    parameters: (parameters (identifier))
    body: (block
      (expression_statement (identifier))))
  (function_definition
    name: (identifier)
    parameters: (parameters (identifier) (identifier))
    body: (block
      (expression_statement (identifier))))
  (function_definition
    name: (identifier)
    parameters: (parameters
      (typed_parameter
        (identifier)
        type: (type (identifier))))
    body: (block
      (expression_statement (identifier))))
  (function_definition
    name: (identifier)
    parameters: (parameters
      (typed_parameter
        (identifier)
        type: (type (attribute
          object: (identifier)
          attribute: (identifier)))))
    body: (block
      (expression_statement (identifier))))
  (function_definition
    name: (identifier)
    parameters: (parameters
      (typed_parameter
        (identifier)
        type: (type (subscript value: (identifier) subscript: (identifier)))))
    return_type: (type (identifier))
    body: (block
      (expression_statement (identifier))))
  (function_definition
    name: (identifier)
    parameters: (parameters
      (identifier)
      (default_parameter
        name: (identifier)
        value: (identifier))
      (list_splat_pattern (identifier))
      (dictionary_splat_pattern (identifier)))
    body: (block
      (expression_statement (identifier))))
  (function_definition
    name: (identifier)
    parameters: (parameters
      (typed_parameter (identifier) type: (type (identifier))))
    return_type: (type (none))
    body: (block
      (return_statement (none))))
  (function_definition
    name: (identifier)
    parameters: (parameters
      (typed_default_parameter
        name: (identifier)
        type: (type (identifier))
        value: (string))
      (default_parameter
        name: (identifier)
        value: (identifier)))
    return_type: (type (none))
    body: (block
      (return_statement (none)))))

=====================================
Function definitions
=====================================

def e((a,b)):
  return (a,b)

def e(*list: str):
  pass

def e(**list: str):
  pass

def f():
  nonlocal a

def g(h, i, *, j, k=100, **kwarg):
  return h,i,j,k,kwarg

def h(*a):
  i((*a))
  j(((*a)))

---

(module
  (function_definition
    name: (identifier)
    parameters: (parameters (tuple_pattern (identifier) (identifier)))
    body: (block
      (return_statement (tuple (identifier) (identifier)))))
  (function_definition
    name: (identifier)
    parameters: (parameters (typed_parameter
      (list_splat_pattern (identifier))
      type: (type (identifier))))
    body: (block
      (pass_statement)))
  (function_definition
    name: (identifier)
    parameters: (parameters (typed_parameter
      (dictionary_splat_pattern (identifier))
      type: (type (identifier))))
    body: (block
      (pass_statement)))
  (function_definition
    name: (identifier)
    parameters: (parameters)
    body: (block
      (nonlocal_statement (identifier))))
  (function_definition
    name: (identifier)
    parameters: (parameters
      (identifier)
      (identifier)
      (list_splat_pattern)
      (identifier)
      (default_parameter name: (identifier) value: (integer))
      (dictionary_splat_pattern (identifier)))
    body: (block
      (return_statement (expression_list
        (identifier)
        (identifier)
        (identifier)
        (identifier)
        (identifier)))))
   (function_definition
     name: (identifier)
     parameters: (parameters (list_splat_pattern (identifier)))
     body: (block
       (expression_statement
         (call function:
           (identifier)
           arguments:
             (argument_list (parenthesized_expression (list_splat (identifier))))))
       (expression_statement
         (call function:
           (identifier)
           arguments: (argument_list (parenthesized_expression (parenthesized_expression (list_splat (identifier))))))))))


==================================
Empty blocks
==================================

# These are not actually valid python; blocks
# must contain at least one statement. But we
# allow them because error recovery for empty
# blocks doesn't work very well otherwise.
def a(b, c):

if d:
  print e
  while f():

---

(module
  (comment)
  (comment)
  (comment)
  (comment)
  (function_definition
    name: (identifier)
    parameters: (parameters (identifier) (identifier))
    body: (block))
  (if_statement
    condition: (identifier)
    consequence: (block
      (print_statement argument: (identifier))
      (while_statement
        condition: (call
          function: (identifier)
          arguments: (argument_list))
        body: (block)))))

====================================================
Class definitions
====================================================

class A:
  def b(self):
    return c
class B():
  pass
class B(method1):
  def method1(self):
    return
class C(method1, Sequence[T]):
  pass
class D(Sequence[T, U]):
  pass

---

(module
  (class_definition
    (identifier)
    (block
      (function_definition
        (identifier)
        (parameters (identifier))
        (block
          (return_statement (identifier))))))
 (class_definition
    (identifier)
    (argument_list)
    (block
      (pass_statement)))
 (class_definition
    (identifier)
    (argument_list (identifier))
    (block
      (function_definition
        (identifier)
        (parameters (identifier))
        (block
          (return_statement)))))
 (class_definition
    (identifier)
    (argument_list (identifier) (subscript (identifier) (identifier)))
    (block
      (pass_statement)))
 (class_definition
    (identifier)
    (argument_list (subscript (identifier) (identifier) (identifier)))
    (block
      (pass_statement))))

====================================================
Class definitions with superclasses
====================================================

class A(B, C):
  def d():
    e

---

(module
  (class_definition
    (identifier)
    (argument_list (identifier) (identifier))
    (block
      (function_definition
        (identifier)
        (parameters)
        (block
          (expression_statement (identifier)))))))

====================================================
Decorated definitions
====================================================

@a.b
class C:
  @d(1)
  @e[2].f.g
  def f():
    g

  @f()
  async def f():
    g

---

(module
  (decorated_definition
    (decorator (attribute (identifier) (identifier)))
    (class_definition (identifier) (block
      (decorated_definition
        (decorator (call
          (identifier)
          (argument_list (integer))))
        (decorator (attribute
          (attribute
            (subscript
              (identifier)
              (integer))
            (identifier))
          (identifier)))
        (function_definition (identifier) (parameters) (block (expression_statement (identifier)))))
      (decorated_definition
        (decorator (call (identifier) (argument_list)))
        (function_definition (identifier) (parameters) (block (expression_statement (identifier)))))))))


====================================================
Raise statements
====================================================

raise
raise RuntimeError('NO')
raise RunTimeError('NO') from e

---

(module
  (raise_statement)
  (raise_statement
    (call (identifier) (argument_list (string))))
  (raise_statement
    (call (identifier) (argument_list (string)))
    (identifier)))

====================================================
Comments
====================================================

print a
# hi
print b # bye
print c

---

(module
  (print_statement (identifier))
  (comment)
  (print_statement (identifier))
  (comment)
  (print_statement (identifier)))

====================================================
Comments at different indentation levels
====================================================

if a:
  # one
# two
    # three
  b
    # four
  c

---

(module
  (if_statement (identifier)
    (comment)
    (comment)
    (comment)
    (block
      (expression_statement (identifier))
      (comment)
      (expression_statement (identifier)))))

====================================================
Comments after dedents
====================================================

if a:
  b

# one
c

---

(module
  (if_statement
    (identifier)
    (block
      (expression_statement (identifier))))
  (comment)
  (expression_statement (identifier)))

====================================================
Comments at the ends of indented blocks
====================================================

if a:
  b
  # one
  # two

if c:
  d
    # three
      # four

# five

---

(module
  (if_statement (identifier) (block
    (expression_statement (identifier))
    (comment)
    (comment)))
  (if_statement (identifier) (block
    (expression_statement (identifier))
    (comment)
    (comment)))
  (comment))

====================================================
Newline tokens followed by comments
====================================================

print "a"
  # We need to recognize the newline *preceding* this comment, because there's no newline after it
---

(module (print_statement (string)) (comment))

====================================================
Global statements
====================================================

global a
global a, b

---

(module
  (global_statement (identifier))
  (global_statement (identifier) (identifier)))

====================================================
Exec statements
====================================================

exec '1+1'
exec 'x+=1' in None
exec 'x+=1' in a, b

---

(module
  (exec_statement (string))
  (exec_statement (string) (none))
  (exec_statement (string) (identifier) (identifier)))

==================================================
Extra newlines
==================================================

if a:


    b()


    c()


    def d():


        e()


    f()

---

(module
  (if_statement (identifier) (block
    (expression_statement (call (identifier) (argument_list)))
    (expression_statement (call (identifier) (argument_list)))
    (function_definition (identifier) (parameters) (block
      (expression_statement (call (identifier) (argument_list)))))
    (expression_statement (call (identifier) (argument_list))))))
