================
pattern matching
================

case expr
  in 5 then true
  else false
end

case expr
  in x unless x < 0
  then true
  in x if x < 0
  then true
  else false
end

case expr
  in 5
  in 5, 
  in 1, 2 
  in 1, 2, 
  in 1, 2, 3 
  in 1, 2, 3, 
  in 1, 2, 3, * 
  in 1, *x, 3 
  in * 
  in *, 3, 4 
  in *, 3, * 
  in *a, 3, *b 
  in a: 
  in a: 5 
  in a: 5, 
  in a: 5, b:, ** 
  in a: 5, b:, **map 
  in a: 5, b:, **nil 
  in **nil 
  in [5] 
  in [5,] 
  in [1, 2] 
  in [1, 2,] 
  in [1, 2, 3] 
  in [1, 2, 3,] 
  in [1, 2, 3, *] 
  in [1, *x, 3] 
  in [*] 
  in [*, 3, 4] 
  in [*, 3, *] 
  in [*a, 3, *b] 
  in {a:} 
  in {a: 5} 
  in {a: 5,} 
  in {a: 5, b:, **} 
  in {a: 5, b:, **map} 
  in {a: 5, b:, **nil} 
  in {**nil} 
  in {} 
  in [] 
end

-----

(program 
  (case_match (identifier) 
    (in_clause 
      (integer)
      (then (true))
    )
    (else (false))) 
  (case_match (identifier) 
    (in_clause 
      (identifier)
      (unless_guard (binary (identifier) (integer)))
      (then (true))
    )
    (in_clause 
      (identifier)
      (if_guard (binary (identifier) (integer)))
      (then (true))
    )
    (else (false))
  )

  (case_match (identifier)
    (in_clause (integer)) 
    (in_clause (array_pattern (integer) (splat_parameter))) 
    (in_clause (array_pattern (integer) (integer))) 
    (in_clause (array_pattern (integer) (integer) (splat_parameter))) 
    (in_clause (array_pattern (integer) (integer) (integer))) 
    (in_clause (array_pattern (integer) (integer) (integer) (splat_parameter))) 
    (in_clause (array_pattern (integer) (integer) (integer) (splat_parameter))) 
    (in_clause (array_pattern (integer) (splat_parameter (identifier)) (integer))) 
    (in_clause (array_pattern (splat_parameter))) 
    (in_clause (array_pattern (splat_parameter) (integer) (integer))) 
    (in_clause (find_pattern (splat_parameter) (integer) (splat_parameter))) 
    (in_clause (find_pattern (splat_parameter (identifier)) (integer) (splat_parameter (identifier)))) 
    (in_clause (hash_pattern (keyword_pattern (hash_key_symbol)))) 
    (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)))) 
    (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)))) 
    (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_parameter))) 
    (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_parameter (identifier)))) 
    (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_nil))) 
    (in_clause (hash_pattern (hash_splat_nil))) 
    (in_clause (array_pattern (integer))) 
    (in_clause (array_pattern (integer) (splat_parameter))) 
    (in_clause (array_pattern (integer) (integer))) 
    (in_clause (array_pattern (integer) (integer) (splat_parameter))) 
    (in_clause (array_pattern (integer) (integer) (integer))) 
    (in_clause (array_pattern (integer) (integer) (integer) (splat_parameter))) 
    (in_clause (array_pattern (integer) (integer) (integer) (splat_parameter))) 
    (in_clause (array_pattern (integer) (splat_parameter (identifier)) (integer))) 
    (in_clause (array_pattern (splat_parameter))) 
    (in_clause (array_pattern (splat_parameter) (integer) (integer))) 
    (in_clause (find_pattern (splat_parameter) (integer) (splat_parameter))) 
    (in_clause (find_pattern (splat_parameter (identifier)) (integer) (splat_parameter (identifier)))) 
    (in_clause (hash_pattern (keyword_pattern (hash_key_symbol)))) 
    (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)))) 
    (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)))) 
    (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_parameter))) 
    (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_parameter (identifier)))) 
    (in_clause (hash_pattern (keyword_pattern (hash_key_symbol) (integer)) (keyword_pattern (hash_key_symbol)) (hash_splat_nil))) 
    (in_clause (hash_pattern (hash_splat_nil))) 
    (in_clause (hash_pattern)) 
    (in_clause (array_pattern))
  )
)

=====================
more pattern matching 
=====================

case expr 
  in 5
  in ^foo
  in ^$foo
  in ^@foo
  in ^@@foo
  in ^(1+1)
  in ^(foo)
  in ^(Foo::Bar)
  in var
  in "string"
  in %w(foo bar)
  in %i(foo bar)
  in /.*abc[0-9]/
  in 5 .. 10
  in .. 10
  in 5 ..
  in 5 => x
  in 5 | ^foo | var | "string"
  in Foo
  in Foo::Bar
  in ::Foo::Bar
  in (nil | self | true | false | __LINE__ | __FILE__ | __ENCODING__)
  in -> x { x == 10 }
  in :foo
  in :"foo bar"
  in -5 | +10
end

--------

 (program 
   (case_match (identifier)
     (in_clause (integer))
     (in_clause (variable_reference_pattern (identifier)))
     (in_clause (variable_reference_pattern (global_variable)))
     (in_clause (variable_reference_pattern (instance_variable)))
     (in_clause (variable_reference_pattern (class_variable)))
     (in_clause (expression_reference_pattern (binary (integer) (integer))))
     (in_clause (expression_reference_pattern (identifier)))
     (in_clause (expression_reference_pattern (scope_resolution (constant) (constant))))
     (in_clause (identifier))
     (in_clause (string (string_content)))
     (in_clause (string_array (bare_string (string_content)) (bare_string (string_content))))
     (in_clause (symbol_array (bare_symbol (string_content)) (bare_symbol (string_content))))
     (in_clause (regex (string_content)))
     (in_clause (range (integer) (integer)))
     (in_clause (range (integer)))
     (in_clause (range (integer)))
     (in_clause (as_pattern (integer) (identifier)))
     (in_clause 
       (alternative_pattern 
         (integer)
         (variable_reference_pattern (identifier))
         (identifier)
         (string (string_content))
       )
     )
     (in_clause (constant))
     (in_clause (scope_resolution (constant) (constant)))
     (in_clause (scope_resolution (scope_resolution (constant)) (constant)))
     (in_clause 
       (parenthesized_pattern 
         (alternative_pattern 
           (nil)
           (self)
           (true)
           (false)
           (line)
           (file)
           (encoding)
         )
       )
     )
     (in_clause (lambda (lambda_parameters (identifier)) (block (binary (identifier) (integer)))))
     (in_clause (simple_symbol))
     (in_clause (delimited_symbol (string_content)))
     (in_clause
       (alternative_pattern
         (unary (integer))
         (unary (integer))
       )
     )
   )
)

==============
array patterns
==============
case expr 
  in [];
  in [x];
  in [x, ];
  in Foo::Bar[];
  in Foo();
  in Bar(*);
  in Bar(a, b, *c, d, e);
end

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

(program 
  (case_match (identifier)
    (in_clause (array_pattern))
    (in_clause (array_pattern (identifier)))
    (in_clause (array_pattern (identifier) (splat_parameter)))
    (in_clause (array_pattern (scope_resolution (constant) (constant))))
    (in_clause (array_pattern (constant)))
    (in_clause (array_pattern (constant) (splat_parameter)))
    (in_clause 
      (array_pattern 
        (constant)
        (identifier)
        (identifier)
        (splat_parameter (identifier))
        (identifier)
        (identifier)
      )
    )
  )
) 

=============
find patterns
=============

case expr 
  in [*, x, *];
  in [*x, 1, 2, *y];
  in Foo::Bar[*, 1, *];
  in Foo(*, Bar, *);
end

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

(program 
  (case_match (identifier)
    (in_clause (find_pattern (splat_parameter) (identifier) (splat_parameter)))
    (in_clause (find_pattern (splat_parameter (identifier)) (integer) (integer) (splat_parameter (identifier))))
    (in_clause (find_pattern 
       (scope_resolution (constant) (constant))
       (splat_parameter)
       (integer)
       (splat_parameter))
    )
    (in_clause (find_pattern (constant) (splat_parameter) (constant) (splat_parameter)))
  )
) 

=============
hash patterns
=============

case expr 
  in {};
  in {x:};
  in Foo::Bar[ x:1 ];
  in Foo::Bar[ x:1, a:, **rest ];
  in Foo( y:);
  in Bar( ** );
  in Bar( a: 1, **nil);
end

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

(program (case_match (identifier)
  (in_clause (hash_pattern))
  (in_clause (hash_pattern (keyword_pattern (hash_key_symbol))))
  (in_clause (hash_pattern 
        (scope_resolution (constant) (constant))
        (keyword_pattern (hash_key_symbol) (integer))
  ))
  (in_clause (hash_pattern 
    (scope_resolution (constant) (constant))
    (keyword_pattern (hash_key_symbol) (integer))
    (keyword_pattern (hash_key_symbol))
    (hash_splat_parameter (identifier))
  ))
  (in_clause (hash_pattern (constant) (keyword_pattern (hash_key_symbol))))
  (in_clause (hash_pattern (constant) (hash_splat_parameter)))
  (in_clause (hash_pattern (constant) (keyword_pattern (hash_key_symbol) (integer)) (hash_splat_nil)))
  )
)

=====================
pattern matching with fancy string literals
=====================

case expr 
  in "string";
  in `ls`;
  in <<"DOC" then end
some text
DOC

---

(program
  (case_match
    value: (identifier)
    clauses: (in_clause
      pattern: (string
        (string_content)))
    clauses: (in_clause
      pattern: (subshell
        (string_content)))
    clauses: (in_clause
      pattern: (heredoc_beginning)
      body: (then)))
  (heredoc_body
    (heredoc_content)
    (heredoc_end)))
