defeat(expected: Token): ParserMonad[Token] = ParserMonad { case head :: tail if head == expected => Right((head, tail)) case head :: _ => Left(List(s"eat: Expected $expected but found $head")) caseNil => Left(List(s"eat: Expected $expected but found end of input")) }
defpeek(expected: Token): ParserMonad[Token] = ParserMonad { case tokens@(head :: _) if head == expected => Right((head, tokens)) case head :: _ => Left(List(s"peek: Expected $expected but found $head")) caseNil => Left(List(s"peek: Expected $expected but found end of input")) }
defpeek[R](select: Token => ParserMonad[R]) = ParserMonad { case tokens@(head :: _) => select(head).run(tokens) caseNil => Left(List(s"peek: Expected a token but found end of input")) }
defparseExprOfLevel(level: Int): ParserMonad[Expr] = { valOpParser = binOpParsers.getOrElse(level, fail("level out of bound"))
// additional level for function calls if (level < 4) { // Left-associate binary operations binaryAssocLeft(parseExprOfLevel(level + 1))(OpParser) } else { // Function application, if applies, or basic terms if singleton listAssocRight(funcCallAssocRight(parseTerm)) } }
for { head <- baseParser result <- loop(head) <|> ParserMonad(head) } yield result }
deffuncCallAssocRight(baseParser: ParserMonad[Expr]): ParserMonad[Expr] = { defloop(head: Expr): ParserMonad[Expr] = { for { curr <- baseParser next <- peek { case _ => // Continue on function applications loop(Call(head, curr)) } <|> ParserMonad(Call(head, curr)) // pure it if nothing more to eat } yield next }
for { head <- baseParser result <- loop(head) <|> ParserMonad(head) } yield result }