generated at
Parsec
HaskellでParserを作るライブラリ
今はすでにメンテナンスモードらしい
Megaparsecを使おう、とのことらしい


Parsecを使ったparserの作り方には2種類ある
関数を組み合わせて0から作る
パーサコンビネータの勉強には良い
予め用意されたものを拡張する
言語ごとのTokenなどは共通していることが多いのでこっちでやったほうが楽
有名な言語なら定義ファイルが用意されているので、
「あの言語に似てるけど、微妙に異なる言語」を作るなら圧倒的に楽
↑今の理解なので間違っているかもしれないmrsekut
前者でも後者でもParsecの基本的な関数を使う
つまり、前者についてのみの解説記事は、後者を選択する場合も役に立つ
逆は成り立たない
後者はレコードに設定を記述する



以下の4つからなる(?)
runParserT関数
一つのparserに対し引数を渡してパターンマッチを行う
paraseTestやparse関数の内部で使われている
単純なparser
一文字をパースする関数
char, digitなど
複数文字をパースする関数
stringのみ
satisfy関数によって定義されている
上の単純なparserを組み合わせて複雑なparserを作る関数
それによって作られたparserを更にパーサコンビネータを使ってparserを作る
最終的に一つの複雑なparserになる
これをrunParserTにわたす


spacesやたら出てくる問題
slackで聞いたら@igrepさんに教えてもらった
『プログラミングHaskell』に書いてあるらしい
元のコード
hs
-- factor ::= '(' expr ')' | nat factor :: Parser Expr factor = (spaces *> char '(' *> spaces *> expr <* spaces <* char ')' <* spaces) <|> spaces *> nat <* spaces -- nat ::= '0' | '1' | '2' | ... nat :: Parser Expr nat = Nat . read <$> many1 digit
書き換えたコード
hs
-- factor ::= '(' expr ')' | nat factor :: Parser Expr factor = (spaces *> char '(' *> skipW expr <* char ')' <* spaces) <|> nat -- nat ::= '0' | '1' | '2' | ... nat :: Parser Expr nat = skipW $ Nat . read <$> many1 digit -- 前後のwhite_spacesをskipするラッパーを作る skipW :: Parser Expr -> Parser Expr skipW p = spaces *> p <* spaces


ParsecT s u m aモナドがわからない
読んで実装しよう
chainlがなにしてるかわからない
↑のページの中のリンクを見てスクラッチで書いてみよう
テストの書き方がわからない
monkey-nimで書いたときのようなノリで書きたい
まだ調べていない
hccで定義しているexprなどの関数は、
「パーサー」?
「パーサコンビネータ」?
これらのなかでmanyなどのパーサコンビネータはどうやって使う?
これらの見分け方は?





雑メモ
以下同じ
hs
relational :: Parser Expr relational = do a <- spaces *> add r <- relOp b <- add return $ r a b
hs
relational :: Parser Expr relational = do a <- spaces *> add r <- relOp r a <$> add


関連parserライブラリ

Parsecの再実装をする



参考
ここのおかげでParser型の意味がわかった
↑ここをドキュメント代わりに使うと良いかも?
そうでもないかもmrsekut