Guest User

Untitled

a guest
Feb 20th, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.97 KB | None | 0 0
  1. package calc3
  2.  
  3. import scala.util.matching.Regex
  4. import lex._
  5.  
  6. /*
  7.  
  8. 変更点
  9.  
  10. ●コンパイルの効率化
  11.  リスト同士の連結をやめて、::でリストを作成するように変更。
  12. ●usageを表示するように。
  13. ●パーサコンビネータとして扱えるような形にパーサを変更。
  14. ●エラーの箇所を出力(ただし1個)
  15. ●ストリームを使って、字句解析する。
  16. ●字句解析は別パッケージ
  17. */
  18.  
  19. sealed abstract class Atom
  20. case class Var(value: Int) extends Atom
  21. case class Add(left:Atom, right:Atom) extends Atom
  22. case class Mul(left:Atom, right:Atom) extends Atom
  23. case class Sub(left:Atom, right:Atom) extends Atom
  24. case class Div(left:Atom, right:Atom) extends Atom
  25. case class Void extends Atom
  26.  
  27. object main {
  28. // パース ------------------------------
  29. def parse(str:String):Atom = {
  30. val cons = Stream.cons
  31.  
  32. // 構文解析 ------------------------
  33. /**
  34. * 予測されたトークンを取り除く
  35. */
  36. def eat(as:(Atom,Stream[Token]))(eatToken:Token,eatStr:String) = {
  37. var (a,stm) = as
  38. if (stm.head==eatToken)
  39. (a,stm.tail)
  40. else
  41. throw new Error("syntax error: found "+stm.head+" expected '"+eatStr+"'"+stm.head.err())
  42. }
  43. /**
  44. * 数字あるいは( exp )
  45. */
  46. def fact(as:(Atom,Stream[Token])):(Atom,Stream[Token]) = {
  47. as match {
  48. case (_,cons(lex.Num(i),t)) => (Var(i) , t)
  49. case (a,cons(lex.Spr(), t)) => eat(exp(a,t))(lex.Epr(),")")
  50. case (_,cons(a,_)) => throw new Error("syntax error:found "+a+" expected expression "+a.err())
  51. }
  52. }
  53.  
  54. /**
  55. * 掛け算か、fact
  56. */
  57. def term(as:(Atom,Stream[Token])):(Atom,Stream[Token]) = {
  58. as match {
  59. case (Void(), t) => term(fact((Void(),t)))
  60. case (a, cons(lex.Mul(),t)) =>
  61. val (b, t2) = fact((Void(),t))
  62. term(Mul(a, b), t2)
  63. case (a, cons(lex.Div(),t)) =>
  64. val (b, t2) = fact((Void(),t))
  65. term(Div(a, b), t2)
  66. case _ => as
  67. }
  68. }
  69.  
  70. /**
  71. * 足し算かterm
  72. */
  73. def exp(as:(Atom,Stream[Token])):(Atom,Stream[Token]) = {
  74. as match {
  75. case (Void(), t) => exp(term((Void(),t)))
  76. case (a, cons(lex.Add(),t)) =>
  77. val (b, t2) = term((Void(),t))
  78. exp(Add(a, b), t2)
  79. case (a, cons(lex.Sub(),t)) =>
  80. val (b, t2) = term((Void(),t))
  81. exp(Sub(a, b), t2)
  82. case _ => as
  83. }
  84. }
  85.  
  86. val tokens = new Lex(str).tokens();
  87. val (a,t) = eat(exp((Void(),tokens)))(lex.Eof(),"Eof")
  88. a
  89. }
  90.  
  91. // コンパイラ ------------------------------------------
  92. var i = -1
  93. val VAL, ADD, SUB, MUL, DIV, RET = {i += 1; i}
  94.  
  95. def compile(a:Atom) = {
  96. def comp(a:Atom,rtn:List[Int]):List[Int] = {
  97. a match {
  98. case Var(i) => i::VAL::rtn
  99. case Add(a,b) => ADD :: comp(a,comp(b,rtn))
  100. case Sub(a,b) => SUB :: comp(a,comp(b,rtn))
  101. case Mul(a,b) => MUL :: comp(a,comp(b,rtn))
  102. case Div(a,b) => DIV :: comp(a,comp(b,rtn))
  103. case Void() => throw new Exception("compile time error")
  104. }
  105. }
  106. (RET::comp(a,List())).reverse
  107. }
  108.  
  109. // 仮想マシン ------------------------------------------
  110.  
  111. def eval(c:List[Int]):Int = {
  112. def eval1(s:List[Int], c:List[Int]):Int = {
  113. (s,c) match {
  114. case (s, VAL::a::c) => eval1(a::s, c)// 値
  115. case (a::b::s, ADD::c) => eval1((a+b)::s, c)// 足し算
  116. case (a::b::s, SUB::c) => eval1((a-b)::s, c)// 引き算
  117. case (a::b::s, MUL::c) => eval1((a*b)::s, c)// 掛け算
  118. case (a::b::s, DIV::c) => eval1((a/b)::s, c)// 割り算
  119. case (a::s, RET::c) => a// リターン
  120. case (_, _) => throw new Exception("runtime error")
  121. }
  122. }
  123. eval1(List():List[Int], c)
  124. }
  125.  
  126. // メイン関数 ---------------------------------------
  127. def main(args: Array[String]):Unit = {
  128. try {
  129. if(args.length <= 0)
  130. throw new Exception("usage: scala calc3.main expression\nexp: scala calc3.main 1+2*3");
  131. val a = parse(args(0))
  132. println(a)
  133. val codes = compile(a)
  134. println(codes)
  135. val result = eval(codes)
  136. println(result)
  137. } catch {
  138. case e => println(e.getMessage() )
  139. }
  140. }
  141.  
  142. }
Add Comment
Please, Sign In to add comment