///|
/// Usage grammar tokens. Offsets are UTF-16 code units in the formal usage.
pub struct UsageToken {
  text : String
  offset : Int32
}

///|
/// Expand repeated program names into top-level alternatives as docopt does.
fn formal_usage(doc : Document) -> String {
  let ws = words(doc.usage[6:].to_owned())
  let out = StringBuilder()
  out.write_string("( ")
  for i in 1.. Array[UsageToken] raise DocoptError {
  let source = formal_usage(self)
  let out = []
  let mut i = 0
  while i < source.length() {
    let c = source[i]
    if c == 32 || c == 9 || c == 10 || c == 13 {
      i += 1
      continue
    }
    let start = i
    if c == 91 || c == 93 || c == 40 || c == 41 || c == 124 {
      out.push({ text: source[i:i + 1].to_owned(), offset: i, })
      i += 1
      continue
    }
    if i + 3 <= source.length() && source[i:i + 3] == "..." {
      out.push({ text: "...", offset: i, })
      i += 3
      continue
    }
    let mut angle = false
    while i < source.length() {
      let x = source[i]
      if x == 60 {
        angle = true
      }
      if !angle &&
        (
          x == 32 ||
          x == 9 ||
          x == 10 ||
          x == 13 ||
          x == 91 ||
          x == 93 ||
          x == 40 ||
          x == 41 ||
          x == 124
        ) {
        break
      }
      if !angle && i + 3 <= source.length() && source[i:i + 3] == "..." {
        break
      }
      i += 1
      if x == 62 {
        angle = false
      }
    }
    guard !angle else {
      raise Language("unclosed  in usage at \{start}")
    }
    out.push({ text: source[start:i].to_owned(), offset: start, })
  }
  out
}