//> using scala "3.6.4" //> using dep "dev.zio::zio-parser:0.1.11" //> using file "Parser.scala" import scala.reflect.TypeTest import zio.parser.* import zio.Chunk enum Token: case For case While case LParen case RParen case LitBool(value: Boolean) case Ident(name: String) enum Stat: //for(i) case For(iterator: String) //while(cond) case While(condition: Boolean) case Identifier(name: String) //C'est pas un statement mais fuck pour l'exemple type ASTParser[A] = Parser[String, Token, A] private def anyTokenOf[T <: Token](using test: TypeTest[Token, T]): ASTParser[T] = Parser.any[Token].transformEither: case t: T => Right(t) case other => Left(s"Unexpected token: $other") private def anyToken(expected: Token): ASTParser[Unit] = Parser.any[Token].transformEither: case t if t == expected => Right(()) case other => Left(s"Unexpected token: $other, Expected: $expected") val forParser: ASTParser[Stat] = anyToken(Token.For) .zip(anyToken(Token.LParen).fatal) .zip(anyTokenOf[Token.Ident].map(_.name).fatal) .zip(anyToken(Token.RParen).fatal) .map(Stat.For.apply) val whileParser: ASTParser[Stat] = anyToken(Token.While) .zip(anyToken(Token.LParen).fatal) .zip(anyTokenOf[Token.LitBool].map(_.value).fatal) .zip(anyToken(Token.RParen).fatal) .map(Stat.While.apply) val identParser: ASTParser[Stat] = anyTokenOf[Token.Ident].map(id => Stat.Identifier(id.name)) val statParser = forParser .orElse(whileParser) .orElse(identParser) .repeat0 println(statParser.parseChunk(Chunk(Token.For, Token.LParen, Token.Ident("i"), Token.RParen))) println(statParser.parseChunk(Chunk(Token.While, Token.LParen, Token.LitBool(true), Token.RParen))) println(statParser.parseChunk(Chunk(Token.Ident("foo")))) //Should fail println("=== Should fail with meaningful error ===") //Unexpected EOF println(statParser.parseChunk(Chunk(Token.For))) //Unexpected EOF println(statParser.parseChunk(Chunk(Token.While))) //Unexpected Token (lit bool vs identifier) println(statParser.parseChunk(Chunk(Token.For, Token.LParen, Token.LitBool(true), Token.RParen))) //Unexpected Token (identifier vs lit bool) println(statParser.parseChunk(Chunk(Token.While, Token.LParen, Token.Ident("foo"), Token.RParen))) //Unexpected EOF println(statParser.parseChunk(Chunk(Token.For, Token.LParen, Token.Ident("i")))) //Unexpected EOF println(statParser.parseChunk(Chunk(Token.While, Token.LParen, Token.LitBool(true)))) //Unexpected Token (identifier vs l-paren) println(statParser.parseChunk(Chunk(Token.For, Token.Ident("i"), Token.RParen))) //Unexpected Token (lit bool vs l-paren) println(statParser.parseChunk(Chunk(Token.While, Token.LitBool(true), Token.RParen)))