solutions/cw5/fun_parser.sc
changeset 920 7af2eea19646
parent 903 2f86ebda3629
equal deleted inserted replaced
919:53f08d873e09 920:7af2eea19646
    13 // more convenience for the map parsers later on;
    13 // more convenience for the map parsers later on;
    14 // it allows writing nested patterns as
    14 // it allows writing nested patterns as
    15 // case x ~ y ~ z => ...
    15 // case x ~ y ~ z => ...
    16 case class ~[+A, +B](x: A, y: B)
    16 case class ~[+A, +B](x: A, y: B)
    17 
    17 
    18 // constraint for the input
    18 // parser combinators
    19 type IsSeq[A] = A => Seq[_]
    19 abstract class Parser[I, T](using is: I => Seq[_])  {
    20 
    20   def parse(in: I): Set[(T, I)]  
    21 abstract class Parser[I : IsSeq, T]{
       
    22   def parse(in: I): Set[(T, I)]
       
    23 
    21 
    24   def parse_all(in: I) : Set[T] =
    22   def parse_all(in: I) : Set[T] =
    25     for ((hd, tl) <- parse(in);
    23     for ((hd, tl) <- parse(in); 
    26         if tl.isEmpty) yield hd
    24         if is(tl).isEmpty) yield hd
    27 }
    25 }
    28 
    26 
    29 // parser combinators
    27 // alternative parser
       
    28 class AltParser[I, T](p: => Parser[I, T], 
       
    29                       q: => Parser[I, T])(using I => Seq[_]) extends Parser[I, T] {
       
    30   def parse(in: I) = p.parse(in) ++ q.parse(in)   
       
    31 }
    30 
    32 
    31 // sequence parser
    33 // sequence parser
    32 class SeqParser[I : IsSeq, T, S](p: => Parser[I, T],
    34 class SeqParser[I, T, S](p: => Parser[I, T], 
    33                                  q: => Parser[I, S]) extends Parser[I, ~[T, S]] {
    35                          q: => Parser[I, S])(using I => Seq[_]) extends Parser[I, ~[T, S]] {
    34   def parse(in: I) =
    36   def parse(in: I) = 
    35     for ((hd1, tl1) <- p.parse(in);
    37     for ((hd1, tl1) <- p.parse(in); 
    36          (hd2, tl2) <- q.parse(tl1)) yield (new ~(hd1, hd2), tl2)
    38          (hd2, tl2) <- q.parse(tl1)) yield (new ~(hd1, hd2), tl2)
    37 }
    39 }
    38 
    40 
    39 // alternative parser
       
    40 class AltParser[I : IsSeq, T](p: => Parser[I, T],
       
    41                               q: => Parser[I, T]) extends Parser[I, T] {
       
    42   def parse(in: I) = p.parse(in) ++ q.parse(in)
       
    43 }
       
    44 
       
    45 // map parser
    41 // map parser
    46 class MapParser[I : IsSeq, T, S](p: => Parser[I, T],
    42 class MapParser[I, T, S](p: => Parser[I, T], 
    47                                  f: T => S) extends Parser[I, S] {
    43                          f: T => S)(using I => Seq[_]) extends Parser[I, S] {
    48   def parse(in: I) = for ((hd, tl) <- p.parse(in)) yield (f(hd), tl)
    44   def parse(in: I) = for ((hd, tl) <- p.parse(in)) yield (f(hd), tl)
    49 }
    45 }
    50 
    46 
       
    47 
    51 // more convenient syntax for parser combinators
    48 // more convenient syntax for parser combinators
    52 implicit def ParserOps[I : IsSeq, T](p: Parser[I, T]) = new {
    49 extension [I, T](p: Parser[I, T])(using I => Seq[_]) {
    53   def ||(q : => Parser[I, T]) = new AltParser[I, T](p, q)
    50   def ||(q : => Parser[I, T]) = new AltParser[I, T](p, q)
    54   def ~[S] (q : => Parser[I, S]) = new SeqParser[I, T, S](p, q)
    51   def ~[S] (q : => Parser[I, S]) = new SeqParser[I, T, S](p, q)
    55   def map[S](f: => T => S) = new MapParser[I, T, S](p, f)
    52   def map[S](f: => T => S) = new MapParser[I, T, S](p, f)
    56 }
    53 }
       
    54 
    57 
    55 
    58 // -------------------------------------------------
    56 // -------------------------------------------------
    59 // atomic parsers
    57 // atomic parsers
    60 
    58 
    61 // atomic parser for types
    59 // atomic parser for types
   144     case tk::tkns if tk._2 == s => Set((s, tkns))
   142     case tk::tkns if tk._2 == s => Set((s, tkns))
   145     case _ => Set()
   143     case _ => Set()
   146   }
   144   }
   147 }
   145 }
   148 
   146 
   149 implicit def parser_interpolation(sc: StringContext) = new {
   147 extension (sc: StringContext) {
   150   def p(args: Any*) = StrParser(sc.s(args:_*))
   148    def p(args: Any*) = StrParser(sc.s(args:_*))
   151 }
   149 }
   152 
   150 
   153 
   151 
   154 // the AST datastructures for the FUN language
   152 // the AST datastructures for the FUN language
   155 
   153