7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Scala: パーサコンビネータの | と ^^ の組み合わせは注意

Posted at

昨日 面倒くさいパーサの実装もDSLで書くだけ!そう、Scalaならね - Qiita という記事を書いたが、パーサコンビネータではまった点があった。

パーサコンビネータの | (alternative) と ^^ (eye brows)の組み合わせで、最後の alternative にしか eye brows の関数が適用されないという問題です。

このサンプルコードを御覧ください。入力 "1"Number(1) に変換されますが、入力 "0" は変換されません。

import scala.util.parsing.combinator._

case class Number(number: String)

object Tokenize extends RegexParsers {
	def number = "0" | "1" ^^ { Number(_) }
	def apply(input: String) = parseAll(number, input)
}

println(Tokenize("0"))                            //> [1.2] parsed: 0
println(Tokenize("1"))                            //> [1.2] parsed: Number(1)

これは、^^ オペレータが "1" のメソッドであるためのようです。カッコを補って表現すると次のような解釈になるわけですね。

def number = "0" | "1".^^({ Number(_) })

この解釈を回避するには2つ方法があります。

  1. alternativeそれぞれに ^^ をつける
  2. alternativeをすべて ( ) で囲んで評価の順番を変える

1の例

import scala.util.parsing.combinator._

case class Number(number: String)

object Tokenize extends RegexParsers {
	def number = "0" ^^ { Number(_) } | "1" ^^ { Number(_) }
	def apply(input: String) = parseAll(number, input)
}

println(Tokenize("0"))                            //> [1.2] parsed: Number(0)
println(Tokenize("1"))                            //> [1.2] parsed: Number(1)

2の例

import scala.util.parsing.combinator._

case class Number(number: String)

object Tokenize extends RegexParsers {
	def number = ("0" | "1") ^^ { Number(_) }
	def apply(input: String) = parseAll(number, input)
}

println(Tokenize("0"))                            //> [1.2] parsed: Number(0)
println(Tokenize("1"))                            //> [1.2] parsed: Number(1)

|^^ の評価の順番を常に意識していないとはまるので、|を使うときはいつもカッコをつけるようにしておいたほうが考えなくていいので楽かもしれませんね。

7
7
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?