==============================
compound statements
==============================

begin
end

begin
    foo
    bar
    baz
end

---

(source_file
  (compound_statement)
  (compound_statement
    (identifier)
    (identifier)
    (identifier)))


==============================
quote statements
==============================

quote end

quote
  x = 1
  y = 2
  x + y
end

---

(source_file
  (quote_statement)
  (quote_statement
    (assignment (identifier) (operator) (integer_literal))
    (assignment (identifier) (operator) (integer_literal))
    (binary_expression (identifier) (operator) (identifier))))


==============================
let statements
==============================

let
end

let var1 = value1, var2, var3 = value3
    code
end

---

(source_file
  (let_statement)
  (let_statement
    (let_binding (identifier) (operator) (identifier))
    (identifier)
    (let_binding (identifier) (operator) (identifier))
    (identifier)))


==============================
if statements
==============================

if a
elseif b
else
end

if true 1 else 0 end

if a
  b()
elseif c
  d()
  d()
else
  e()
end

---

(source_file

  (if_statement
    (identifier)
    (elseif_clause
      (identifier))
    (else_clause))

  (if_statement
    (boolean_literal)
    (integer_literal)
    (else_clause
      (integer_literal)))

  (if_statement
    (identifier)
    (call_expression (identifier) (argument_list))
    (elseif_clause
      (identifier)
      (call_expression (identifier) (argument_list))
      (call_expression (identifier) (argument_list)))
    (else_clause
      (call_expression (identifier) (argument_list)))))


==============================
try statements
==============================

try catch end
try finally end

try
    sqrt(x)
catch
    sqrt(complex(x, 0))
end

try
    operate_on_file(f)
finally
    close(f)
end

try
    # fallible
catch
    # handle errors
else
    # do something if there were no exceptions
end

---

(source_file
  (try_statement
    (catch_clause))

  (try_statement
    (finally_clause))

  (try_statement
    (call_expression (identifier) (argument_list (identifier)))
    (catch_clause
      (call_expression
        (identifier)
        (argument_list
          (call_expression (identifier) (argument_list (identifier) (integer_literal)))))))

  (try_statement
    (call_expression (identifier) (argument_list (identifier)))
    (finally_clause
      (call_expression (identifier) (argument_list (identifier)))))

  (try_statement
    (line_comment)
    (catch_clause)
    (line_comment)
    (else_clause)
    (line_comment)))



==============================
for statements
==============================

for x in xs end

for x in xs foo!(x) end

for i in [1, 2, 3]
  print(i)
end

for (a, b) in c
  print(a, b)
end

---

(source_file
  (for_statement
    (for_binding
      (identifier)
      (identifier)))

  (for_statement
    (for_binding
      (identifier)
      (identifier))
    (call_expression (identifier) (argument_list (identifier))))

  (for_statement
    (for_binding
      (identifier)
      (vector_expression (integer_literal) (integer_literal) (integer_literal)))
    (call_expression (identifier) (argument_list (identifier))))

  (for_statement
    (for_binding
      (tuple_expression (identifier) (identifier))
      (identifier))
    (call_expression (identifier) (argument_list (identifier) (identifier)))))


==============================
for outer statements
==============================

n = 1
for outer n in range
  body
end

for outer x = iter1, outer y = iter2
  body
end

---
(source_file
  (assignment (identifier) (operator) (integer_literal))
  (for_statement
    (for_binding (identifier) (identifier))
    (identifier))
  (for_statement
    (for_binding (identifier) (identifier))
    (for_binding (identifier) (identifier))
    (identifier)))


==============================
while statements
==============================

while true end

while i < 5
  print(i)
  continue
  break
end

while a(); b(); end

---

(source_file
  (while_statement (boolean_literal))

  (while_statement
    (binary_expression (identifier) (operator) (integer_literal))
    (call_expression (identifier) (argument_list (identifier)))
    (continue_statement)
    (break_statement))

  (while_statement
    (call_expression (identifier) (argument_list))
    (call_expression (identifier) (argument_list))))


==============================
return statements
==============================

return
return a
return a || b
return a, b, c

---

(source_file
  (return_statement)
  (return_statement (identifier))
  (return_statement (binary_expression (identifier) (operator) (identifier)))
  (return_statement (open_tuple (identifier) (identifier) (identifier))))


==============================
export statements
==============================

export a
export a, b, +, (*)
export @macroMcAtface

---

(source_file
  (export_statement (identifier))
  (export_statement (identifier) (identifier) (operator) (operator))
  (export_statement (macro_identifier (identifier))))


==============================
import statements
==============================

import Pkg

using Sockets

using ..Foo, ..Bar

import CSV, Chain, DataFrames

import Base: show, @kwdef, +, (*)

import LinearAlgebra as la

import Base: @view as @v


---

(source_file
  ;; Simple import
  (import_statement (identifier))
  (import_statement (identifier))

  ;; Relative paths
  (import_statement
    (import_path (identifier))
    (import_path (identifier)))

  ;; List import
  (import_statement (identifier) (identifier) (identifier))

  ;; Selected import
  (import_statement
    (selected_import
      (identifier)
      (identifier)
      (macro_identifier (identifier))
      (operator)
      (operator)))

  ;; Alias
  (import_statement (import_alias (identifier) (identifier)))
  (import_statement
    (selected_import
      (identifier)
      (import_alias (macro_identifier (identifier)) (macro_identifier (identifier))))))


===============================
const statements
===============================

const x = 5
const y, z = 1, 2

(0, const x, y = 1, 2)

---

(source_file
  (const_statement
    (assignment (identifier) (operator) (integer_literal)))
  (const_statement
    (assignment
    (open_tuple (identifier) (identifier))
    (operator)
    (open_tuple (integer_literal) (integer_literal))))
  ; const statements inside tuples
  (tuple_expression
    (integer_literal)
    (const_statement
      (assignment
        (open_tuple (identifier) (identifier))
        (operator)
        (open_tuple (integer_literal) (integer_literal))))))


===============================
local statements
===============================

local x
local y, z = 1, 2
local foo() = 3
local function bar() 4 end

---

(source_file
  (local_statement (identifier))
  (local_statement
    (assignment
    (open_tuple (identifier) (identifier))
    (operator)
    (open_tuple (integer_literal) (integer_literal))))
  (local_statement
    (assignment
      (call_expression (identifier) (argument_list))
      (operator)
      (integer_literal)))
  (local_statement
    (function_definition
      (signature
        (call_expression (identifier) (argument_list)))
        (integer_literal))))


===============================
global statements
===============================

global X
global Y, Z = 11, 42
global foo() = 3
global function bar() 4 end

---

(source_file
  (global_statement (identifier))
  (global_statement
    (assignment
    (open_tuple (identifier) (identifier))
    (operator)
    (open_tuple (integer_literal) (integer_literal))))
  (global_statement
    (assignment
      (call_expression (identifier) (argument_list))
      (operator)
      (integer_literal)))
  (global_statement
    (function_definition
      (signature
        (call_expression (identifier) (argument_list)))
        (integer_literal))))
