factorもどき
inforno :: Scalaでスタック指向言語をサクッと実装する や 合併のお知らせ|OKIソフトウェア
を参考に自分もfactorもどきをscalaでかいてみました。かなりコピペしています。
かなりいろんなことをはしょっています。
import scala.util.parsing.combinator._ import java.io.{FileReader, InputStreamReader} import scala.collection.mutable.{Stack, HashMap} class TinyFactorParser extends JavaTokenParsers { var quoteIndex = 0 def quoteName = { quoteIndex += 1 ;"quot"+ quoteIndex} var qTable=new HashMap[Any,List[Any]]() lazy val item:Parser[Any] = quotation| "true" ^^^ true|"false" ^^^ false | stringLiteral ^^ (s => s.substring(1, s.length() - 1)) | """[a-zA-Z_0-9\+\-\*\<\>\=]+""".r ^^ (s => try {s.toLong} catch {case ex: NumberFormatException => Symbol(s)}) lazy val quotation:Parser[Any]="[" ~> rep(item) <~ "]" ^^ {script =>{var name = Symbol("") ;name=Symbol(quoteName); qTable += (name -> script);name}} lazy val word:Parser[(Any,List[Any])]=":" ~>rep(item)<~ ";" ^^ {case name::script => (name -> script)} lazy val program:Parser[HashMap[Any,List[Any]]]=rep(word) ^^ {HashMap() ++= _ } } object TinyFactor{ var dataStack= new Stack[Any] () var procStack= new Stack[Any] () var quoteTable=new HashMap[Any,List[Any]]() var wordTable=new HashMap[Any,List[Any]]() def pop=dataStack.pop def push(v:Any)=dataStack.push(v) def ilB2(f:(Long,Long)=>Boolean){(pop,pop) match{ case (x,y)=> dataStack.push(f(y.asInstanceOf[Long],x.asInstanceOf[Long])) }} def iArI2(f:(Long,Long)=>Long){(pop,pop) match{ case (x,y)=> dataStack.push(f(y.asInstanceOf[Long],x.asInstanceOf[Long])) }} def callWord(x:Any,y:HashMap[Any,List[Any]]){procStack++=y(x).reverse} val execTable:HashMap[Any,()=>Unit]= HashMap( (Symbol("drop"), ()=>{ pop }), (Symbol("dup"), ()=>{val v= pop;push(v);push(v) }), (Symbol("swap"),()=>{(pop,pop) match {case (x,y) => {push(x);push(y)}}}), (Symbol("rot"),()=>{(pop,pop,pop) match {case (x,y,z) => {push(x);push(z);push(y)}}}), (Symbol("if"),()=>{(pop,pop,pop) match {case (x,y,z) =>{if(z==true) callWord(y,quoteTable) else callWord(x,quoteTable)}}}), (Symbol("dip"),()=>{(pop,pop) match {case (x,y) => {procStack.push(y);callWord(x,quoteTable)}}}), (Symbol("+"),() => {iArI2(_+_)}), (Symbol("-"),()=> {iArI2(_-_)} ), (Symbol("*"),()=> { iArI2(_*_)} ), (Symbol("/"),()=> { iArI2(_/_)} ), (Symbol(">"),()=> { ilB2(_>_) } ), (Symbol("<"),()=> { ilB2(_<_) } ), (Symbol(">="),()=> { ilB2(_>=_)} ), (Symbol("<="),()=> { ilB2(_<=_) } ), (Symbol("=="),()=> { ilB2(_==_) } ) ) def displayStack{ println("dataStack:"+dataStack.toString) println("procStack:"+procStack.toString)} def main(args: Array[String]) { val reader = if (args(0) == "-") new InputStreamReader(System.in) else new FileReader(args(0)) val parsers = new TinyFactorParser wordTable = parsers.parseAll(parsers.program, reader).get quoteTable=parsers.qTable def evalProcTop{ procStack.pop match { case x if quoteTable.contains(x) => {push(x)} case x if wordTable.contains(x) => {callWord(x,wordTable)} case x if execTable.contains(x) => {execTable(x) () } case x => push(x) } } def evalProcAll{ while( ! procStack.isEmpty ){displayStack;evalProcTop} } println(wordTable) println(quoteTable) callWord(Symbol("main"),wordTable) evalProcAll displayStack } }