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] =   |