Pipe operator can not be applied to `Some` variant

playground

type ParsedValue[V] Result[(V, String), String]

fn ParsedValue::to_string[V : Show](self : ParsedValue[V]) -> String {
  match self {
    ParsedValue(Ok(curr, rest)) => "Ok(\(curr), \(rest))"
    ParsedValue(Err(err)) => "Err(\(err))"
  }
}

struct Lexer[V] {
  parse : (String) -> ParsedValue[V]
}

fn Lexer::and[V1, V2](self : Lexer[V1], lexer2 : Lexer[V2]) -> Lexer[(V1, V2)] {
  fn parse(str : String) -> ParsedValue[(V1, V2)] {
    let r1 = (self.parse)(str)
    match r1.0 {
      Ok(curr, rest) => {
        let r2 = (lexer2.parse)(rest)
        match r2.0 {
          Err(err) => ParsedValue(Err(err))
          Ok(curr2, rest2) => ParsedValue(Ok((curr, curr2), rest2))
        }
      }
      Err(err) => ParsedValue(Err(err))
    }
  }

  { parse, }
}

fn Lexer::or[V](self : Lexer[V], lexer2 : Lexer[V]) -> Lexer[V] {
  fn parse(str : String) -> ParsedValue[V] {
    let r1 = (self.parse)(str)
    match r1.0 {
      Ok(_) => r1
      Err(_) => (lexer2.parse)(str)
    }
  }

  { parse, }
}

fn Lexer::map[V, V2](self : Lexer[V], f : (V) -> V2) -> Lexer[V2] {
  fn parse(str : String) -> ParsedValue[V2] {
    let r1 = (self.parse)(str)
    match r1 {
      ParsedValue(Ok(curr, rest)) => ParsedValue(Ok(f(curr), rest))
      ParsedValue(Err(err)) => ParsedValue(Err(err))
    }
  }

  { parse, }
}

fn Lexer::many[V](self : Lexer[V]) -> Lexer[List[V]] {
  fn parse(str : String) -> ParsedValue[List[V]] {
    fn handle(result : List[V], str : String) -> ParsedValue[List[V]] {
      if str.length() == 0 {
        ParsedValue(Ok(result |> reverseList, str))
      } else {
        let r = (self.parse)(str)
        match r {
          ParsedValue(Err(_)) => ParsedValue(Ok(result |>  reverseList, str))
          ParsedValue(Ok(curr, rest)) => {
            let result = List::Cons(curr, result)
            handle(result, rest)
          }
        }
      }
    }

    handle(List::Nil, str)
  }

  { parse, }
}

fn Lexer::parseChar(char : Char) -> Lexer[Char] {
  fn parse(str : String) -> ParsedValue[Char] {
    if str.length() > 0 && str.get(0) == char {
      let rest = str.to_bytes().sub_string(1, str.length() - 1)
      ParsedValue(Ok(char, rest))
    } else {
      ParsedValue(Err("the str[\(str)] is not valid"))
    }
  }

  { parse, }
}

trait Add  {
  add(Self, Self) -> Self
}

fn Lexer::add[V : Add](self : Lexer[V], lexer2 : Lexer[V]) -> Lexer[V] {
  fn parse(str : String) -> ParsedValue[V] {
    match (self.parse)(str).0 {
      Ok(curr, rest) =>
        match (lexer2.parse)(rest).0 {
          Ok(curr2, rest2) => ParsedValue(Ok(curr.add(curr2), rest2))
          Err(err) => ParsedValue(Err(err))
        }
      Err(err) => ParsedValue(Err(err))
    }
  }

  { parse, }
}

fn Lexer::seq[V : Add](lexers : List[Lexer[V]]) -> Lexer[V] {
  fn takeOneAndConcat(lexers : List[Lexer[V]], result : Option[Lexer[V]]) ->
       Option[Lexer[V]] {
    match lexers {
      Nil => result
      Cons(head, tail) =>
        match result {
          None => takeOneAndConcat(tail, Some(head))
          Some(result) => {
            // takeOneAndConcat(tail, Some(result.add(head)))
            takeOneAndConcat(tail, result.add(head) |> Some)
          }
        }
    }
  }

  match takeOneAndConcat(lexers, None) {
    None => abort("Lexer::seq failed")
    Some(result) => result
  }
}

fn mapList[V, V2](list : List[V], f : (V) -> V2) -> List[V2] {
  loop list, (Nil : List[V2]) {
    Nil, result => break result
    Cons(head, left), result => continue left, Cons(f(head), result)
  }
  |> reverseList
}

fn reverseList[V](list : List[V]) -> List[V] {
  loop list, (Nil : List[V]) {
    Nil, result => break result
    Cons(head, left), result => continue left, Cons(head, result)
  }
}

fn Lexer::parseWord(word : String) -> Lexer[String] {
  let chars = {
    let mut result : List[Char] = Nil
    let mut i = 0
    while i < word.length() {
      result = Cons(word.get(i), result)
      i = i + 1
    }
    result |> reverseList
  }
  chars
  |> mapList(Lexer::parseChar)
  |> mapList(fn(c) { c.map(fn(c) { c.to_string() }) })
  |> Lexer::seq
}

fn Add::add(x : String, y : String) -> String {
  x + y
}

fn init {
  {
    println("test parseChar")
    let parseA = Lexer::parseChar('a')
    let r = (parseA.parse)("abc")
    println(r)
    println("test parseChar end")
  }
  {
    println("test or")
    let parser = Lexer::parseWord("a").or(Lexer::parseWord("b"))
    (parser.parse)("cba") |> println
    (parser.parse)("bac") |> println
    println("test or end")
  }
  let keywords = {
    let whitespace = Lexer::parseWord(" ")
    let if_ = Lexer::parseWord("if")
    let else_ = Lexer::parseWord("else")
    let do_ = Lexer::parseWord("do")
    let while_ = Lexer::parseWord("while")
    let for_ = Lexer::parseWord("for")
    if_.or(else_).or(while_).or(for_).or(do_).and(whitespace.many()).map(
      fn(x) { x.0 },
    ).many()
  }
  println((keywords.parse)("if else while for do while if elsee"))
}

Sorry for the late response. The feature itself is quite simple and we would add it in the future. But currently it is blocked by our shift from constructor with tuple arguments to native multi-argument tuples.

2 Likes