본문 바로가기

Programming/Scala

Scala - Basic calculator using Parser Combinator (스칼라 언어로 만드는 간단한 사칙 연산 계산기 프로그램)

Scala 언어에서 지원하는 매력적인 라이브러리가 있는데, 그 중 하나가 Parser Combinator 이다. 이 라이브러리를 이용하면, Parser 를 작성하기가 쉽고, 소스가 이해하기도 쉽다. 그러므로 유지보수도 쉬워진다.


그래서 연습삼아서 계산기 프로그램을 작성해 보았다.

간단하게 사칙연산을 지원하고 숫자는 자연수, 정수, 소수(floating point number) 까지만 지원된다.


소스는 아래와 같다.




package parser


import util.parsing.combinator.JavaTokenParsers


/**

 * User: starblood

 * Date: 8/1/11

 * Floating point 를 계산하는 프로그램.

 * Scala 언어에서 지원하는 Parser Combinator library 를 사용하여 간단 하게 구현함.

 * 표현식은 부동소숫점을 나타내는 숫자들의 사칙연산 (곱하기, 나누기, 더하기, 빼기) 와 괄호("(", ")") 가 지원됨.

 *

 * 문법은 아래와 같다.

 * expr := term , {("+" , term | "-" , term)}

 * term := factor , {("*" , factor | "*" , factor)}

 * factor := "(" , expr , ")" | floatingPointNumber

 */

object ExprParser extends JavaTokenParsers {

  def expr : Parser[Double] = term ~! rep("+" ~! term | "-" ~! term)  ^^ {

    case term~termList => {

      termList.foldLeft(term){(acc, termExpr) =>

        termExpr match {

          case "+"~trm => acc + trm

          case "-"~trm => acc - trm

        }

      }

    }

  }

  def term : Parser[Double] = factor ~! rep("*" ~! factor | "/" ~! factor) ^^ {

    case factor~factorList => {

      factorList.foldLeft(factor){(acc, facExpr) =>

        facExpr match {

          case "*"~fac => acc * fac

          case "/"~fac => acc / fac

        }

      }

    }

  }

  def factor : Parser[Double] = "(" ~! expr ~! ")" ^^ {case "("~expr~")" => expr} |

                                floatingPointNumber ^^ {case floatingPointNumber => floatingPointNumber.toDouble}


  def main(args: Array[String]) {

    val str = "(5 - 1) * (3 + 2)"

    println(parseAll(expr, str)) // 결과 출력

  }

}