はわわーっ

はわわわわっ

trifectaでスタイルの設定とか

やってみた。
とりあえず動くようになったけど、いろいろ間違ってるかもしれない。。。

トークンパーザにコメントを解釈させるようにする。
trifectaにはParserっていうのがあるけど、コメントは設定できないっぽいので自分で型を作る必要がある。

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

import Control.Applicative
import Text.Trifecta

newtype FooParser a = FooParser { unFooParser :: Parser a }
                        deriving (Functor, Monad, Applicative, Alternative,
                                  Parsing, CharParsing)

で、これをTokenParsingのインスタンスにしてsomeSpaceを定義する。
このときにCommentStyleを作ってbuildSomeSpaceParserを使う。
CommentStyleはText.Parser.Token.Styleを見つつ、せっかくなのでLensを使う。

import Control.Lens
import Data.Char (isSpace)
import Text.Parser.Token.Style

instance TokenParsing FooParser where
  someSpace = buildSomeSpaceParser (skipSome (satisfy isSpace)) $
                commentLine .~ ";" $ emptyCommentStyle

;で行コメントになるようにしてみた。
これでトークンパーザがコメントを解釈してくれるようになる。

あと、DeltaParsingっていうのもあるんだけど、これはなんなんだろう。。

使ってみる。
parseTestとかはParserのほうを引数に取るので自分で作ったやつを変換する必要がある。

>>> parseTest (unFooParser (whiteSpace *> many natural)) "1 2 3"
[1,2,3]
>>> parseTest (unFooParser (whiteSpace *> many natural)) "1 ;2 3"
[1]
>>> parseTest (unFooParser (whiteSpace *> many natural)) "1 ;2 \n3"
[1,3]

ちょっと分かりづらいけど、;から改行までがコメントになってる。

identifierのトークンパーザを作ってみる。
Text.Parser.Tokenの最初の方に書いてあるようにスタイルにidentを適用させる。
ついでにトークンパーザになるようにtokenもつける。

identifier :: FooParser String
identifier = token $ ident $ 
               styleStart .~ (letter <|> sym) $
               styleLetter .~ (alphaNum <|> sym) $ emptyIdents
  where sym = oneOf "!$%^*+-/:<=>?@^_~"

使ってみる。

>>> parseTest (unFooParser (whiteSpace *> many identifier)) "foo bar baz"
["foo","bar","baz"]
>>> parseTest (unFooParser (whiteSpace *> many identifier)) "foo ;bar baz"
["foo"]
>>> parseTest (unFooParser (whiteSpace *> many identifier)) "foo ;bar \nbaz"
["foo","baz"]

とりあえず、こんな感じで動くようになった。

ソース全体

{-# LANGUAGE GeneralizedNewtypeDeriving #-}


import Control.Applicative
import Control.Lens
import Data.Char (isSpace)
import Text.Trifecta
import Text.Parser.Token.Style

newtype FooParser a = FooParser { unFooParser :: Parser a }
                      deriving (Functor, Monad, Applicative, Alternative,
                                Parsing, CharParsing)

instance TokenParsing FooParser where
  someSpace = buildSomeSpaceParser (skipSome (satisfy isSpace)) $
                commentLine .~ ";" $ emptyCommentStyle

identifier :: FooParser String
identifier = token $ ident $
               styleStart .~ (letter <|> sym) $
               styleLetter .~ (alphaNum <|> sym) $ emptyIdents
  where sym = oneOf "!$%^*+-/:<=>?@^_~"