================================================================================
Blocks: declaration
================================================================================

NSObject* (^blockName)(NSObject *);

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    type: (type_identifier)
    declarator: (pointer_declarator
      declarator: (block_declarator
        declarator: (identifier)
        parameters: (parameter_list
          (parameter_declaration
            type: (type_identifier)
            declarator: (abstract_pointer_declarator)))))))

================================================================================
Blocks: As a local variable
================================================================================

int (^blockName)() = ^int() {return -1;};
int (^blockName)(int) = ^int(int a) {return -1;};
int (^blockName)(int, NSObject *) = ^int(int a, NSObject *object) {return -1;};

NSString * _Nullable(^blockName)(NSString * _Nonnull) = ^NSString * _Nullable(NSString * _Nonnull key) {
  return nil;
};

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    type: (primitive_type)
    declarator: (init_declarator
      declarator: (block_declarator
        declarator: (identifier)
        parameters: (parameter_list))
      value: (block_expression
        declarator: (type_descriptor
          type: (primitive_type)
          declarator: (abstract_function_declarator
            parameters: (parameter_list)))
        (compound_statement
          (return_statement
            (number_literal))))))
  (declaration
    type: (primitive_type)
    declarator: (init_declarator
      declarator: (block_declarator
        declarator: (identifier)
        parameters: (parameter_list
          (parameter_declaration
            type: (primitive_type))))
      value: (block_expression
        declarator: (type_descriptor
          type: (primitive_type)
          declarator: (abstract_function_declarator
            parameters: (parameter_list
              (parameter_declaration
                type: (primitive_type)
                declarator: (identifier)))))
        (compound_statement
          (return_statement
            (number_literal))))))
  (declaration
    type: (primitive_type)
    declarator: (init_declarator
      declarator: (block_declarator
        declarator: (identifier)
        parameters: (parameter_list
          (parameter_declaration
            type: (primitive_type))
          (parameter_declaration
            type: (type_identifier)
            declarator: (abstract_pointer_declarator))))
      value: (block_expression
        declarator: (type_descriptor
          type: (primitive_type)
          declarator: (abstract_function_declarator
            parameters: (parameter_list
              (parameter_declaration
                type: (primitive_type)
                declarator: (identifier))
              (parameter_declaration
                type: (type_identifier)
                declarator: (pointer_declarator
                  declarator: (identifier))))))
        (compound_statement
          (return_statement
            (number_literal))))))
  (declaration
    type: (type_identifier)
    declarator: (init_declarator
      declarator: (pointer_declarator
        (type_qualifier)
        declarator: (block_declarator
          declarator: (identifier)
          parameters: (parameter_list
            (parameter_declaration
              type: (type_identifier)
              declarator: (abstract_pointer_declarator
                (type_qualifier))))))
      value: (block_expression
        declarator: (type_descriptor
          type: (type_identifier)
          declarator: (abstract_pointer_declarator
            (type_qualifier)
            declarator: (abstract_function_declarator
              parameters: (parameter_list
                (parameter_declaration
                  type: (type_identifier)
                  declarator: (pointer_declarator
                    (type_qualifier)
                    declarator: (identifier)))))))
        (compound_statement
          (return_statement
            (nil)))))))

================================================================================
Blocks: As a typedef
================================================================================

typedef void(^blockName)(void);
typedef void(^blockName)(NSObject *object);
typedef void(^blockName)(NSObject * _Nullable object);
typedef void(^blockName)(NSUInteger val1, NSUInteger val2);
typedef void (^blockName)(NSMutableOrderedSet <NSObject *> * _Nullable objects, NSInteger val1, NSBlock_declaration * _Nullable block_declaration);
typedef void (^blockName)(__kindof UIView * _Nonnull view);
typedef NSURLResponse * _Nullable (^blockName)(NSURLResponse * _Nonnull val1, NSBundle * _Nullable val2);

// type qualifier in block definition
typedef id _Nullable (^blockName)(NSString *name, NSBundle * _Nullable bundle);

--------------------------------------------------------------------------------

(translation_unit
  (type_definition
    type: (primitive_type)
    declarator: (block_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (primitive_type)))))
  (type_definition
    type: (primitive_type)
    declarator: (block_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (type_identifier)
          declarator: (pointer_declarator
            declarator: (identifier))))))
  (type_definition
    type: (primitive_type)
    declarator: (block_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (type_identifier)
          declarator: (pointer_declarator
            (type_qualifier)
            declarator: (identifier))))))
  (type_definition
    type: (primitive_type)
    declarator: (block_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (type_identifier)
          declarator: (identifier))
        (parameter_declaration
          type: (type_identifier)
          declarator: (identifier)))))
  (type_definition
    type: (primitive_type)
    declarator: (block_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (generic_type_specifier
            class_name: (type_identifier)
            type_reference: (generic_type_references
              (type_descriptor
                type: (type_identifier)
                declarator: (abstract_pointer_declarator))))
          declarator: (pointer_declarator
            (type_qualifier)
            declarator: (identifier)))
        (parameter_declaration
          type: (type_identifier)
          declarator: (identifier))
        (parameter_declaration
          type: (type_identifier)
          declarator: (pointer_declarator
            (type_qualifier)
            declarator: (identifier))))))
  (type_definition
    type: (primitive_type)
    declarator: (block_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          (type_qualifier)
          type: (type_identifier)
          declarator: (pointer_declarator
            (type_qualifier)
            declarator: (identifier))))))
  (type_definition
    type: (type_identifier)
    declarator: (pointer_declarator
      (type_qualifier)
      declarator: (block_declarator
        declarator: (identifier)
        parameters: (parameter_list
          (parameter_declaration
            type: (type_identifier)
            declarator: (pointer_declarator
              (type_qualifier)
              declarator: (identifier)))
          (parameter_declaration
            type: (type_identifier)
            declarator: (pointer_declarator
              (type_qualifier)
              declarator: (identifier)))))))
  (comment)
  (type_definition
    type: (id)
    (type_qualifier)
    declarator: (block_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (type_identifier)
          declarator: (pointer_declarator
            declarator: (identifier)))
        (parameter_declaration
          type: (type_identifier)
          declarator: (pointer_declarator
            (type_qualifier)
            declarator: (identifier)))))))

================================================================================
Blocks: As a method parameter
================================================================================

@interface Block
- (void)loginWithCompletion:(nullable NSNumber *(^)(BOOL success, NSString *name, id object))completion;
@end

@implementation Block
- (void)loginWithCompletion:(nullable void(_Nonnull ^)(BOOL success, id object))completion {
  [self registerHandler:^(UIView * _Nonnull view, NSString * _Nonnull name, NSDictionary * _Nullable params, void (^ _Nonnull callback)(int, id _Nullable)) {
    if (handler) {
        handler(params, callback);
    }
  } forMethod:method];
}
- (void)URLSession:(NSURLSession *)session
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
}
@end

--------------------------------------------------------------------------------

(translation_unit
  (class_interface
    name: (identifier)
    (method_declaration
      scope: (instance_scope)
      type: (primitive_type)
      selector: (keyword_selector
        (keyword_declarator
          keyword: (identifier)
          type: (nullable)
          type: (type_identifier)
          declarator: (abstract_pointer_declarator
            declarator: (block_abstract_declarator
              parameters: (parameter_list
                (parameter_declaration
                  type: (BOOL)
                  declarator: (identifier))
                (parameter_declaration
                  type: (type_identifier)
                  declarator: (pointer_declarator
                    declarator: (identifier)))
                (parameter_declaration
                  type: (id)
                  declarator: (identifier)))))
          name: (identifier)))))
  (class_implementation
    name: (identifier)
    (method_definition
      scope: (instance_scope)
      type: (primitive_type)
      selector: (keyword_selector
        (keyword_declarator
          keyword: (identifier)
          type: (nullable)
          type: (primitive_type)
          declarator: (block_abstract_declarator
            (type_qualifier)
            parameters: (parameter_list
              (parameter_declaration
                type: (BOOL)
                declarator: (identifier))
              (parameter_declaration
                type: (id)
                declarator: (identifier))))
          name: (identifier)))
      body: (compound_statement
        (expression_statement
          (message_expression
            receiver: (self)
            selector: (keyword_argument_list
              (keyword_argument
                keyword: (identifier)
                argument: (block_expression
                  parameters: (parameter_list
                    (parameter_declaration
                      type: (type_identifier)
                      declarator: (pointer_declarator
                        (type_qualifier)
                        declarator: (identifier)))
                    (parameter_declaration
                      type: (type_identifier)
                      declarator: (pointer_declarator
                        (type_qualifier)
                        declarator: (identifier)))
                    (parameter_declaration
                      type: (type_identifier)
                      declarator: (pointer_declarator
                        (type_qualifier)
                        declarator: (identifier)))
                    (parameter_declaration
                      type: (primitive_type)
                      declarator: (block_declarator
                        (type_qualifier)
                        declarator: (identifier)
                        parameters: (parameter_list
                          (parameter_declaration
                            type: (primitive_type))
                          (parameter_declaration
                            type: (id)
                            (type_qualifier))))))
                  (compound_statement
                    (if_statement
                      condition: (parenthesized_expression
                        (identifier))
                      consequence: (compound_statement
                        (expression_statement
                          (call_expression
                            function: (identifier)
                            arguments: (argument_list
                              (identifier)
                              (identifier)))))))))
              (keyword_argument
                keyword: (identifier)
                argument: (identifier)))))))
    (method_definition
      scope: (instance_scope)
      type: (primitive_type)
      selector: (keyword_selector
        (keyword_declarator
          keyword: (identifier)
          type: (type_identifier)
          declarator: (abstract_pointer_declarator)
          name: (identifier))
        (keyword_declarator
          keyword: (identifier)
          type: (primitive_type)
          declarator: (block_abstract_declarator
            parameters: (parameter_list
              (parameter_declaration
                type: (type_identifier)
                declarator: (identifier))))
          name: (identifier)))
      body: (compound_statement))))

================================================================================
Blocks: As a property
================================================================================

@interface Block
@property (nonatomic, copy) int (^blockName)(int, int);
@property (nonatomic, copy) int (^blockName)(int a, int b);
@property (nonatomic, copy) NSObject * (^blockName)(int, int);
@property (nonatomic, copy) id (^blockName)(int, int, UIImage * _Nonnull frame);
@property (nonatomic, strong) NSMutableDictionary<NSNumber *,void (^)(UIImage * _Nullable, NSTimeInterval)> *tasks;
@end

--------------------------------------------------------------------------------

(translation_unit
  (class_interface
    name: (identifier)
    (property_declaration
      (property_attributes
        (nonatomic)
        (copy))
      type: (primitive_type)
      declarator: (block_declarator
        declarator: (identifier)
        parameters: (parameter_list
          (parameter_declaration
            type: (primitive_type))
          (parameter_declaration
            type: (primitive_type)))))
    (property_declaration
      (property_attributes
        (nonatomic)
        (copy))
      type: (primitive_type)
      declarator: (block_declarator
        declarator: (identifier)
        parameters: (parameter_list
          (parameter_declaration
            type: (primitive_type)
            declarator: (identifier))
          (parameter_declaration
            type: (primitive_type)
            declarator: (identifier)))))
    (property_declaration
      (property_attributes
        (nonatomic)
        (copy))
      type: (type_identifier)
      declarator: (pointer_declarator
        declarator: (block_declarator
          declarator: (identifier)
          parameters: (parameter_list
            (parameter_declaration
              type: (primitive_type))
            (parameter_declaration
              type: (primitive_type))))))
    (property_declaration
      (property_attributes
        (nonatomic)
        (copy))
      type: (id)
      declarator: (block_declarator
        declarator: (identifier)
        parameters: (parameter_list
          (parameter_declaration
            type: (primitive_type))
          (parameter_declaration
            type: (primitive_type))
          (parameter_declaration
            type: (type_identifier)
            declarator: (pointer_declarator
              (type_qualifier)
              declarator: (identifier))))))
    (property_declaration
      (property_attributes
        (nonatomic)
        (strong))
      type: (generic_type_specifier
        class_name: (type_identifier)
        type_reference: (generic_type_references
          (type_descriptor
            type: (type_identifier)
            declarator: (abstract_pointer_declarator))
          (type_descriptor
            type: (primitive_type)
            declarator: (block_abstract_declarator
              parameters: (parameter_list
                (parameter_declaration
                  type: (type_identifier)
                  declarator: (abstract_pointer_declarator
                    (type_qualifier)))
                (parameter_declaration
                  type: (type_identifier)))))))
      declarator: (pointer_declarator
        declarator: (identifier)))))

================================================================================
Blocks: As a argument to a method call
================================================================================

[someObject someMethodThatTakesABlock:^(id  _Nullable observer, id  _Nonnull object, NSDictionary<NSString *,id> * _Nonnull change) {
    int (^blockName)() = ^int() {return -1;};
}];

--------------------------------------------------------------------------------

(translation_unit
  (expression_statement
    (message_expression
      receiver: (type_identifier)
      selector: (keyword_argument_list
        (keyword_argument
          keyword: (identifier)
          argument: (block_expression
            parameters: (parameter_list
              (parameter_declaration
                type: (id)
                (type_qualifier)
                declarator: (identifier))
              (parameter_declaration
                type: (id)
                (type_qualifier)
                declarator: (identifier))
              (parameter_declaration
                type: (generic_type_specifier
                  class_name: (type_identifier)
                  type_reference: (generic_type_references
                    (type_descriptor
                      type: (type_identifier)
                      declarator: (abstract_pointer_declarator))
                    (type_descriptor
                      type: (id))))
                declarator: (pointer_declarator
                  (type_qualifier)
                  declarator: (identifier))))
            (compound_statement
              (declaration
                type: (primitive_type)
                declarator: (init_declarator
                  declarator: (block_declarator
                    declarator: (identifier)
                    parameters: (parameter_list))
                  value: (block_expression
                    declarator: (type_descriptor
                      type: (primitive_type)
                      declarator: (abstract_function_declarator
                        parameters: (parameter_list)))
                    (compound_statement
                      (return_statement
                        (number_literal)))))))))))))

================================================================================
Blocks: As a C function call, as _field_declarator
================================================================================

void SomeFunctionThatTakesABlock(returnType (^blockName)(int));

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (type_identifier)
          declarator: (block_declarator
            declarator: (identifier)
            parameters: (parameter_list
              (parameter_declaration
                type: (primitive_type)))))))))

================================================================================
Blocks: As a cast type specifier
================================================================================

(returnType (^)(int, id))anotherBlock;

--------------------------------------------------------------------------------

(translation_unit
  (expression_statement
    (cast_expression
      type: (type_descriptor
        type: (type_identifier)
        declarator: (block_abstract_declarator
          parameters: (parameter_list
            (parameter_declaration
              type: (primitive_type))
            (parameter_declaration
              type: (id)))))
      value: (identifier))))

================================================================================
Blocks: block type in block declaration parameter_list
================================================================================

void(^blockName1)(void(^blockName2)(void));

@interface Block
- (void)someMethodThatTakesABlock:(void(^)(void(^)(void)))block;
@end

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    type: (primitive_type)
    declarator: (block_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (primitive_type)
          declarator: (block_declarator
            declarator: (identifier)
            parameters: (parameter_list
              (parameter_declaration
                type: (primitive_type))))))))
  (class_interface
    name: (identifier)
    (method_declaration
      scope: (instance_scope)
      type: (primitive_type)
      selector: (keyword_selector
        (keyword_declarator
          keyword: (identifier)
          type: (primitive_type)
          declarator: (block_abstract_declarator
            parameters: (parameter_list
              (parameter_declaration
                type: (primitive_type)
                declarator: (block_abstract_declarator
                  parameters: (parameter_list
                    (parameter_declaration
                      type: (primitive_type)))))))
          name: (identifier))))))

================================================================================
Blocks: block type in block declaration parameter_list
================================================================================

void (^blockName)(void);

void (^(^blockName)(void (^)(void)))(void);

void(^(^blockName)(NSDictionary *params))(UIImage *image) = ^(NSDictionary *params) {
    return ^(UIImage * image) {
    };
};

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    type: (primitive_type)
    declarator: (block_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (primitive_type)))))
  (declaration
    type: (primitive_type)
    declarator: (block_declarator
      return_type: (block_declarator
        declarator: (identifier)
        parameters: (parameter_list
          (parameter_declaration
            type: (primitive_type)
            declarator: (block_abstract_declarator
              parameters: (parameter_list
                (parameter_declaration
                  type: (primitive_type)))))))
      parameters: (parameter_list
        (parameter_declaration
          type: (primitive_type)))))
  (declaration
    type: (primitive_type)
    declarator: (init_declarator
      declarator: (block_declarator
        return_type: (block_declarator
          declarator: (identifier)
          parameters: (parameter_list
            (parameter_declaration
              type: (type_identifier)
              declarator: (pointer_declarator
                declarator: (identifier)))))
        parameters: (parameter_list
          (parameter_declaration
            type: (type_identifier)
            declarator: (pointer_declarator
              declarator: (identifier)))))
      value: (block_expression
        parameters: (parameter_list
          (parameter_declaration
            type: (type_identifier)
            declarator: (pointer_declarator
              declarator: (identifier))))
        (compound_statement
          (return_statement
            (block_expression
              parameters: (parameter_list
                (parameter_declaration
                  type: (type_identifier)
                  declarator: (pointer_declarator
                    declarator: (identifier))))
              (compound_statement))))))))

================================================================================
Blocks: block_type_specifier in cast expression parameter_list
================================================================================

((id(*)(id, SEL, id, id, id, id, void(^)(NSURLRequest *)))objc_msgSend)(
  slf, swizzledSelector, session, task, response, newRequest, completionHandler
);

--------------------------------------------------------------------------------

(translation_unit
  (expression_statement
    (call_expression
      function: (parenthesized_expression
        (cast_expression
          type: (type_descriptor
            type: (id)
            declarator: (abstract_function_declarator
              declarator: (abstract_parenthesized_declarator
                (abstract_pointer_declarator))
              parameters: (parameter_list
                (parameter_declaration
                  type: (id))
                (parameter_declaration
                  type: (SEL))
                (parameter_declaration
                  type: (id))
                (parameter_declaration
                  type: (id))
                (parameter_declaration
                  type: (id))
                (parameter_declaration
                  type: (id))
                (parameter_declaration
                  type: (primitive_type)
                  declarator: (block_abstract_declarator
                    parameters: (parameter_list
                      (parameter_declaration
                        type: (type_identifier)
                        declarator: (abstract_pointer_declarator))))))))
          value: (identifier)))
      arguments: (argument_list
        (identifier)
        (identifier)
        (identifier)
        (identifier)
        (identifier)
        (identifier)
        (identifier)))))

================================================================================
Blocks: expression
================================================================================

[self.KVOController observe:imageView keyPaths:@[NSStringFromSelector(@selector(currentFrameIndex)), NSStringFromSelector(@selector(currentLoopCount))] options:NSKeyValueObservingOptionNew block:^(id  _Nullable observer, id  _Nonnull object, NSDictionary<NSString *,id> * _Nonnull change) {
}];

--------------------------------------------------------------------------------

(translation_unit
  (expression_statement
    (message_expression
      receiver: (field_expression
        argument: (self)
        field: (field_identifier))
      selector: (keyword_argument_list
        (keyword_argument
          keyword: (identifier)
          argument: (identifier))
        (keyword_argument
          keyword: (identifier)
          argument: (array_expression
            (call_expression
              function: (identifier)
              arguments: (argument_list
                (selector_expression
                  name: (identifier))))
            (call_expression
              function: (identifier)
              arguments: (argument_list
                (selector_expression
                  name: (identifier))))))
        (keyword_argument
          keyword: (identifier)
          argument: (identifier))
        (keyword_argument
          keyword: (identifier)
          argument: (block_expression
            parameters: (parameter_list
              (parameter_declaration
                type: (id)
                (type_qualifier)
                declarator: (identifier))
              (parameter_declaration
                type: (id)
                (type_qualifier)
                declarator: (identifier))
              (parameter_declaration
                type: (generic_type_specifier
                  class_name: (type_identifier)
                  type_reference: (generic_type_references
                    (type_descriptor
                      type: (type_identifier)
                      declarator: (abstract_pointer_declarator))
                    (type_descriptor
                      type: (id))))
                declarator: (pointer_declarator
                  (type_qualifier)
                  declarator: (identifier))))
            (compound_statement)))))))

================================================================================
Blocks: as a instance variable
================================================================================

@interface FLEXVariableEditorViewController : UIViewController {
    @protected
    void (^_Nullable _commitHandler)();
}
@end


--------------------------------------------------------------------------------

(translation_unit
  (class_interface
    name: (identifier)
    (superclass_reference
      name: (identifier))
    (protected)
    (field_declaration
      type: (primitive_type)
      declarator: (block_declarator
        (type_qualifier)
        declarator: (identifier)
        parameters: (parameter_list)))))

================================================================================
Blocks: unknown [FIXME]
================================================================================

extern void use(id);
extern void use_block(void (^)(void));

void use_block(int (^block_t)(void)) {
  block_t();
  return;
}

void test7(void) {
  use_block(^{return 1;});
}

// int (^square(int x))(void) {
//   return ^{ return x * x; };
// }

void test8(void) {
  int (^square_block)(void) = square(4);
  int i = square_block();
  NSLog(@"%d", i);
}

void (^simpleBlock)() = ^ _Nonnull { //expected-warning {{attribute '_Nonnull' ignored, because it cannot be applied to omitted return type}}
  return;
};

void (^simpleBlock6)() = ^ const (void) { //expected-warning {{'const' qualifier on omitted return type '<dependent type>' has no effect}}
  return;
};

--------------------------------------------------------------------------------

(translation_unit
  (declaration
    (storage_class_specifier)
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (id)))))
  (declaration
    (storage_class_specifier)
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (primitive_type)
          declarator: (block_abstract_declarator
            parameters: (parameter_list
              (parameter_declaration
                type: (primitive_type))))))))
  (function_definition
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (primitive_type)
          declarator: (block_declarator
            declarator: (identifier)
            parameters: (parameter_list
              (parameter_declaration
                type: (primitive_type)))))))
    body: (compound_statement
      (expression_statement
        (call_expression
          function: (identifier)
          arguments: (argument_list)))
      (return_statement)))
  (function_definition
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (primitive_type))))
    body: (compound_statement
      (expression_statement
        (call_expression
          function: (identifier)
          arguments: (argument_list
            (block_expression
              (compound_statement
                (return_statement
                  (number_literal)))))))))
  (comment)
  (comment)
  (comment)
  (function_definition
    type: (primitive_type)
    declarator: (function_declarator
      declarator: (identifier)
      parameters: (parameter_list
        (parameter_declaration
          type: (primitive_type))))
    body: (compound_statement
      (declaration
        type: (primitive_type)
        declarator: (init_declarator
          declarator: (block_declarator
            declarator: (identifier)
            parameters: (parameter_list
              (parameter_declaration
                type: (primitive_type))))
          value: (call_expression
            function: (identifier)
            arguments: (argument_list
              (number_literal)))))
      (declaration
        type: (primitive_type)
        declarator: (init_declarator
          declarator: (identifier)
          value: (call_expression
            function: (identifier)
            arguments: (argument_list))))
      (expression_statement
        (call_expression
          function: (identifier)
          arguments: (argument_list
            (string_expression)
            (identifier))))))
  (declaration
    type: (primitive_type)
    declarator: (init_declarator
      declarator: (block_declarator
        declarator: (identifier)
        parameters: (parameter_list))
      value: (block_expression
        declarator: (type_qualifier)
        (compound_statement
          (comment)
          (return_statement)))))
  (declaration
    type: (primitive_type)
    declarator: (init_declarator
      declarator: (block_declarator
        declarator: (identifier)
        parameters: (parameter_list))
      value: (block_expression
        declarator: (type_qualifier)
        parameters: (parameter_list
          (parameter_declaration
            type: (primitive_type)))
        (compound_statement
          (comment)
          (return_statement))))))

================================================================================
IMP: type definition and cast expression
================================================================================

// id (*IMP)(id, SEL, ...)
typedef NSObject * (* typedefIMP)(id thisSelf, SEL selector, NSString *filePath);

CGFloat (* msgSendIMP)(id, SEL, id, CGFloat) = (CGFloat (*)(id, SEL, id, CGFloat))objc_msgSend;

@interface NSMutableArray<T> : NSObject <NSCopying>
- (void)sortWithFunction:(int (*)(T, T))function;
- (void)getObjects:(T __strong *)objects length:(unsigned*)length;
@end


--------------------------------------------------------------------------------

(translation_unit
  (comment)
  (type_definition
    type: (type_identifier)
    declarator: (pointer_declarator
      declarator: (function_declarator
        declarator: (parenthesized_declarator
          (pointer_declarator
            declarator: (type_identifier)))
        parameters: (parameter_list
          (parameter_declaration
            type: (id)
            declarator: (identifier))
          (parameter_declaration
            type: (SEL)
            declarator: (identifier))
          (parameter_declaration
            type: (type_identifier)
            declarator: (pointer_declarator
              declarator: (identifier)))))))
  (expression_statement
    (assignment_expression
      left: (call_expression
        function: (call_expression
          function: (identifier)
          arguments: (argument_list
            (pointer_expression
              argument: (identifier))))
        arguments: (argument_list
          (identifier)
          (identifier)
          (identifier)
          (identifier)))
      right: (cast_expression
        type: (type_descriptor
          type: (type_identifier)
          declarator: (abstract_function_declarator
            declarator: (abstract_parenthesized_declarator
              (abstract_pointer_declarator))
            parameters: (parameter_list
              (parameter_declaration
                type: (id))
              (parameter_declaration
                type: (SEL))
              (parameter_declaration
                type: (id))
              (parameter_declaration
                type: (type_identifier)))))
        value: (identifier))))
  (class_interface
    name: (identifier)
    (protocol_qualifiers
      (protocol_identifier))
    (superclass_reference
      name: (identifier)
      type_reference: (generic_type_references
        (type_descriptor
          type: (type_identifier))))
    (method_declaration
      scope: (instance_scope)
      type: (primitive_type)
      selector: (keyword_selector
        (keyword_declarator
          keyword: (identifier)
          type: (primitive_type)
          declarator: (abstract_function_declarator
            declarator: (abstract_parenthesized_declarator
              (abstract_pointer_declarator))
            parameters: (parameter_list
              (parameter_declaration
                type: (type_identifier))
              (parameter_declaration
                type: (type_identifier))))
          name: (identifier))))
    (method_declaration
      scope: (instance_scope)
      type: (primitive_type)
      selector: (keyword_selector
        (keyword_declarator
          keyword: (identifier)
          type: (type_identifier)
          type: (type_qualifier)
          declarator: (abstract_pointer_declarator)
          name: (identifier))
        (keyword_declarator
          keyword: (identifier)
          type: (sized_type_specifier)
          declarator: (abstract_pointer_declarator)
          name: (identifier))))))

================================================================================
Blocks: block type in block declaration parameter_list
================================================================================

// void (^GlobalBlockName())(NSIndexPath *indexPath, BOOL isOn) {
//   return ^(NSIndexPath * _Nonnull indexPath, BOOL isOn) {
//   };
// }

// void (^GlobalBlockName(NSString *event, NSString *type))(NSIndexPath *indexPath, BOOL isOn) {
//     return ^(NSIndexPath * _Nonnull indexPath, BOOL isOn) {
//     };
// }

--------------------------------------------------------------------------------

(translation_unit
  (comment)
  (comment)
  (comment)
  (comment)
  (comment)
  (comment)
  (comment)
  (comment))
