PPaste!

Test parser fatal

Home - All the pastes - Authored by Thooms

Raw version

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//> 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)))