357    (IdParser ~ "[" ~ AExp ~ "]" ~ ":=" ~ AExp) ==> {  | 
   359    (IdParser ~ "[" ~ AExp ~ "]" ~ ":=" ~ AExp) ==> {  | 
   358      case x ~ _ ~ z ~ _ ~ _ ~ u => AssignA(x, z, u): Stmt } |  | 
   360      case x ~ _ ~ z ~ _ ~ _ ~ u => AssignA(x, z, u): Stmt } |  | 
   359    ("if" ~ BExp ~ "then" ~ Block ~ "else" ~ Block) ==> | 
   361    ("if" ~ BExp ~ "then" ~ Block ~ "else" ~ Block) ==> | 
   360     { case _ ~ y ~ _ ~ u ~ _ ~w => If(y, u, w): Stmt } | | 
   362     { case _ ~ y ~ _ ~ u ~ _ ~w => If(y, u, w): Stmt } | | 
   361    ("while" ~ BExp ~ "do" ~ Block) ==> { case _ ~ y ~ _ ~ w => While(y, w) } | | 
   363    ("while" ~ BExp ~ "do" ~ Block) ==> { case _ ~ y ~ _ ~ w => While(y, w) } | | 
   362    ("new" ~ IdParser ~ "[" ~ NumParser ~ "]") ==> {  | 
   364    ("new(" ~ IdParser ~ "[" ~ NumParser ~ "])") ==> {  | 
   363     case _ ~ y ~ _ ~ u ~ _ => ArrayDef(y, u) } |  | 
   365     case _ ~ y ~ _ ~ u ~ _ => ArrayDef(y, u) } |  | 
   364    ("write" ~ IdParser) ==> { case _ ~ y => Write(y) }  | 
   366    ("write" ~ IdParser) ==> { case _ ~ y => Write(y) }  | 
   365    | 
   367    | 
   366 lazy val Stmts: Parser[String, Block] =  | 
   368 lazy val Stmts: Parser[String, Block] =  | 
   367   (Stmt ~ ";" ~ Stmts) ==> { case x ~ _ ~ z => x :: z : Block } | | 
   369   (Stmt ~ ";" ~ Stmts) ==> { case x ~ _ ~ z => x :: z : Block } | | 
   403   | 
   405   | 
   404 // simple BF instructions translation  | 
   406 // simple BF instructions translation  | 
   405 def instr(c: Char) : String = c match { | 
   407 def instr(c: Char) : String = c match { | 
   406   case '>' => "ptr := ptr + 1;"  | 
   408   case '>' => "ptr := ptr + 1;"  | 
   407   case '<' => "ptr := ptr - 1;"  | 
   409   case '<' => "ptr := ptr - 1;"  | 
   408   case '+' => "field[ptr] := field[ptr] + 1;"  | 
   410   case '+' => "mem[ptr] := mem[ptr] + 1;"  | 
   409   case '-' => "field[ptr] := field[ptr] - 1;"  | 
   411   case '-' => "mem[ptr] := mem[ptr] - 1;"  | 
   410   case '.' => "x := field[ptr]; write x;"  | 
   412   case '.' => "x := mem[ptr]; write x;"  | 
   411   //case ',' => "XXX" // "ptr = getchar();\n"  | 
   413   //case ',' => "XXX" // "ptr = getchar();\n"  | 
   412   case '['  => "while (field[ptr] != 0) do {" | 
   414   case '['  => "while (mem[ptr] != 0) do {" | 
   413   case ']'  => "skip};"  | 
   415   case ']'  => "skip};"  | 
   414   case _ => ""  | 
   416   case _ => ""  | 
   415 }  | 
   417 }  | 
   416   | 
   418   | 
   417 def instrs(prog: String) : String =  | 
   419 def instrs(prog: String) : String =  | 
   441 def spl(s: String) = splice(s.toList, Nil).reverse  | 
   443 def spl(s: String) = splice(s.toList, Nil).reverse  | 
   442   | 
   444   | 
   443 def instr2(c: Char, n: Int) : String = c match { | 
   445 def instr2(c: Char, n: Int) : String = c match { | 
   444   case '>' => s"ptr := ptr + $n;"  | 
   446   case '>' => s"ptr := ptr + $n;"  | 
   445   case '<' => s"ptr := ptr - $n;"  | 
   447   case '<' => s"ptr := ptr - $n;"  | 
   446   case '0' => s"field[ptr] := 0;"  | 
   448   case '0' => s"mem[ptr] := 0;"  | 
   447   case '+' => s"field[ptr] := field[ptr] + $n;"  | 
   449   case '+' => s"mem[ptr] := mem[ptr] + $n;"  | 
   448   case '-' => s"field[ptr] := field[ptr] - $n;"  | 
   450   case '-' => s"mem[ptr] := mem[ptr] - $n;"  | 
   449   case '.' => s"x := field[ptr]; write x;"   | 
   451   case '.' => s"x := mem[ptr]; write x;"   | 
   450   case '['  => "while (field[ptr] != 0) do {" * n  | 
   452   case '['  => "while (mem[ptr] != 0) do {" * n  | 
   451   case ']'  => "skip};" * n  | 
   453   case ']'  => "skip};" * n  | 
   452   case _ => ""  | 
   454   case _ => ""  | 
   453 }  | 
   455 }  | 
   454   | 
   456   | 
   455 def instrs2(prog: String) : String =  | 
   457 def instrs2(prog: String) : String =  | 
   456   spl(prog.replaceAll("""\[-\]""", "0")).map{ case (c, n) => instr2(c, n) }.mkString | 
   458   spl(prog.replaceAll("""\[-\]""", "0")).map{ case (c, n) => instr2(c, n) }.mkString | 
   457   | 
   459   | 
   458 def bf_str(prog: String) : String = { | 
   460 def bf_str(prog: String) : String = { | 
   459   "\n" ++  | 
   461   "new(mem[30000]);" ++  | 
   460   "ptr := 15000;" ++  | 
   462   "ptr := 15000;" ++  | 
   461   instrs2(prog) ++  | 
   463   instrs2(prog) ++  | 
   462   "skip"  | 
   464   "skip"  | 
   463 }  | 
   465 }  | 
   464   | 
   466   | 
   466   println(s"BF pre-processing of $name")  | 
   468   println(s"BF pre-processing of $name")  | 
   467   val bf_string = bf_str(prog).replaceAll("\\s", "") | 
   469   val bf_string = bf_str(prog).replaceAll("\\s", "") | 
   468   println(s"BF parsing (program length ${bf_string.length} characters)") | 
   470   println(s"BF parsing (program length ${bf_string.length} characters)") | 
   469   val (time, bf_prog) = time_needed(1, Stmts.parse_all(bf_string).toList.head)  | 
   471   val (time, bf_prog) = time_needed(1, Stmts.parse_all(bf_string).toList.head)  | 
   470   println(s"BF generated WHILE program (needed $time for parsing)")  | 
   472   println(s"BF generated WHILE program (needed $time for parsing)")  | 
   471   compile_and_run(ArrayDef("field", 30000) :: bf_prog, name) | 
   473   compile_and_run(bf_prog, name)  | 
   472 }  | 
   474 }  | 
   473   | 
   475   | 
   474 // a benchmark program (counts down from 'Z' to 'A')  | 
   476 // a benchmark program (counts down from 'Z' to 'A')  | 
   475 val bf0 = """>++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++  | 
   477 val bf0 = """>++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++  | 
   476             [>++++++++<-]>.[-]<<>++++++++++[>++++++++++[>++  | 
   478             [>++++++++<-]>.[-]<<>++++++++++[>++++++++++[>++  |