プログラミングHaskell 8.10 練習問題

1. def nat: Parser[Int] = for { xs <- many1(digit) } yield xs.mkString.toInt def neg: Parser[Int] = for { _ <- symbol("-") n <- nat } yield -n def int: Parser[Int] = neg +++ nat 2. def comment: Parser[Unit] = for { _ <- symbol("--") _ <- m…

プログラミングHaskell 8.10 練習問題

def nat: Parser[Int] = for { xs <- many1(digit) } yield xs.mkString.toInt def neg: Parser[Int] = for { _ <- symbol("-") n <- nat } yield -n def int: Parser[Int] = neg +++ nat def comment: Parser[Unit] = for { _ <- symbol("--") _ <- many(sa…

プログラミングHaskell 8.8 数式

自然数と加算演算子、乗算演算子、および括弧からなる数式を考える。 加算演算子と乗算子は右結合とし、乗算演算子は加算演算子よりも高い結合順序を持つとする。 「2 + 3 + 4」 は「2 + (3 + 4)」 「2 * 3 + 4」は 「(2 * 3) + 4」 を意味する。 BNFで表し…

プログラミングHaskell 8.7 空白の扱い

実用的なパーサーは、入力文字列中の「トークン」の前後に任意の空白を許す。...(中略)...あるトークンのパーサーを適用する際、前後の空白を無視する部品を定義する。 def token[A](p: Parser[A]): Parser[A] = for { _ <- space v <- p _ <- space } yield…

プログラミングHaskell 8.6 パーサーの部品

述語pを満足する一文字用のパーサー sat p を定義する。 def sat(p: Char => Boolean): Parser[Char] = { item.flatMap(x => p(x) match { case true => succeed(x) case false => failure }) } これを使えば、数字・アルファベットとかのパーサーも。 def d…

プログラミングHaskell 8.5 選択

だいぶ間があいたけど、引き続き。 パーサーを結合させるもう一つの自然な方法は、一番目のパーサーを入力文字列に適用し、もし失敗したら、代わりに二番目のパーサーを適用することである。 +++(「または」と読む)を定義する。 def +++[A](p: Parser[A])(…

プログラミングHaskell 8.4 連結

ひきつづきプログラミングHaskellをScalaで書き換えつつ読んでいきます。 おそらく、二つのパーサーを組み合わせる最も単純な方法は、一方の後に他方を適用することだろう。一番目のパーサーの返す出力文字列が、二番目のパーサーの入力文字列となる。 連結…

基本的なパーサー

プログラミングHaskellより。 ここで、他のパーサーを構築するのに利用する基本的なパーサー三つを定義しよう。 ちょっと本の表記から変えます。 returnが予約語なので、メソッド名をreturn -> succeedにします。 String => List[Char]への変換は明示的に行…

パーサーの型

プログラミングHaskellより。 でもScalaで書いてみます。 適切な構文木の型Treeが与えられたとすると、パーサーはString -> Treeを持つ関数として表現できる。 type Parser = String => Tree しかし、一般的にはパーサーがすべての文字列を使い切るとは限ら…

パーサーとは (1)

プログラミングHaskellより。 パーサーとは、文字列を取り、文字列の文法構造を表現する曖昧さのない構文木を返すプログラムである。 曖昧さをなくすってのが大事なんだろう。 たとえば、文字列 "2 * 3 + 4"が与えられたとき、数式のパーサーは以下のような…

パーサーを書けるようになりたい

パーサーを書けるようになりたい、と思いました。 JSONとかxmlとかcsvとか。 以下のようなことをフワ〜っと思っていました。 社会人になって2年半、もうプログラミング歴も同じだけ経ったから(やばい)、なにか動くものを作りたい。 全く新しいものを作るっ…