===============================
Call expressions
===============================

class C {
  def main() {
    a()
    a(123)
    a(b, c)
    a.map(x => x + 1)
    a { 123 }
    a { b }
    a.map{ x => x + 1 }
    a.exists { case ((i, _)) => i }
  }
}

---

(compilation_unit
  (class_definition
    (identifier)
    (template_body
      (function_definition
        (identifier)
        (parameters)
        (block
          (call_expression (identifier) (arguments))
          (call_expression (identifier) (arguments (integer_literal)))
          (call_expression (identifier) (arguments (identifier) (identifier)))
          (call_expression (field_expression (identifier) (identifier)) (arguments
            (lambda_expression (identifier)
                (infix_expression (identifier) (operator_identifier) (integer_literal)))))
          (call_expression (identifier) (block (integer_literal)))
          (call_expression (identifier) (block (identifier)))
          (call_expression (field_expression (identifier) (identifier)) (block
            (lambda_expression (identifier)
                (infix_expression (identifier) (operator_identifier) (integer_literal)))))
          (call_expression (field_expression (identifier) (identifier)) (case_block (case_clause
            (tuple_pattern (tuple_pattern (identifier) (wildcard))) (identifier)))))))))

===============================
Generic functions
===============================

class C {
  def main() {
    a[T]()
    List[Traversable[ClassPath]]()
  }
}

---

(compilation_unit
  (class_definition
    (identifier)
    (template_body
      (function_definition
        (identifier)
        (parameters)
        (block
          (call_expression
            (generic_function
              (identifier)
              (type_arguments (type_identifier)))
            (arguments))
          (call_expression
            (generic_function
              (identifier)
              (type_arguments
                (generic_type (type_identifier) (type_arguments (type_identifier)))))
            (arguments)))))))

===============================
Assignments
===============================

class C {
  def main() {
    a = b
    a(1) = c
  }
}

---

(compilation_unit
  (class_definition
    (identifier)
    (template_body
      (function_definition
        (identifier)
        (parameters)
        (block
          (assignment_expression (identifier) (identifier))
          (assignment_expression (call_expression (identifier) (arguments (integer_literal))) (identifier))
        )
      )
    )
  )
)

===============================
If expressions
===============================

class C {
  def main() {
    if (a) b()
    if (c) {
      d()
      e()
    } else if (f) {
      g()
    } else {
      h()
    }
  }
}

def other() {
  if (a) {
    b
  }
  else c()
}

---

(compilation_unit
  (class_definition
    (identifier)
    (template_body
      (function_definition
        (identifier)
        (parameters)
        (block
          (if_expression
            (parenthesized_expression (identifier))
            (call_expression (identifier) (arguments)))
          (if_expression
            (parenthesized_expression (identifier))
            (block (call_expression (identifier) (arguments)) (call_expression (identifier) (arguments)))
            (if_expression
              (parenthesized_expression (identifier))
              (block (call_expression (identifier) (arguments)))
              (block (call_expression (identifier) (arguments)))))))))
  (function_definition
    (identifier)
    (parameters)
    (block
      (if_expression
        (parenthesized_expression (identifier))
        (block (identifier))
        (call_expression (identifier) (arguments))))))

===============================
Try expressions
===============================

def main() {
  try a() finally depth -= 1
  try {
    doThing()
  } catch {
    case e: SomeException => prinlnt(e.message)
    case NonFatal(ex) => throw new SomeException(ex)
  } finally {
    tryAnotherThing()
  }
  try b()
  catch { case e => println(e) }
  finally doFinalThing()
  try a()
  finally b()
}

---

(compilation_unit
  (function_definition
    (identifier)
    (parameters)
    (block
      (try_expression
        (call_expression (identifier) (arguments))
        (finally_clause (infix_expression (identifier) (operator_identifier) (integer_literal))))
      (try_expression
        (block (call_expression (identifier) (arguments)))
        (catch_clause
          (case_block
            (case_clause
              (typed_pattern
                (identifier)
                (type_identifier))
              (call_expression
                (identifier)
                (arguments (field_expression
                  (identifier)
                  (identifier)))))
            (case_clause
              (case_class_pattern
                (type_identifier)
                (identifier))
              (throw_expression (instance_expression (call_expression (identifier) (arguments (identifier))))
              )
            )
          )
        )
        (finally_clause (block (call_expression (identifier) (arguments))))
        )
      (try_expression (call_expression (identifier) (arguments))
        (catch_clause (case_block (case_clause
          (identifier) 
          (call_expression
            (identifier)
            (arguments (identifier))))))
        (finally_clause (call_expression (identifier) (arguments))))
      (try_expression (call_expression (identifier) (arguments))
        (finally_clause (call_expression (identifier) (arguments)))))))

===============================
Match expressions
===============================

def matchTest(x: Int): String = x match {
  case 0 =>
  case 1 => "one"; "uno"
  case 2 => "two"
  case 3 => {
    "3"
  }
  case ((i, _)) => i
  case _ =>
    val x = "many"
    "more"
}

---

(compilation_unit
  (function_definition
    (identifier)
    (parameters (parameter (identifier) (type_identifier)))
    (type_identifier)
    (match_expression (identifier) (case_block
      (case_clause (integer_literal))
      (case_clause (integer_literal) (string) (string))
      (case_clause (integer_literal) (string))
      (case_clause (integer_literal) (block (string)))
      (case_clause (tuple_pattern (tuple_pattern (identifier) (wildcard))) (identifier))
      (case_clause (wildcard) (val_definition (identifier) (string)) (string))))))

===============================
Field expressions
===============================

class C {
  def main() {
    a.b = c
    a.b.d
  }
}

---

(compilation_unit
  (class_definition
    (identifier)
    (template_body
      (function_definition
        (identifier)
        (parameters)
        (block
          (assignment_expression
            (field_expression (identifier) (identifier))
            (identifier))
          (field_expression
            (field_expression (identifier) (identifier))
            (identifier)))))))

===============================
Instance expressions
===============================

class C {
  def main() {
    a = new B
    c = new D(e, f)
  }
}

---

(compilation_unit
  (class_definition
    (identifier)
    (template_body
      (function_definition
        (identifier)
        (parameters)
        (block
          (assignment_expression (identifier) (instance_expression (identifier)))
          (assignment_expression (identifier) (instance_expression (call_expression (identifier) (arguments (identifier) (identifier))))))))))

===============================
Infix expressions
===============================

class C {
  def main() {
    a = b max c
    d + e + f
  }
}

---

(compilation_unit
  (class_definition
    (identifier)
    (template_body
      (function_definition
        (identifier)
        (parameters)
        (block
          (assignment_expression
            (identifier)
            (infix_expression (identifier) (identifier) (identifier)))
          (infix_expression
            (infix_expression (identifier) (operator_identifier) (identifier))
            (operator_identifier)
            (identifier)))))))

===============================
Prefix expressions
===============================

class C {
  def main() {
    !a
    !!a
    +a + b
  }
}

---

(compilation_unit
  (class_definition
    (identifier)
    (template_body
      (function_definition
        (identifier)
        (parameters)
        (block
          (prefix_expression (identifier))
          (prefix_expression (prefix_expression (identifier)))
          (infix_expression
            (prefix_expression (identifier))
            (operator_identifier)
            (identifier)))))))

===============================
Postfix expressions
===============================

object O {
  val v = "value" toUpperCase
  val c = 1 + 2 toString
}

---

(compilation_unit
  (object_definition
    (identifier)
    (template_body
      (val_definition
        (identifier)
        (postfix_expression (string) (identifier)))
      (val_definition
        (identifier)
        (postfix_expression
          (infix_expression (integer_literal) (operator_identifier) (integer_literal))
          (identifier)
          )
        )
      )
    )
  )

===============================
Ascription Expression
===============================

object O {
  val l = a: List
  val x = 2: Byte
  Nil: List[String]
  3: _*
}

---

(compilation_unit
  (object_definition
    (identifier)
    (template_body
      (val_definition (identifier)
        (ascription_expression (identifier)
          (type_identifier)))
      (val_definition (identifier)
        (ascription_expression (integer_literal)
          (type_identifier)))
      (ascription_expression (identifier)
        (generic_type (type_identifier)
          (type_arguments (type_identifier))))
      (ascription_expression (integer_literal)
        (repeated_parameter_type (type_identifier))))))

================================================================================
Lambda Expression
================================================================================

object O {
  val l = a => a + 1
  val b = (x: Int, y: Int) => { x * y }
  val f = _ => 2
  (a, b, _) => a - b
  foo { i => val x = 2 + i }
}

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

(compilation_unit
  (object_definition (identifier)
    (template_body (val_definition
        (identifier) (lambda_expression
          (identifier) (infix_expression
            (identifier) (operator_identifier) (integer_literal))))
      (val_definition (identifier)
        (lambda_expression (bindings
            (binding (identifier) (type_identifier))
            (binding (identifier) (type_identifier)))
          (block (infix_expression
              (identifier) (operator_identifier) (identifier)))))
      (val_definition (identifier)
        (lambda_expression (identifier) (integer_literal)))
      (lambda_expression
        (bindings
          (binding (identifier))
          (binding (identifier))
          (binding (identifier)))
        (infix_expression (identifier)
          (operator_identifier)
          (identifier)))
      (call_expression
        (identifier)
        (block (lambda_expression
          (identifier)
          (val_definition (identifier) (infix_expression (integer_literal) (operator_identifier) (identifier)))))))))

===============================
Unit expressions
===============================

val x = ()
def f(): Unit = { (   
); }

---
(compilation_unit
  (val_definition (identifier) (unit))
  (function_definition (identifier) (parameters) (type_identifier) (block (unit)))
  )

===============================
Return expressions
===============================

def f: Unit = return
def g(a: A): B = { f(); return null.asInstanceOf[B] }

---

(compilation_unit
  (function_definition (identifier) (type_identifier) (return_expression))
  (function_definition
    (identifier)
    (parameters (parameter (identifier) (type_identifier)))
    (type_identifier)
    (block
      (call_expression
        (identifier)
        (arguments))
      (return_expression
        (generic_function (field_expression (null_literal) (identifier))
        (type_arguments (type_identifier))))
      )
    )
  )

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

def f = {
  while(a) g()
  while(b < c) {
    d
  }
}

---

(compilation_unit
  (function_definition
    (identifier)
    (block
      (while_expression
        (parenthesized_expression (identifier))
        (call_expression (identifier) (arguments)))
      (while_expression
        (parenthesized_expression (infix_expression (identifier) (operator_identifier) (identifier)))
        (block (identifier))))))

===============================
Do-while loops
===============================

def f() = {
  do g(a, b) while(c && d)
  do {
    g(a, b)
    h(a, b)
  } while (c < d)
}

---

(compilation_unit
  (function_definition
    (identifier)
    (parameters)
    (block
      (do_while_expression
        (call_expression (identifier) (arguments (identifier) (identifier)))
        (parenthesized_expression (infix_expression (identifier) (operator_identifier) (identifier))))
      (do_while_expression
        (block
          (call_expression (identifier) (arguments (identifier) (identifier)))
          (call_expression (identifier) (arguments (identifier) (identifier))))
        (parenthesized_expression (infix_expression (identifier) (operator_identifier) (identifier)))))))

===============================
For comprehensions
===============================

def f() = {
  for (n <- nums) yield n + 1
  for (x <- xs; y <- ys) g(x, y)
  for {
    x <- xs
    a = b + c
    y <- g() if d
    (t, u) = y
  } yield {
    h(x, y)
  }
}

---

(compilation_unit
 (function_definition
   (identifier)
   (parameters)
   (block
     (for_expression
       (enumerators (enumerator (identifier) (identifier)))
       (infix_expression (identifier) (operator_identifier) (integer_literal)))
     (for_expression
       (enumerators
         (enumerator (identifier) (identifier))
         (enumerator (identifier) (identifier)))
       (call_expression (identifier) (arguments (identifier) (identifier))))
     (for_expression
       (enumerators
         (enumerator (identifier) (identifier))
         (enumerator (identifier) (infix_expression (identifier) (operator_identifier) (identifier)))
         (enumerator (identifier) (call_expression (identifier) (arguments)) (guard (identifier)))
         (enumerator (tuple_pattern (identifier) (identifier)) (identifier)))
       (block (call_expression (identifier) (arguments (identifier) (identifier))))))))

===============================
Chained expressions
===============================

def main() {
  val myList = List(1, 2, 3)

  myList.map(_ * 2)

  myList
    .map(_ * 2)

  myList
    .length
}

---

(compilation_unit
  (function_definition
    (identifier)
    (parameters)
    (block
      (val_definition (identifier) (call_expression
        (identifier)
        (arguments (integer_literal) (integer_literal) (integer_literal))))
      (call_expression
        (field_expression (identifier) (identifier))
        (arguments (infix_expression
          (identifier) (operator_identifier) (integer_literal))))
      (call_expression
        (field_expression (identifier) (identifier))
        (arguments (infix_expression
          (identifier) (operator_identifier) (integer_literal))))
      (field_expression (identifier) (identifier)))))
