Concurrent Clean : Parser Library

HaskellとはParsecを使うための言語だ」といわれているかは知らないが、さすがに使ったことがないのはまずかろうということで、CleanのParser Libraryを使ってみた。
確か、前にも使おうとして、軽い挫折をしたような気がしたけれど、
http://sky.zero.ad.jp/~zaa54437/programming/clean/CleanBook/part2/Chap5.html
に書いてあるのと、Parser Libraryのは若干違って、その辺に戸惑いながら、ライブラリのソースコードを直接読みながら何とか次のプログラムを作成。

module Main

import StdEnv, Parsers

Start = parse p ['1+2*3'] "expression" "number"

num = satisfy (flip isMember ['0123456789']) <@ digitToInt
opr = satisfy (flip isMember ['+-*/%'])

p = expr  <&> \i =
    empty <@  \_ = i

/*
 * expr = num opr expr | num
 */
expr =   num  <&> (\i =
         opr  <&> (\o =
         expr <@  (\j = arith o i j)))
     <|> num

arith '+' = (+)
arith '-' = (-)
arith '*' = (*)
arith '/' = (/)
arith '%' = (rem)

む、これだと、演算子優先順位が効かないで、全て右結合になってしまうな。

      • -

S式をパースしてみた

module SExpr

import StdEnv, OptEnv, Parsers

Start = parse (first sexpr_all) ['(define (f a b) (+ a b))'] "" ""

sexpr_all = sexpr <&> \t =
            empty <@  \_ = t

sexpr =  symbol '(' &> list <& symbol ')' <@ (\tt = B tt)
     <|> atom                             <@ (\t  = L t )

atom = <+> (satisfy \x = not (isMember x ['()'])
                      && isPrint x
                      && not (isSpace x)) <@ \t = toString t

list =  sexpr          <&> \t  =
        <*> (ds sexpr) <@  \tt = [t:tt]

::Tree a = L a | B [Tree a]

まだ、目と頭が慣れなくてくらくらする。