anchor.diff:      : us=unaliasedSelector (K_AS c=ident { alias = c; })? { $s = ::make_shared<raw_selector>(us, alias); }
       ;
   
  -unaliasedSelector returns [cql3::expr::expression s]
  -    @init { cql3::expr::expression tmp; }
  -    :  ( c=cident                                  { tmp = cql3::expr::unresolved_identifier{std::move(c)}; }
  +unaliasedSelector returns [expression s]
  +    @init { expression tmp; }
  +    :  ( c=cident                                  { tmp = unresolved_identifier{std::move(c)}; }
          | K_COUNT '(' countArgument ')'             { tmp = make_count_rows_function_expression(); }
  -       | K_WRITETIME '(' c=cident ')'              { tmp = cql3::expr::column_mutation_attribute{cql3::expr::column_mutation_attribute::attribute_kind::writetime,
  -                                                                                              cql3::expr::unresolved_identifier{std::move(c)}}; }
  -       | K_TTL       '(' c=cident ')'              { tmp = cql3::expr::column_mutation_attribute{cql3::expr::column_mutation_attribute::attribute_kind::ttl,
  -                                                                                              cql3::expr::unresolved_identifier{std::move(c)}}; }
  -       | f=functionName args=selectionFunctionArgs { tmp = cql3::expr::function_call{std::move(f), std::move(args)}; }
  -       | K_CAST      '(' arg=unaliasedSelector K_AS t=native_type ')'  { tmp = cql3::expr::cast{std::move(arg), std::move(t)}; }
  +       | K_WRITETIME '(' c=cident ')'              { tmp = column_mutation_attribute{column_mutation_attribute::attribute_kind::writetime,
  +                                                                                              unresolved_identifier{std::move(c)}}; }
  +       | K_TTL       '(' c=cident ')'              { tmp = column_mutation_attribute{column_mutation_attribute::attribute_kind::ttl,
  +                                                                                              unresolved_identifier{std::move(c)}}; }
  +       | f=functionName args=selectionFunctionArgs { tmp = function_call{std::move(f), std::move(args)}; }
  +       | K_CAST      '(' arg=unaliasedSelector K_AS t=native_type ')'  { tmp = cast{std::move(arg), std::move(t)}; }
          )
  -       ( '.' fi=cident { tmp = cql3::expr::field_selection{std::move(tmp), std::move(fi)}; } )*
  +       ( '.' fi=cident { tmp = field_selection{std::move(tmp), std::move(fi)}; } )*
       { $s = tmp; }
       ;
   
  -selectionFunctionArgs returns [std::vector<cql3::expr::expression> a]
  +selectionFunctionArgs returns [std::vector<expression> a]
       : '(' ')'
       | '(' s1=unaliasedSelector { a.push_back(std::move(s1)); }
             ( ',' sn=unaliasedSelector { a.push_back(std::move(sn)); } )*
  
positive.code:                     if (text.size() == 1 && text[0] == '\xFF') {
                          text = {};
                      }
                      $constant = cql3::expr::untyped_constant{cql3::expr::untyped_constant::string, std::move(text)};
                  }
      | t=INTEGER        { $constant = cql3::expr::untyped_constant{cql3::expr::untyped_constant::integer, $t.text}; }
      | t=FLOAT          { $constant = cql3::expr::untyped_constant{cql3::expr::untyped_constant::floating_point, $t.text}; }
      | t=BOOLEAN        { $constant = cql3::expr::untyped_constant{cql3::expr::untyped_constant::boolean, $t.text}; }
      | t=DURATION       { $constant = cql3::expr::untyped_constant{cql3::expr::untyped_constant::duration, $t.text}; }
      | t=UUID           { $constant = cql3::expr::untyped_constant{cql3::expr::untyped_constant::uuid, $t.text}; }
      | t=HEXNUMBER      { $constant = cql3::expr::untyped_constant{cql3::expr::untyped_constant::hex, $t.text}; }
      | { sign=""; } ('-' {sign = "-"; } )? t=(K_NAN | K_INFINITY) { $constant = cql3::expr::untyped_constant{cql3::expr::untyped_constant::floating_point, sign + $t.text}; }
      ;
  
  mapLiteral returns [cql3::expr::collection_constructor map]
      @init{std::vector<cql3::expr::expression> m;}
      : '{' { }
            ( k1=term ':' v1=term { m.push_back(cql3::expr::tuple_constructor{{std::move(k1), std::move(v1)}}); }
              ( ',' kn=term ':' vn=term { m.push_back(cql3::expr::tuple_constructor{{std::move(kn), std::move(vn)}}); } )*  )?
        '}' { $map = cql3::expr::collection_constructor{cql3::expr::collection_constructor::style_type::map, std::move(m)}; }
      ;
  
  setOrMapLiteral[cql3::expr::expression t] returns [cql3::expr::collection_constructor value]
  	@init{ std::vector<cql3::expr::expression> e; }
      : ':' v=term { e.push_back(cql3::expr::tuple_constructor{{std::move(t), std::move(v)}}); }
            ( ',' kn=term ':' vn=term { e.push_back(cql3::expr::tuple_constructor{{std::move(kn), std::move(vn)}}); } )*
        { $value = cql3::expr::collection_constructor{cql3::expr::collection_constructor::style_type::map, std::move(e)}; }
      | { e.push_back(std::move(t)); }
            ( ',' tn=term { e.push_back(std::move(tn)); } )*
        { $value = cql3::expr::collection_constructor{cql3::expr::collection_constructor::style_type::set, std::move(e)}; }
      ;
  
  collectionLiteral returns [cql3::expr::expression value]
  	@init{ std::vector<cql3::expr::expression> l; }
      : '['
            ( t1=term { l.push_back(std::move(t1)); } ( ',' tn=term { l.push_back(std::move(tn)); } )* )?
        ']' { $value = cql3::expr::collection_constructor{cql3::expr::collection_constructor::style_type::list, std::move(l)}; }
      | '{' t=term v=setOrMapLiteral[t] { $value = std::move(v); } '}'
      // Note that we have an ambiguity between maps and set for "{}". So we force it to a set literal,
      // and deal with it later based on the type of the column (SetLiteral.java).
      | '{' '}' { $value = cql3::expr::collection_constructor{cql3::expr::collection_constructor::style_type::set, {}}; }
      ;
  
  usertypeLiteral returns [cql3::expr::expression ut]
      @init{ cql3::expr::usertype_constructor::elements_map_type m; }
      @after{ $ut = cql3::expr::usertype_constructor{std::move(m)}; }
      // We don't allow empty literals because that conflicts with sets/maps and is currently useless since we don't allow empty user types
      : '{' k1=ident ':' v1=term { m.emplace(std::move(*k1), std::move(v1)); } ( ',' kn=ident ':' vn=term { m.emplace(std::move(*kn), std::move(vn)); } )* '}'
      ;
  
  tupleLiteral returns [cql3::expr::expression tt]
      @init{ std::vector<cql3::expr::expression> l; }
      @after{ $tt = cql3::expr::tuple_constructor{std::move(l)}; }
      : '(' t1=term { l.push_back(std::move(t1)); } ( ',' tn=term { l.push_back(std::move(tn)); } )* ')'
      ;
  
  value returns [cql3::expr::expression value]
      : c=constant           { $value = std::move(c); }
      | l=collectionLiteral  { $value = std::move(l); }
      | u=usertypeLiteral    { $value = std::move(u); }
      | t=tupleLiteral       { $value = std::move(t); }
      | K_NULL               { $value = cql3::expr::null(); }
      | ':' id=ident         { $value = new_bind_variables(id); }
      | QMARK                { $value = new_bind_variables(shared_ptr<cql3::column_identifier>{}); }
      ;
  
  intValue returns [cql3::expr::expression value]
      :
      | t=INTEGER     { $value = cql3::expr::untyped_constant{cql3::expr::untyped_constant::integer, $t.text}; }
      | ':' id=ident  { $value = new_bind_variables(id); }
      | QMARK         { $value = new_bind_variables(shared_ptr<cql3::column_identifier>{}); }
      ;
  
negative.code:     @init {
          auto attrs = std::make_unique<cql3::attributes::raw>();
          std::vector<::shared_ptr<cql3::column_identifier::raw>> column_names;
          std::vector<expression> values;
          bool if_not_exists = false;
          bool default_unset = false;
          std::optional<expression> json_value;
      }
      : K_INSERT K_INTO cf=columnFamilyName
          ('(' c1=cident { column_names.push_back(c1); }  ( ',' cn=cident { column_names.push_back(cn); } )* ')'
  