Skip to content

Instantly share code, notes, and snippets.

@kmizu
Last active July 14, 2021 10:19
Show Gist options
  • Save kmizu/a9f9c29262d19f6110cfde4f12104109 to your computer and use it in GitHub Desktop.
Save kmizu/a9f9c29262d19f6110cfde4f12104109 to your computer and use it in GitHub Desktop.
8÷2(3+1) に対する二通りのパーザ(あるいはインタプリタ)作ってみた
import com.github.kmizu.scomb._
object Calculator1 extends SCombinator[Int] {
def root: Parser[Int] = expression
def expression: Parser[Int] = rule(A)
def A: Parser[Int] = rule(chainl(M) {
$("+").map { op => (lhs: Int, rhs: Int) => lhs + rhs } |
$("-").map { op => (lhs: Int, rhs: Int) => lhs - rhs }
})
def M: Parser[Int] = rule(
chainl(N) {
$("×").map { op => (lhs: Int, rhs: Int) => lhs * rhs } |
$("÷").map { op => (lhs: Int, rhs: Int) => lhs / rhs }
}
)
def N: Parser[Int] = rule {
(P ~ P.*).map{ case a ~ bs => bs.foldLeft(a){_ * _} }
}
def P: P[Int] = rule{ K | number }
def K: P[Int] =
(for {
_ <- string("("); e <- expression; _ <- string(")")} yield e)
def number: P[Int] = rule(set('0'to'9').+.map{ digits => digits.mkString.toInt})
}
import com.github.kmizu.scomb._
object Calculator2 extends SCombinator[Int] {
def root: Parser[Int] = expression
def expression: Parser[Int] = rule(A)
def A: Parser[Int] = rule(chainl(N) {
$("+").map { op => (lhs: Int, rhs: Int) => lhs + rhs } |
$("-").map { op => (lhs: Int, rhs: Int) => lhs - rhs }
})
def N: Parser[Int] = rule {
(M ~ M.*).map{ case a ~ bs => bs.foldLeft(a){_ * _} }
}
def M: Parser[Int] = rule(
chainl(P) {
$("×").map { op => (lhs: Int, rhs: Int) => lhs * rhs } |
$("÷").map { op => (lhs: Int, rhs: Int) => lhs / rhs }
}
)
def P: P[Int] = rule{ K | number }
def K: P[Int] =
(for {
_ <- string("("); e <- expression; _ <- string(")")} yield e)
def number: P[Int] = rule(set('0'to'9').+.map{ digits => digits.mkString.toInt})
}
[mizushima]$ sbt console
warning: ignoring extraneous `sbt-` prefix in version `sbt-1.5.2`
(set by /home/mizushima/work/implicit_multiplication/project/build.properties)
[info] welcome to sbt 1.5.2 (Ubuntu Java 11.0.9.1)
[info] loading project definition from /home/mizushima/work/implicit_multiplication/project
[info] loading settings for project implicit_multiplication from build.sbt ...
[info] set current project to implicit_multiplication (in build file:/home/mizushima/work/implicit_multiplication/)
[info] Starting scala interpreter...
Welcome to Scala 2.13.4 (OpenJDK 64-Bit Server VM, Java 11.0.9.1).
Type in expressions for evaluation. Or try :help.
scala> Calculator1.parse("8÷2(3+1)")
val res0: com.github.kmizu.scomb.Result[Int] = Success(1) // 暗黙の乗算を優先した場合
scala> Calculator2.parse("8÷2(3+1)")
val res1: com.github.kmizu.scomb.Result[Int] = Success(16) // 除算を優先した場合
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment