///|
fn Cursor::identifier(self : Cursor) -> Node raise ParseFailure {
  let start = self.index
  if !is_id_start(self.current()) {
    raise ParseFailure("E0004", [Some("a-zA-Z")])
  }
  ignore(self.next())
  while is_id_char(self.current()) {
    ignore(self.next())
  }
  Node::with_span(Identifier(self.slice(start, self.index)), start, self.index)
}

///|
fn Cursor::digits(self : Cursor) -> String raise ParseFailure {
  let start = self.index
  while is_digit(self.current()) {
    ignore(self.next())
  }
  if self.index == start {
    raise ParseFailure("E0004", [Some("0-9")])
  }
  self.slice(start, self.index)
}

///|
fn Cursor::number(self : Cursor) -> Node raise ParseFailure {
  let start = self.index
  if self.current() == Some('-') {
    ignore(self.next())
  }
  ignore(self.digits())
  if self.current() == Some('.') {
    ignore(self.next())
    ignore(self.digits())
  }
  Node::with_span(
    NumberLiteral(self.slice(start, self.index)),
    start,
    self.index,
  )
}

///|
fn Cursor::escape(self : Cursor) -> String raise ParseFailure {
  match self.current() {
    Some('\\') | Some('"') => {
      let ch = self.current().unwrap()
      ignore(self.next())
      "\\" + ch.to_string()
    }
    Some('u') | Some('U') => {
      let u = self.current().unwrap()
      ignore(self.next())
      let digits = if u == 'u' { 4 } else { 6 }
      let buf = StringBuilder()
      buf.write_char('\\')
      buf.write_char(u)
      for _ in 0.. c.to_string()
            None => "None"
          }
          raise ParseFailure("E0026", [Some(buf.to_string() + last)])
        }
        buf.write_char(self.current().unwrap())
        ignore(self.next())
      }
      buf.to_string()
    }
    ch => raise ParseFailure("E0025", [ch.map(c => c.to_string())])
  }
}

///|
fn Cursor::string_literal(self : Cursor) -> Node raise ParseFailure {
  let start = self.index
  let buf = StringBuilder()
  self.expect('"')
  while true {
    match self.current() {
      Some('"') => {
        ignore(self.next())
        break
      }
      Some('\n') => raise ParseFailure("E0020", [])
      None => {
        self.expect('"')
        break
      }
      Some('\\') => {
        ignore(self.next())
        buf.write_string(self.escape())
      }
      Some(ch) => {
        buf.write_char(ch)
        ignore(self.next())
      }
    }
  }
  Node::with_span(StringLiteral(buf.to_string()), start, self.index)
}

///|
fn Cursor::literal(self : Cursor) -> Node raise ParseFailure {
  if self.is_number_start() {
    return self.number()
  }
  if self.current() == Some('"') {
    return self.string_literal()
  }
  raise ParseFailure("E0014", [])
}

///|
fn identifier_name(node : Node) -> String {
  match node.kind {
    Identifier(name) => name
    _ => ""
  }
}

///|
fn uppercase_function(name : String) -> Bool {
  let chars = name.to_array()
  if chars.is_empty() || chars[0] < 'A' || chars[0] > 'Z' {
    return false
  }
  for c in chars {
    if !((c >= 'A' && c <= 'Z') ||
      (c >= '0' && c <= '9') ||
      c == '_' ||
      c == '-') {
      return false
    }
  }
  true
}