// Port of sqlglot/parser.py: aliases, identifiers, literals and other atoms.

///|
pub fn Parser::parse_alias(
  self : Parser,
  this : Expr?,
  explicit? : Bool = false,
) -> Expr? raise SqlglotError {
  match self.fns.hooks.parse_alias {
    Some(f) => f(self, this, explicit)
    None => self.parse_alias_base(this, explicit~)
  }
}

///|
pub fn Parser::parse_alias_base(
  self : Parser,
  this : Expr?,
  explicit? : Bool = false,
) -> Expr? raise SqlglotError {
  if self.can_parse_limit_or_offset() {
    return this
  }
  if self.can_parse_named_window() {
    return this
  }
  let any_token = self.match_(ALIAS)
  let comments = self.prev_comments
  if explicit && !any_token {
    return this
  }
  if self.match_(L_PAREN) {
    let aliases = self.expression(
      mk(Aliases, [
        ("this", this),
        ("expressions", self.parse_csv(() => self.parse_id_var(any_token~))),
      ]),
      comments~,
    )
    self.match_r_paren(expression=aliases)
    return Some(aliases)
  }
  let alias = match
    self.parse_id_var(any_token~, tokens=self.cfg.alias_tokens) {
    Some(a) => Some(a)
    None =>
      if self.cfg.string_aliases {
        self.parse_string_as_identifier()
      } else {
        None
      }
  }
  match alias {
    Some(a) => {
      let comments = comments + a.pop_comments()
      let e = self.expression(
        mk(Alias, [("this", this), ("alias", a)]),
        comments~,
      )
      match e.this() {
        Some(column) =>
          if e.comments.unwrap_or([]).is_empty() &&
            !column.comments.unwrap_or([]).is_empty() {
            e.comments = Some(column.pop_comments())
          }
        None => ()
      }
      Some(e)
    }
    None => this
  }
}

///|
pub fn Parser::parse_id_var(
  self : Parser,
  any_token? : Bool = true,
  tokens? : TokenSet,
) -> Expr? raise SqlglotError {
  match self.fns.hooks.parse_id_var {
    Some(f) => f(self, any_token, tokens)
    None => self.parse_id_var_base(any_token~, tokens?)
  }
}

///|
pub fn Parser::parse_id_var_base(
  self : Parser,
  any_token? : Bool = true,
  tokens? : TokenSet,
) -> Expr? raise SqlglotError {
  let mut expression = self.parse_identifier()
  if expression is None {
    let matched = (any_token && self.advance_any() is Some(_)) ||
      self.match_set(
        match tokens {
          Some(t) => t
          None => self.cfg.id_var_tokens
        },
      )
    if matched {
      let quoted = self.prev.token_type == STRING
      expression = Some(self.identifier_expression(quoted~))
    }
  }
  expression
}

///|
pub fn Parser::parse_string(self : Parser) -> Expr? raise SqlglotError {
  if self.match_keys(self.fns.string_parsers) {
    return self.fns.string_parsers[self.prev.token_type](self, self.prev)
  }
  self.parse_placeholder()
}

///|
pub fn Parser::parse_string_as_identifier(
  self : Parser,
) -> Expr? raise SqlglotError {
  if !self.match_(STRING) {
    return None
  }
  let output = to_identifier(self.prev.text, quoted=true)
  output.update_positions_from_token(self.prev) |> ignore
  Some(output)
}

///|
pub fn Parser::parse_number(self : Parser) -> Expr? raise SqlglotError {
  if self.match_keys(self.fns.numeric_parsers) {
    return self.fns.numeric_parsers[self.prev.token_type](self, self.prev)
  }
  self.parse_placeholder()
}

///|
pub fn Parser::parse_identifier(self : Parser) -> Expr? raise SqlglotError {
  if self.match_(IDENTIFIER) {
    return Some(self.identifier_expression(quoted=true))
  }
  self.parse_placeholder()
}

///|
pub fn Parser::parse_var(
  self : Parser,
  any_token? : Bool = false,
  tokens? : TokenSet,
  upper? : Bool = false,
) -> Expr? raise SqlglotError {
  if (any_token && self.advance_any() is Some(_)) ||
    self.match_(VAR) ||
    (match tokens {
      Some(t) => self.match_set(t)
      None => false
    }) {
    let text = if upper { self.prev_upper() } else { self.prev.text }
    return Some(self.expression(mk1(Var, text)))
  }
  self.parse_placeholder()
}

///|
pub fn Parser::advance_any(
  self : Parser,
  ignore_reserved? : Bool = false,
) -> Token? {
  if self.curr.ok() &&
    (
      ignore_reserved ||
      !self.cfg.reserved_tokens.contains(self.curr.token_type)
    ) {
    self.advance()
    return Some(self.prev)
  }
  None
}

///|
pub fn Parser::parse_var_or_string(
  self : Parser,
  upper? : Bool = false,
) -> Expr? raise SqlglotError {
  expr_or(self.parse_string(), () => self.parse_var(any_token=true, upper~))
}

///|
pub fn Parser::parse_primary_or_var(self : Parser) -> Expr? raise SqlglotError {
  expr_or(self.parse_primary(), () => self.parse_var(any_token=true))
}

///|
pub fn Parser::parse_null(self : Parser) -> Expr? raise SqlglotError {
  if self.match_any([NULL, UNKNOWN]) {
    return self.fns.primary_parsers[NULL](self, self.prev)
  }
  self.parse_placeholder()
}

///|
pub fn Parser::parse_boolean(self : Parser) -> Expr? raise SqlglotError {
  if self.match_(TRUE) {
    return self.fns.primary_parsers[TRUE](self, self.prev)
  }
  if self.match_(FALSE) {
    return self.fns.primary_parsers[FALSE](self, self.prev)
  }
  self.parse_placeholder()
}

///|
pub fn Parser::parse_star(self : Parser) -> Expr? raise SqlglotError {
  if self.match_(STAR) {
    return self.fns.primary_parsers[STAR](self, self.prev)
  }
  self.parse_placeholder()
}

///|
pub fn Parser::parse_parameter(self : Parser) -> Expr? raise SqlglotError {
  match self.fns.hooks.parse_parameter {
    Some(f) => f(self)
    None => {
      let this = expr_or(self.parse_identifier(), () => {
        self.parse_primary_or_var()
      })
      Some(self.expression(mk1(Parameter, this)))
    }
  }
}

///|
pub fn Parser::parse_placeholder(self : Parser) -> Expr? raise SqlglotError {
  if self.match_keys(self.fns.placeholder_parsers) {
    let placeholder = self.fns.placeholder_parsers[self.prev.token_type](self)
    match placeholder {
      Some(_) => return placeholder
      None => ()
    }
    self.advance(times=-1)
  }
  None
}

///|
pub fn Parser::parse_star_op(
  self : Parser,
  keywords : ArrayView[String],
) -> Array[Expr]? raise SqlglotError {
  if !self.match_texts(keywords) {
    return None
  }
  if self.match_(L_PAREN, advance=false) {
    return Some(self.parse_wrapped_csv(() => self.parse_expression()))
  }
  let expression = self.parse_alias(self.parse_disjunction(), explicit=true)
  match expression {
    Some(e) => Some([e])
    None => None
  }
}

///|
pub fn Parser::parse_select_or_expression(
  self : Parser,
  alias? : Bool = false,
) -> Expr? raise SqlglotError {
  let first = if alias {
    self.parse_alias(self.parse_assignment(), explicit=true)
  } else {
    self.parse_assignment()
  }
  expr_or(self.parse_set_operations(first), () => self.parse_select())
}

///|
pub fn Parser::parse_ddl_select(self : Parser) -> Expr? raise SqlglotError {
  self.parse_query_modifiers(
    self.parse_set_operations(
      self.parse_select(nested=true, parse_subquery_alias=false),
    ),
  )
}