12 // more convenience for the map parsers later on; |
12 // more convenience for the map parsers later on; |
13 // it allows writing nested patterns as |
13 // it allows writing nested patterns as |
14 // case x ~ y ~ z => ... |
14 // case x ~ y ~ z => ... |
15 |
15 |
16 |
16 |
17 case class ~[+A, +B](x: A, y: B) |
17 case class o[+A, +B](x: A, y: B) |
18 |
18 |
19 |
19 |
20 type IsSeq[I] = I => Seq[_] |
20 type IsSeq[I] = I => Seq[?] |
21 |
21 |
22 abstract class Parser[I, T](using is: I => Seq[_]) { |
22 abstract class Parser[I, T](using is: I => Seq[?]) { |
23 def parse(in: I): Set[(T, I)] |
23 def parse(in: I): Set[(T, I)] |
24 |
24 |
25 def parse_all(in: I) : Set[T] = |
25 def parse_all(in: I) : Set[T] = |
26 for ((hd, tl) <- parse(in); |
26 for ((hd, tl) <- parse(in); |
27 if is(tl).isEmpty) yield hd |
27 if is(tl).isEmpty) yield hd |
35 def parse(in: I) = p.parse(in) ++ q.parse(in) |
35 def parse(in: I) = p.parse(in) ++ q.parse(in) |
36 } |
36 } |
37 |
37 |
38 // sequence parser |
38 // sequence parser |
39 class SeqParser[I : IsSeq, T, S](p: => Parser[I, T], |
39 class SeqParser[I : IsSeq, T, S](p: => Parser[I, T], |
40 q: => Parser[I, S]) extends Parser[I, ~[T, S]] { |
40 q: => Parser[I, S]) extends Parser[I, o[T, S]] { |
41 def parse(in: I) = |
41 def parse(in: I) = |
42 for ((hd1, tl1) <- p.parse(in); |
42 for ((hd1, tl1) <- p.parse(in); |
43 (hd2, tl2) <- q.parse(tl1)) yield (new ~(hd1, hd2), tl2) |
43 (hd2, tl2) <- q.parse(tl1)) yield (new o(hd1, hd2), tl2) |
44 } |
44 } |
45 |
45 |
46 // map parser |
46 // map parser |
47 class MapParser[I : IsSeq, T, S](p: => Parser[I, T], |
47 class MapParser[I : IsSeq, T, S](p: => Parser[I, T], |
48 f: T => S) extends Parser[I, S] { |
48 f: T => S) extends Parser[I, S] { |
85 // StrParser(_some_string_) more conveniently as |
85 // StrParser(_some_string_) more conveniently as |
86 // |
86 // |
87 // p"<_some_string_>" |
87 // p"<_some_string_>" |
88 |
88 |
89 extension (sc: StringContext) |
89 extension (sc: StringContext) |
90 def p(args: Any*) = StrParser(sc.s(args:_*)) |
90 def p(args: Any*) = StrParser(sc.s(args*)) |
91 |
91 |
92 |
92 |
93 // more convenient syntax for parser combinators |
93 // more convenient syntax for parser combinators |
94 extension [I : IsSeq, T](p: Parser[I, T]) { |
94 extension [I : IsSeq, T](p: Parser[I, T]) { |
95 def ||(q : => Parser[I, T]) = new AltParser[I, T](p, q) |
95 def ||(q : => Parser[I, T]) = new AltParser[I, T](p, q) |
96 def ~[S] (q : => Parser[I, S]) = new SeqParser[I, T, S](p, q) |
96 def o[S] (q : => Parser[I, S]) = new SeqParser[I, T, S](p, q) |
97 def map[S](f: => T => S) = new MapParser[I, T, S](p, f) |
97 def map[S](f: => T => S) = new MapParser[I, T, S](p, f) |
98 } |
98 } |
99 |
99 |
100 |
100 |
101 // the abstract syntax trees for the WHILE language |
101 // the abstract syntax trees for the WHILE language |
122 case class Or(b1: BExp, b2: BExp) extends BExp |
122 case class Or(b1: BExp, b2: BExp) extends BExp |
123 |
123 |
124 |
124 |
125 // arithmetic expressions |
125 // arithmetic expressions |
126 lazy val AExp: Parser[String, AExp] = |
126 lazy val AExp: Parser[String, AExp] = |
127 (Te ~ p"+" ~ AExp).map[AExp]{ case x ~ _ ~ z => Aop("+", x, z) } || |
127 (Te o p"+" o AExp).map[AExp]{ case x o _ o z => Aop("+", x, z): AExp } || |
128 (Te ~ p"-" ~ AExp).map[AExp]{ case x ~ _ ~ z => Aop("-", x, z) } || Te |
128 (Te o p"-" o AExp).map[AExp]{ case x o _ o z => Aop("-", x, z) } || Te |
129 lazy val Te: Parser[String, AExp] = |
129 lazy val Te: Parser[String, AExp] = |
130 (Fa ~ p"*" ~ Te).map[AExp]{ case x ~ _ ~ z => Aop("*", x, z) } || |
130 (Fa o p"*" o Te).map[AExp]{ case x o _ o z => Aop("*", x, z) } || |
131 (Fa ~ p"/" ~ Te).map[AExp]{ case x ~ _ ~ z => Aop("/", x, z) } || Fa |
131 (Fa o p"/" o Te).map[AExp]{ case x o _ o z => Aop("/", x, z) } || Fa |
132 lazy val Fa: Parser[String, AExp] = |
132 lazy val Fa: Parser[String, AExp] = |
133 (p"(" ~ AExp ~ p")").map{ case _ ~ y ~ _ => y } || |
133 (p"(" o AExp o p")").map{ case _ o y o _ => y } || |
134 IdParser.map(Var(_)) || |
134 IdParser.map(Var(_)) || |
135 NumParser.map(Num(_)) |
135 NumParser.map(Num(_)) |
136 |
136 |
137 // boolean expressions with some simple nesting |
137 // boolean expressions with some simple nesting |
138 lazy val BExp: Parser[String, BExp] = |
138 lazy val BExp: Parser[String, BExp] = |