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

int main() {
  if (a)
    1;

  if (!a) {
    2;
  } else {
    3;
  }
}

---

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator (identifier) (parameter_list))
    (compound_statement
      (if_statement (parenthesized_expression (identifier))
        (expression_statement (number_literal)))
      (if_statement (parenthesized_expression (unary_expression (identifier)))
        (compound_statement
          (expression_statement (number_literal)))
        (compound_statement
          (expression_statement (number_literal)))))))

============================================
For loops
============================================

int main() {
  for (;;)
    1;

  for (int i = 0; i < 5; next(), i++) {
    2;
  }

  for (start(); check(); step())
    3;

  for (i = 0, j = 0, k = 0, l = 0; i < 1, j < 1; i++, j++, k++, l++)
    1;
}

---

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator (identifier) (parameter_list))
    (compound_statement
      (for_statement
        (expression_statement (number_literal)))
      (for_statement
        (declaration (primitive_type) (init_declarator (identifier) (number_literal)))
        (binary_expression (identifier) (number_literal))
        (comma_expression
          (call_expression (identifier) (argument_list))
          (update_expression (identifier)))
        (compound_statement (expression_statement (number_literal))))
      (for_statement
        (call_expression (identifier) (argument_list))
        (call_expression (identifier) (argument_list))
        (call_expression (identifier) (argument_list))
        (expression_statement (number_literal)))
      (for_statement
        (comma_expression
          (assignment_expression (identifier) (number_literal))
          (comma_expression
            (assignment_expression (identifier) (number_literal))
            (comma_expression
              (assignment_expression (identifier) (number_literal))
              (assignment_expression (identifier) (number_literal)))))
        (comma_expression
          (binary_expression
            (identifier)
            (number_literal))
          (binary_expression
            (identifier)
            (number_literal)))
        (comma_expression
          (update_expression (identifier))
          (comma_expression
            (update_expression (identifier))
            (comma_expression
              (update_expression (identifier))
              (update_expression (identifier)))))
        (expression_statement (number_literal))))))

============================================
While loops
============================================

int main() {
  while (x)
    printf("hi");
}

---

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator (identifier) (parameter_list))
    (compound_statement
      (while_statement (parenthesized_expression (identifier))
        (expression_statement (call_expression
          (identifier)
          (argument_list (string_literal))))))))

============================================
Labeled statements
============================================

void foo(T *t) {
recur:
  t = t->next();
  if (t) goto recur;
}

---

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator (identifier) (parameter_list
      (parameter_declaration (type_identifier) (pointer_declarator (identifier)))))
    (compound_statement
      (labeled_statement (statement_identifier)
        (expression_statement (assignment_expression
          (identifier)
          (call_expression (field_expression (identifier) (field_identifier)) (argument_list)))))
      (if_statement (parenthesized_expression (identifier)) (goto_statement (statement_identifier))))))

============================================
Switch statements
============================================

void foo(int a) {
  switch (a) {
    puts("entered switch!");

    case 3:
    case 5:
      if (b) {
        c();
      }
      break;

    default:
      c();
      break;
  }
}

---

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator (identifier) (parameter_list
      (parameter_declaration (primitive_type) (identifier))))
    (compound_statement
      (switch_statement
        (parenthesized_expression (identifier))
        (compound_statement
          (expression_statement (call_expression (identifier) (argument_list (string_literal))))
          (case_statement (number_literal))
          (case_statement (number_literal)
            (if_statement
              (parenthesized_expression (identifier))
              (compound_statement (expression_statement (call_expression (identifier) (argument_list)))))
            (break_statement))
          (case_statement
            (expression_statement (call_expression (identifier) (argument_list)))
            (break_statement)))))))

============================================
Case statements separate from switch statements
============================================

int main() {
  switch (count % 8) {
  case 0:
    do {
      *to = *from++;
      case 2: *to = *from++;
      case 1: *to = *from++;
    } while (--n > 0);
  }
}

---

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator (identifier) (parameter_list))
    (compound_statement
      (switch_statement
        (parenthesized_expression (binary_expression (identifier) (number_literal)))
        (compound_statement
          (case_statement (number_literal)
            (do_statement
              (compound_statement
                (expression_statement (assignment_expression
                  (pointer_expression (identifier))
                  (pointer_expression (update_expression (identifier)))))
                (case_statement (number_literal)
                  (expression_statement (assignment_expression
                    (pointer_expression (identifier))
                    (pointer_expression (update_expression (identifier))))))
                (case_statement (number_literal)
                  (expression_statement (assignment_expression
                    (pointer_expression (identifier))
                    (pointer_expression (update_expression (identifier)))))))
              (parenthesized_expression (binary_expression (update_expression (identifier)) (number_literal))))))))))

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

void foo() {
  return;
  return a;
  return a, b;
}

---

(translation_unit
  (function_definition
    (primitive_type)
    (function_declarator (identifier) (parameter_list))
    (compound_statement
      (return_statement)
      (return_statement (identifier))
      (return_statement (comma_expression (identifier) (identifier))))))

============================================
Comments with asterisks
============================================

/*************************
 * odd number of asterisks
 *************************/
int a;

/**************************
 * even number of asterisks
 **************************/
int b;

---

(translation_unit
  (comment)
  (declaration (primitive_type) (identifier))
  (comment)
  (declaration (primitive_type) (identifier)))

============================================
Attributes
============================================

void f() {
  [[a]] switch (b) {
   [[c]] case 1: {}
   case 2:
     [[fallthrough]];
   default:
  }
  [[a]] while (true) {}
  [[a]] if (true) {}
  [[a]] for (;;) {}
  [[a]] return;
  [[a]] a;
  [[a]];
  [[a]] label: {}
  [[a]] goto label;

  // these are c++ specific, but their bind locations should be c-compatible
  if (true) [[likely]] {} else [[unlikely]] {}
  do [[likely]] {} while (true);
}

---

(translation_unit
  (function_definition (primitive_type)
    (function_declarator (identifier) (parameter_list))
      (compound_statement
        (attributed_statement
          (attribute_declaration (attribute (identifier)))
          (switch_statement
            (parenthesized_expression (identifier))
            (compound_statement
              (attributed_statement
                (attribute_declaration (attribute (identifier)))
                (case_statement (number_literal) (compound_statement)))
              (case_statement (number_literal)
                (attributed_statement
                  (attribute_declaration (attribute (identifier)))
                  (expression_statement)))
              (case_statement))))
        (attributed_statement (attribute_declaration (attribute (identifier))) (while_statement (parenthesized_expression (true)) (compound_statement)))
        (attributed_statement (attribute_declaration (attribute (identifier))) (if_statement (parenthesized_expression (true)) (compound_statement)))
        (attributed_statement (attribute_declaration (attribute (identifier))) (for_statement (compound_statement)))
        (attributed_statement (attribute_declaration (attribute (identifier))) (return_statement))
        (attributed_statement (attribute_declaration (attribute (identifier))) (expression_statement (identifier)))
        (attributed_statement (attribute_declaration (attribute (identifier))) (expression_statement))
        (attributed_statement (attribute_declaration (attribute (identifier))) (labeled_statement (statement_identifier) (compound_statement)))
        (attributed_statement (attribute_declaration (attribute (identifier))) (goto_statement (statement_identifier)))
        (comment)
        (if_statement
          (parenthesized_expression (true))
          (attributed_statement (attribute_declaration (attribute (identifier))) (compound_statement))
          (attributed_statement (attribute_declaration (attribute (identifier))) (compound_statement)))
        (do_statement
          (attributed_statement (attribute_declaration (attribute (identifier))) (compound_statement))
          (parenthesized_expression (true))))))
