| 742 |      1 | // Parser Combinators:
 | 
|  |      2 | // Simple Version for WHILE-language
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |      3 | //====================================
 | 
| 742 |      4 | //
 | 
|  |      5 | // with some added convenience for
 | 
|  |      6 | // map-parsers and grammar rules
 | 
|  |      7 | //
 | 
|  |      8 | // call with
 | 
|  |      9 | //
 | 
|  |     10 | //    amm comb2.sc
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     11 | 
 | 
| 971 |     12 | 
 | 
| 742 |     13 | // more convenience for the map parsers later on;
 | 
|  |     14 | // it allows writing nested patterns as
 | 
|  |     15 | // case x ~ y ~ z => ...
 | 
|  |     16 | 
 | 
| 977 |     17 | case class ~[+A, +B](x: A, y: B) 
 | 
| 941 |     18 | 
 | 
| 973 |     19 | // to make sure the input has an empty-method
 | 
| 972 |     20 | trait IsSeq[I] {
 | 
|  |     21 |   extension (i: I) def isEmpty: Boolean
 | 
|  |     22 | }
 | 
|  |     23 | 
 | 
|  |     24 | given IsSeq[String] = _.isEmpty
 | 
|  |     25 | given [I]: IsSeq[Seq[I]] = _.isEmpty
 | 
|  |     26 | 
 | 
|  |     27 | 
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     28 | // parser combinators
 | 
| 972 |     29 | abstract class Parser[I : IsSeq, T] { p =>
 | 
| 971 |     30 |   def parse(in: I): Set[(T, I)]  
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     31 | 
 | 
| 972 |     32 |   def parse_all(in: I) : Set[T] =
 | 
| 971 |     33 |     for ((hd, tl) <- parse(in); 
 | 
| 972 |     34 |         if tl.isEmpty) yield hd
 | 
| 971 |     35 | 
 | 
|  |     36 |   // alternative parser
 | 
| 977 |     37 |   def ||(q: => Parser[I, T]) : Parser[I, T] = new Parser[I, T] {
 | 
| 971 |     38 |     def parse(in: I) = p.parse(in) ++ q.parse(in)
 | 
|  |     39 |   }
 | 
| 906 |     40 | 
 | 
| 971 |     41 |   // sequence parser
 | 
|  |     42 |   def ~[S](q: => Parser[I, S]) = new Parser[I, T ~ S] {
 | 
|  |     43 |     def parse(in: I) = 
 | 
|  |     44 |       for ((hd1, tl1) <- p.parse(in); 
 | 
|  |     45 |           (hd2, tl2) <- q.parse(tl1)) yield (new ~(hd1, hd2), tl2)
 | 
|  |     46 |   }
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     47 | 
 | 
| 971 |     48 |   // map parser
 | 
|  |     49 |   def map[S](f: => T => S) = new Parser[I, S] {
 | 
|  |     50 |     def parse(in: I) = for ((hd, tl) <- p.parse(in)) yield (f(hd), tl)
 | 
|  |     51 |   }
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     52 | }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     53 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     54 | // atomic parser for (particular) strings
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     55 | case class StrParser(s: String) extends Parser[String, String] {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     56 |   def parse(sb: String) = {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     57 |     val (prefix, suffix) = sb.splitAt(s.length)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     58 |     if (prefix == s) Set((prefix, suffix)) else Set()
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     59 |   }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     60 | }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     61 | 
 | 
| 981 |     62 | 
 | 
|  |     63 | 
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     64 | // atomic parser for identifiers (variable names)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     65 | case object IdParser extends Parser[String, String] {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     66 |   val reg = "[a-z][a-z,0-9]*".r
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     67 |   def parse(sb: String) = reg.findPrefixOf(sb) match {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     68 |     case None => Set()
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     69 |     case Some(s) => Set(sb.splitAt(s.length))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     70 |   }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     71 | }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     72 | 
 | 
| 948 |     73 | // atomic parser for numbers (transformed into Ints)
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     74 | case object NumParser extends Parser[String, Int] {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     75 |   val reg = "[0-9]+".r
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     76 |   def parse(sb: String) = reg.findPrefixOf(sb) match {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     77 |     case None => Set()
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     78 |     case Some(s) => {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     79 |       val (hd, tl) = sb.splitAt(s.length)
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     80 |       Set((hd.toInt, tl)) 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     81 |     }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     82 |   }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     83 | }
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     84 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     85 | // the following string interpolation allows us to write 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     86 | // StrParser(_some_string_) more conveniently as 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     87 | //
 | 
| 981 |     88 | // p"_some_string_" 
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |     89 | 
 | 
| 906 |     90 | extension (sc: StringContext) 
 | 
| 965 |     91 |   def p(args: Any*) = StrParser(sc.s(args*))
 | 
| 906 |     92 | 
 | 
| 981 |     93 | 
 | 
|  |     94 | 
 | 
|  |     95 | // the following is an alternative way to achieve the same, except
 | 
|  |     96 | // that the p needs parentheses as in
 | 
|  |     97 | //
 | 
|  |     98 | // p("_some_string_")
 | 
|  |     99 | //
 | 
|  |    100 | //import StrParser.{apply => p}
 | 
|  |    101 | 
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    102 | // the abstract syntax trees for the WHILE language
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    103 | abstract class Stmt
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    104 | abstract class AExp
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    105 | abstract class BExp 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    106 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    107 | type Block = List[Stmt]
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    108 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    109 | case object Skip extends Stmt
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    110 | case class If(a: BExp, bl1: Block, bl2: Block) extends Stmt
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    111 | case class While(b: BExp, bl: Block) extends Stmt
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    112 | case class Assign(s: String, a: AExp) extends Stmt
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    113 | case class Write(s: String) extends Stmt
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    114 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    115 | case class Var(s: String) extends AExp
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    116 | case class Num(i: Int) extends AExp
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    117 | case class Aop(o: String, a1: AExp, a2: AExp) extends AExp
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    118 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    119 | case object True extends BExp
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    120 | case object False extends BExp
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    121 | case class Bop(o: String, a1: AExp, a2: AExp) extends BExp
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    122 | case class And(b1: BExp, b2: BExp) extends BExp
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    123 | case class Or(b1: BExp, b2: BExp) extends BExp
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    124 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    125 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    126 | // arithmetic expressions
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    127 | lazy val AExp: Parser[String, AExp] = 
 | 
| 971 |    128 |   (Te ~ p"+" ~ AExp).map[AExp]{ case x ~ _ ~ z => Aop("+", x, z) } ||
 | 
|  |    129 |   (Te ~ p"-" ~ AExp).map[AExp]{ case x ~ _ ~ z => Aop("-", x, z) } || Te
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    130 | lazy val Te: Parser[String, AExp] = 
 | 
| 971 |    131 |   (Fa ~ p"*" ~ Te).map[AExp]{ case x ~ _ ~ z => Aop("*", x, z) } || 
 | 
|  |    132 |   (Fa ~ p"/" ~ Te).map[AExp]{ case x ~ _ ~ z => Aop("/", x, z) } || Fa  
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    133 | lazy val Fa: Parser[String, AExp] = 
 | 
| 971 |    134 |    (p"(" ~ AExp ~ p")").map{ case _ ~ y ~ _ => y } || 
 | 
| 948 |    135 |    IdParser.map(Var(_)) || 
 | 
|  |    136 |    NumParser.map(Num(_))
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    137 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    138 | // boolean expressions with some simple nesting
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    139 | lazy val BExp: Parser[String, BExp] = 
 | 
| 971 |    140 |   (AExp ~ p"==" ~ AExp).map[BExp]{ case x ~ _ ~ z => Bop("==", x, z) } || 
 | 
|  |    141 |   (AExp ~ p"!=" ~ AExp).map[BExp]{ case x ~ _ ~ z => Bop("!=", x, z) } || 
 | 
|  |    142 |   (AExp ~ p"<" ~ AExp).map[BExp]{ case x ~ _ ~ z => Bop("<", x, z) } || 
 | 
|  |    143 |   (AExp ~ p">" ~ AExp).map[BExp]{ case x ~ _ ~ z => Bop(">", x, z) } ||
 | 
|  |    144 |   (p"(" ~ BExp ~ p")" ~ p"&&" ~ BExp).map[BExp]{ case _ ~ y ~ _ ~ _ ~ v => And(y, v) } ||
 | 
|  |    145 |   (p"(" ~ BExp ~ p")" ~ p"||" ~ BExp).map[BExp]{ case _ ~ y ~ _ ~ _ ~ v => Or(y, v) } ||
 | 
|  |    146 |   (p"true".map[BExp]{ _ => True }) || 
 | 
|  |    147 |   (p"false".map[BExp]{ _ => False }) ||
 | 
|  |    148 |   (p"(" ~ BExp ~ p")").map[BExp]{ case _ ~ x ~ _ => x }
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    149 | 
 | 
| 971 |    150 | // Stmt: a single statement
 | 
|  |    151 | // Stmts: multiple statements
 | 
|  |    152 | // Block: blocks (enclosed in curly braces)
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    153 | lazy val Stmt: Parser[String, Stmt] =
 | 
| 919 |    154 |   ((p"skip".map[Stmt]{_ => Skip }) ||
 | 
| 971 |    155 |   (IdParser ~ p":=" ~ AExp).map[Stmt]{ case x ~ _ ~ z => Assign(x, z) } ||
 | 
|  |    156 |   (p"write(" ~ IdParser ~ p")").map[Stmt]{ case _ ~ y ~ _ => Write(y) } ||
 | 
|  |    157 |   (p"if" ~ BExp ~ p"then" ~ Block ~ p"else" ~ Block)
 | 
|  |    158 |     .map[Stmt]{ case _ ~ y ~ _ ~ u ~ _ ~ w => If(y, u, w) } ||
 | 
|  |    159 |   (p"while" ~ BExp ~ p"do" ~ Block).map[Stmt]{ case _ ~ y ~ _ ~ w => While(y, w) })  
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    160 | lazy val Stmts: Parser[String, Block] =
 | 
| 919 |    161 |   (Stmt ~ p";" ~ Stmts).map[Block]{ case x ~ _ ~ z => x :: z } ||
 | 
|  |    162 |   (Stmt.map[Block]{ s => List(s) })
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    163 | lazy val Block: Parser[String, Block] =
 | 
| 919 |    164 |   ((p"{" ~ Stmts ~ p"}").map{ case _ ~ y ~ _ => y } || 
 | 
| 971 |    165 |   (Stmt.map(s => List(s))))
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    166 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    167 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    168 | // Examples
 | 
| 956 |    169 | println(AExp.parse_all("2*2*2"))
 | 
| 955 |    170 | println(BExp.parse_all("5+3"))
 | 
|  |    171 | println(Stmt.parse_all("5==3"))
 | 
|  |    172 | println(Stmt.parse_all("x2:=5+3"))
 | 
|  |    173 | println(Block.parse_all("{x:=5;y:=8}"))
 | 
|  |    174 | println(Block.parse_all("if(false)then{x:=5}else{x:=10}"))
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    175 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    176 | val fib = """n := 10;
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    177 |              minus1 := 0;
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    178 |              minus2 := 1;
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    179 |              temp := 0;
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    180 |              while (n > 0) do {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    181 |                  temp := minus2;
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    182 |                  minus2 := minus1 + minus2;
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    183 |                  minus1 := temp;
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    184 |                  n := n - 1
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    185 |              };
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    186 |              result := minus2""".replaceAll("\\s+", "")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    187 | 
 | 
| 955 |    188 | println("fib testcase:")
 | 
|  |    189 | println(Stmts.parse_all(fib))
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    190 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    191 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    192 | // an interpreter for the WHILE language
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    193 | type Env = Map[String, Int]
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    194 | 
 | 
| 971 |    195 | def eval_aexp(a: AExp, env: Env) : Int =
 | 
|  |    196 |   a match {
 | 
|  |    197 |     case Num(i) => i
 | 
|  |    198 |     case Var(s) => env(s)
 | 
|  |    199 |     case Aop("+", a1, a2) => eval_aexp(a1, env) + eval_aexp(a2, env)
 | 
|  |    200 |     case Aop("-", a1, a2) => eval_aexp(a1, env) - eval_aexp(a2, env)
 | 
|  |    201 |     case Aop("*", a1, a2) => eval_aexp(a1, env) * eval_aexp(a2, env)
 | 
|  |    202 |     case Aop("/", a1, a2) => eval_aexp(a1, env) / eval_aexp(a2, env)
 | 
|  |    203 |   }
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    204 | 
 | 
| 973 |    205 | def eval_bexp(b: BExp, env: Env) : Boolean = b match {
 | 
| 971 |    206 |     case True => true
 | 
|  |    207 |     case False => false
 | 
|  |    208 |     case Bop("==", a1, a2) => eval_aexp(a1, env) == eval_aexp(a2, env)
 | 
|  |    209 |     case Bop("!=", a1, a2) => !(eval_aexp(a1, env) == eval_aexp(a2, env))
 | 
|  |    210 |     case Bop(">", a1, a2) => eval_aexp(a1, env) > eval_aexp(a2, env)
 | 
|  |    211 |     case Bop("<", a1, a2) => eval_aexp(a1, env) < eval_aexp(a2, env)
 | 
|  |    212 |     case And(b1, b2) => eval_bexp(b1, env) && eval_bexp(b2, env)
 | 
|  |    213 |     case Or(b1, b2) => eval_bexp(b1, env) || eval_bexp(b2, env)
 | 
|  |    214 |   }
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    215 | 
 | 
| 973 |    216 | def eval_stmt(s: Stmt, env: Env) : Env = s match {
 | 
| 971 |    217 |     case Skip => env
 | 
|  |    218 |     case Assign(x, a) => env + (x -> eval_aexp(a, env))
 | 
|  |    219 |     case If(b, bl1, bl2) => if (eval_bexp(b, env)) eval_bl(bl1, env) else eval_bl(bl2, env) 
 | 
|  |    220 |     case While(b, bl) => 
 | 
|  |    221 |       if (eval_bexp(b, env)) eval_stmt(While(b, bl), eval_bl(bl, env))
 | 
|  |    222 |       else env
 | 
|  |    223 |     case Write(x) => { println(env(x)) ; env }  
 | 
|  |    224 |   }
 | 
| 973 |    225 | def eval_bl(bl: Block, env: Env) : Env = bl match {
 | 
| 971 |    226 |     case Nil => env
 | 
|  |    227 |     case s::bl => eval_bl(bl, eval_stmt(s, env))
 | 
|  |    228 |   }
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    229 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    230 | def eval(bl: Block) : Env = eval_bl(bl, Map())
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    231 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    232 | // parse + evaluate fib program; then lookup what is
 | 
| 742 |    233 | // stored under the variable "result" 
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    234 | println(eval(Stmts.parse_all(fib).head)("result"))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    235 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    236 | 
 | 
| 971 |    237 | // more examples
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    238 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    239 | // calculate and print all factors bigger 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    240 | // than 1 and smaller than n
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    241 | println("Factors")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    242 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    243 | val factors =  
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    244 |    """n := 12;
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    245 |       f := 2;
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    246 |       while (f < n / 2 + 1) do {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    247 |         if ((n / f) * f == n) then  { write(f) } else { skip };
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    248 |         f := f + 1
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    249 |       }""".replaceAll("\\s+", "")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    250 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    251 | println(eval(Stmts.parse_all(factors).head))
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    252 | 
 | 
| 742 |    253 | 
 | 
| 732 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    254 | // calculate all prime numbers up to a number 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    255 | println("Primes")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    256 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    257 | val primes =  
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    258 |    """end := 100;
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    259 |       n := 2;
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    260 |       while (n < end) do {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    261 |         f := 2;
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    262 |         tmp := 0;
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    263 |         while ((f < n / 2 + 1) && (tmp == 0)) do {
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    264 |           if ((n / f) * f == n) then  { tmp := 1 } else { skip };
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    265 |           f := f + 1
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    266 |         };
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    267 |         if (tmp == 0) then { write(n) } else { skip };
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    268 |         n  := n + 1
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    269 |       }""".replaceAll("\\s+", "")
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    270 | 
 | 
| 
Christian Urban <christian.urban@kcl.ac.uk> parents: diff
changeset |    271 | println(eval(Stmts.parse_all(primes).head))
 |