forked from scala/scala3
-
Notifications
You must be signed in to change notification settings - Fork 0
/
i18628.scala
91 lines (63 loc) · 2.44 KB
/
i18628.scala
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
abstract class Reader[+T] {
def first: T
def rest: Reader[T]
def atEnd: Boolean
}
trait Parsers {
type Elem
type Input = Reader[Elem]
sealed abstract class ParseResult[+T] {
val successful: Boolean
def map[U](f: T => U): ParseResult[U]
def flatMapWithNext[U](f: T => Input => ParseResult[U]): ParseResult[U]
}
sealed abstract class NoSuccess(val msg: String) extends ParseResult[Nothing] { // when we don't care about the difference between Failure and Error
val successful = false
def map[U](f: Nothing => U) = this
def flatMapWithNext[U](f: Nothing => Input => ParseResult[U]): ParseResult[U]
= this
}
case class Failure(override val msg: String) extends NoSuccess(msg)
case class Error(override val msg: String) extends NoSuccess(msg)
case class Success[+T](result: T, val next: Input) extends ParseResult[T] {
val successful = true
def map[U](f: T => U) = Success(f(result), next)
def flatMapWithNext[U](f: T => Input => ParseResult[U]): ParseResult[U] = f(result)(next) match {
case s @ Success(result, rest) => Success(result, rest)
case f: Failure => f
case e: Error => e
}
}
case class ~[+a, +b](_1: a, _2: b) {
override def toString = s"(${_1}~${_2})"
}
abstract class Parser[+T] extends (Input => ParseResult[T]) {
def apply(in: Input): ParseResult[T]
def ~ [U](q: => Parser[U]): Parser[~[T, U]] = {
(for(a <- this; b <- q) yield new ~(a,b))
}
def flatMap[U](f: T => Parser[U]): Parser[U]
= Parser{ in => this(in).flatMapWithNext(f)}
def map[U](f: T => U): Parser[U] //= flatMap{x => success(f(x))}
= Parser{ in => this(in).map(f)}
def ^^ [U](f: T => U): Parser[U] = map(f)
}
def Parser[T](f: Input => ParseResult[T]): Parser[T]
= new Parser[T]{ def apply(in: Input) = f(in) }
def accept(e: Elem): Parser[Elem] = acceptIf(_ == e)("'"+e+"' expected but " + _ + " found")
def acceptIf(p: Elem => Boolean)(err: Elem => String): Parser[Elem] = Parser { in =>
if (in.atEnd) Failure("end of input")
else if (p(in.first)) Success(in.first, in.rest)
else Failure(err(in.first))
}
}
object grammars3 extends Parsers {
type Elem = String
val a: Parser[String] = accept("a")
val b: Parser[String] = accept("b")
val AnBnCn: Parser[List[String]] = {
repMany(a,b)
}
def repMany[T](p: => Parser[T], q: => Parser[T]): Parser[List[T]] =
p~repMany(p,q)~q ^^ {case x~xs~y => x::xs:::(y::Nil)}
}