|         |      1 val DIGIT = RANGE("0123456789") | 
|         |      2 val NONZERODIGIT = RANGE("123456789") | 
|         |      3  | 
|         |      4 val NUMBER = ALT(SEQ(NONZERODIGIT, STAR(DIGIT)), "0") | 
|         |      5 val LPAREN = CHAR('(') | 
|         |      6 val RPAREN = CHAR(')') | 
|         |      7 val WHITESPACE = PLUS(RANGE(" \n")) | 
|         |      8 val OPS = RANGE("+-*") | 
|         |      9  | 
|         |     10 // for classifying the strings that have been recognised | 
|         |     11 abstract class Token | 
|         |     12 case object T_WHITESPACE extends Token | 
|         |     13 case class T_NUM(s: String) extends Token | 
|         |     14 case class T_OP(s: String) extends Token | 
|         |     15 case object T_LPAREN extends Token | 
|         |     16 case object T_RPAREN extends Token | 
|         |     17  | 
|         |     18 val lexing_rules: List[Rule[Token]]=  | 
|         |     19   List((NUMBER, (s) => T_NUM(s.mkString)), | 
|         |     20        (WHITESPACE, (s) => T_WHITESPACE), | 
|         |     21        (LPAREN, (s) => T_LPAREN), | 
|         |     22        (RPAREN, (s) => T_RPAREN), | 
|         |     23        (OPS, (s) => T_OP(s.mkString))) | 
|         |     24  | 
|         |     25 val Tk = Tokenizer(lexing_rules, List(T_WHITESPACE)) | 
|         |     26  | 
|         |     27  | 
|         |     28 // parser combinators with input type I and return type T | 
|         |     29 // and memoisation | 
|         |     30  | 
|         |     31 case class SubList[T](s: List[T], l: Int, h: Int) { | 
|         |     32   def low = l | 
|         |     33   def high = h | 
|         |     34   def length = h - l | 
|         |     35   def sublist(l: Int = l, h: Int = h) = s.slice(l, h) | 
|         |     36   def set(low: Int = l, high: Int = h) = SubList(s, low, high) | 
|         |     37 } | 
|         |     38  | 
|         |     39 type Ctxt[T] = List[(String, SubList[T])] | 
|         |     40  | 
|         |     41 abstract class Parser[I, T] { | 
|         |     42  | 
|         |     43   def parse(ts: SubList[I], ctxt: Ctxt[I]): Set[(T, SubList[I])] | 
|         |     44  | 
|         |     45   def parse_all(s: List[I]) : Set[T] = | 
|         |     46     for ((head, tail) <- parse(SubList(s, 0, s.length), Nil); if (tail.sublist() == Nil)) yield head | 
|         |     47  | 
|         |     48   def || (right : => Parser[I, T]) : Parser[I, T] = new AltParser(this, right) | 
|         |     49   def ==>[S] (f: => T => S) : Parser [I, S] = new FunParser(this, f) | 
|         |     50   def ~[S] (right : => Parser[I, S]) : Parser[I, (T, S)] = new SeqParser(this, right) | 
|         |     51   def ~>[S] (right : => Parser[I, S]) : Parser[I, S] = this ~ right ==> (_._2) | 
|         |     52   def <~[S] (right : => Parser[I, S]) : Parser[I, T] = this ~ right ==> (_._1) | 
|         |     53 } | 
|         |     54  | 
|         |     55 class SeqParser[I, T, S](p: => Parser[I, T], q: => Parser[I, S]) extends Parser[I, (T, S)] { | 
|         |     56   def parse(sb: SubList[I], ctxt: Ctxt[I]) =  | 
|         |     57     for ((head1, tail1) <- p.parse(sb, ctxt);  | 
|         |     58          (head2, tail2) <- q.parse(tail1, ctxt)) yield ((head1, head2), tail2) | 
|         |     59 } | 
|         |     60  | 
|         |     61 class AltParser[I, T](p: => Parser[I, T], q: => Parser[I, T]) extends Parser[I, T] { | 
|         |     62   def parse(sb: SubList[I], ctxt: Ctxt[I]) = p.parse(sb, ctxt) ++ q.parse(sb, ctxt)    | 
|         |     63 } | 
|         |     64  | 
|         |     65 class FunParser[I, T, S](p: => Parser[I, T], f: T => S) extends Parser[I, S] { | 
|         |     66   def parse(sb: SubList[I], ctxt: Ctxt[I]) =  | 
|         |     67     for ((head, tail) <- p.parse(sb, ctxt)) yield (f(head), tail) | 
|         |     68 } | 
|         |     69  | 
|         |     70 case object NumParser extends Parser[Token, Int] { | 
|         |     71   def parse(sb: SubList[Token], ctxt: Ctxt[Token]) = { | 
|         |     72     if (0 < sb.length) sb.sublist(sb.low, sb.low + 1) match {  | 
|         |     73       case T_NUM(i)::Nil => Set((i.toInt, sb.set(low = sb.low + 1)))  | 
|         |     74       case _ => Set() | 
|         |     75     } | 
|         |     76     else Set() | 
|         |     77   } | 
|         |     78 } | 
|         |     79  | 
|         |     80 case class TokParser(t: Token) extends Parser[Token, Token] { | 
|         |     81   def parse(sb: SubList[Token], ctxt: Ctxt[Token]) = { | 
|         |     82     if (0 < sb.length && sb.sublist(sb.low, sb.low + 1) == List(t)) Set((t, sb.set(low = sb.low + 1)))  | 
|         |     83     else Set() | 
|         |     84   } | 
|         |     85 } | 
|         |     86  | 
|         |     87 implicit def token2tparser(t: Token) = TokParser(t) | 
|         |     88  | 
|         |     89 class IgnLst[I, T](p: => Parser[I, T]) extends Parser[I, T] { | 
|         |     90   def parse(sb: SubList[I], ctxt: Ctxt[I]) = { | 
|         |     91     if (sb.length == 0) Set() | 
|         |     92     else for ((head, tail) <- p.parse(sb.set(high = sb.high - 1), ctxt))  | 
|         |     93          yield (head, tail.set(high = tail.high + 1)) | 
|         |     94   } | 
|         |     95 } | 
|         |     96  | 
|         |     97 class CHECK[I, T](nt: String, p: => Parser[I, T]) extends Parser[I, T] { | 
|         |     98   def parse(sb: SubList[I], ctxt: Ctxt[I]) = { | 
|         |     99     val should_trim = ctxt.contains (nt, sb) | 
|         |    100     if (should_trim && sb.length == 0) Set() | 
|         |    101     else if (should_trim) new IgnLst(p).parse(sb, (nt, sb)::ctxt) | 
|         |    102     else p.parse(sb, (nt, sb)::ctxt) | 
|         |    103   } | 
|         |    104 } | 
|         |    105  | 
|         |    106 lazy val E: Parser[Token, Int] =  | 
|         |    107   new CHECK("E", (E ~ T_OP("+") ~ E) ==> { case ((x, y), z) => x + z} ||  | 
|         |    108                  (E ~ T_OP("*") ~ E) ==> { case ((x, y), z) => x * z} || | 
|         |    109                  (T_LPAREN ~ E ~ T_RPAREN) ==> { case ((x, y), z) => y} || | 
|         |    110                  NumParser) | 
|         |    111  | 
|         |    112 println(E.parse_all(Tk.fromString("1 + 2 * 3"))) | 
|         |    113 println(E.parse_all(Tk.fromString("(1 + 2) * 3"))) |