scala/ScalaBook/chapter-04/ramint.scala
import scala.util.parsing.combinator._
trait Command
case class Commands(cmds: List[Command]) extends Command
case class IFcomm(cond: String,
then_part: Commands,
else_part: Commands) extends Command
case class WHILEcomm(cond: String, do_part: Commands) extends Command
case class WRITEcomm(outvar: String) extends Command
case class READcomm(invar: String) extends Command
case class ASSIGNMENTcomm(ass_var: String, action: String) extends Command
object RAMparser extends JavaTokenParsers {
def commands = rep(command) ^^ { case cmds => Commands(cmds) }
def command = ifcommand | whilecommand | writecommand |
readcommand | assignment | failure("unexpected symbol")
def ifcommand: Parser[Command] = ("if" ~ ident ~ "=" ~ "0" ~ "then" ~ commands ~ optElse ~ "end") ^^
{ case "if" ~ id ~ "=" ~ "0" ~ "then" ~ thenpart ~ elsepart ~ "end" =>
IFcomm(id,thenpart,elsepart)}
def optElse: Parser[Commands] = opt("else"~commands) ^^ { case None => Commands(Nil)
case Some("else"~cmds) => cmds}
def whilecommand: Parser[Command] = ("while" ~ ident ~ "=" ~ "0" ~ "do" ~ commands ~ "end") ^^
{case "while"~id~"="~"0"~"do"~cmds~"end" => WHILEcomm(id,cmds) }
def writecommand = ("write" ~ ident) ^^ { case "write"~id => WRITEcomm(id) }
def readcommand = ("read" ~ ident) ^^ { case "read"~id => READcomm(id) }
def assignment = (ident ~ ("++" | "--")) ^^ { case id~op => ASSIGNMENTcomm(id,op) }
}
var ST: Map[String,Int] = Map()
def eval(commands: List[Command]): Unit = {
if (! commands.isEmpty) {
commands.head match {
case IFcomm(condvar,thenPart,elsePart) => if (! ST.contains(condvar) )
ST += (condvar -> 0)
if ( ST(condvar) == 0 )
eval(thenPart.cmds)
else
eval(elsePart.cmds)
case WHILEcomm(condvar, doCMDs) => if (! ST.contains(condvar) ) ST += (condvar -> 0)
while ( ST(condvar) == 0 ) {
eval(doCMDs.cmds)
}
case WRITEcomm(myvar) => if (! ST.contains(myvar) ) {
ST += (myvar -> 0)
}
println(ST(myvar))
case READcomm(myvar) => if (! ST.contains(myvar) ) {
ST += (myvar -> 0)
}
print("? ")
var x = readInt()
if (x < 0) {
println("***ERROR: Number cannot be negative")
return
}
else
ST += (myvar -> x)
case ASSIGNMENTcomm(invar,act) => if (! ST.contains(invar) ) {
ST += (invar -> 0)
}
if (act == "++")
ST += (invar -> (ST(invar)+1))
else {
if ( ST(invar) > 0 )
ST += (invar -> (ST(invar)-1))
}
}
eval(commands.tail)
}
}
import java.io.FileReader
if (args.isEmpty)
println("Usage: ramint input_file")
else if (args.length > 1)
println("Usage: ramint input_file")
else {
try {
val reader = new FileReader(args(0))
val result =
RAMparser.parseAll(RAMparser.commands, reader)
if ( result.successful) {
val parseTree = result.get
eval(parseTree.cmds)
}
else
println(result)
} catch {
case e : Exception =>
println("File "+args(0)+" does not exist")
exit()
}
}