parser-tsの関数
parser-ts本家は説明が少ない
一部、test caseが用意されていない関数があったり
test caseを見ただけじゃわかりにくかったり
docsを読んだだけじゃわかりにくかったり
このrepoと併用してこのノートを見ると良いかも知れないmrsekut.icon
説明がこのノートと、Repo内のコメントと二重管理になってダルいが、このノートの方を親切に書く
parserを組み立てていくときの気持ち
まず、特定の文字列の消費を成功するようなparserを組み立てる
次に、欲しいデータを返すように改変していく
特に名称が異なるもの
table:Parsecとの対応
parset-ts Parsec
either try
大きな区分
Alt
Alternative
Apply
Functor
Monad
combinators
Parser同士を組み合わせる
constructors
Parser以外の者からParserを作る
destructors
haskellでいうdo記法内のletによる変数定義ってどうやるの?
現状はこんな感じで入れ子でやってるが、もう少しきれいな書き方はできないのか
code:ts
const link: P.Parser<string, LinkN> = pipe(
bracketStart,
P.map(() => ({ type: 'link' as const, references: [] })),
P.chain(a =>
pipe(
string,
P.map(v => ({ ...a, value: v })),
P.chain(v =>
pipe(
bracketEnd,
P.map(() => v),
),
),
),
),
);
再起の仕方
「このparserを繰り返し適用する」
みたいなことはできるのか
行末になるまで、これを繰り返し、をやりたい
P.manyTill(notation, C.char('\n'));とかかなmrsekut.icon
Char
combinators
alphanum
digit
lower
many
many1
notAlphanum
notDigit
notLetter
notLower
notSpace
notUpper
space
upper
constructors
char
notChar
notOneOf
oneOf
model
Char (type alias)
utils
letter
String
combinators
doubleQuotedString
float
int
many
many1
maybe
notSpaces
notSpaces1
spaces
spaces1
constructors
oneOf
string
destructors
fold([...p])
普通に連結
全ての...pが、頭から順番に実行される
全体でparseした文字列を返す
chainを簡潔に書けるイメージかなmrsekut.icon
Parser調べたいやつ
Alt
alt★
Alternative
zero
Applicative
of
Apply
ap :: p a -> p (a -> b) -> p b
parserの機能としては、p aと同一視する
p aのparseを行って、Rightだったらその結果にa -> bを適用する
結果的にParser<a, b>な型のparserになる
apFirst★
apSecond★
Functor
map
parseの結果を加工する
Monad
chain
chainFirst★
flatten★
combinators
between, surroundedBy
前者は同じ記号
e.g. |2|
後者は異なる記号
e.g. (2)
cut, cutWith, either
だいたいわかったmrsekut.icon
eof
end of the stream
expected(p, errorMsg: string)
pと同じ挙動をする
ただし、失敗した場合はerrorMsgを返す
一般ユーザーが使うのかは不明
filter p f
雑にpでparseした後に、その結果をfでfilteringする感じ
item
何でも良いので一文字消化
故に引数を取らない
lookAhead p
前方にpを満たすものがあるかどうかを確認する
確認するだけで消費はしない
「確認してなかったときはhogeをする」はどう書けばいい #?? many, many1
繰り返す
many1Till, manyTill
tillに至るまで繰り返す
消費しきったら停止する
takeUntil
many1Tillの述語版
使うことないと思う
maybe
monoidとparserを引数に取る
parserが失敗した場合はmonoidを返す
monoidはempty(default値)を意味する
失敗してもRight
optional
あってもなくてもいい
正規表現で言う「?」
実際にあったかどうかはOption型で結果を示す
Eitherではなく
sepBy, sepBy1, sepByCut
区切り
リストの中の,とかに使う
seq
複数のparserを連結する
内部のどれか一つでも失敗すれば、全体としても失敗する
最後のparserの値のみを返す
だから、全体の文字列を返すなどしたいときは、何かしら工夫が必要
どうすればいいだろうmrsekut.icon
引数をうまく使うんだろうけど
foldと異なり、前のparserの値を受け取れる
withStart
pを実行するが、返り値にcursor開始位置を伴う
constructors
fail
何も消費せずに、ただfatal errorを起こす
failAt
sat
charの代わりに述語関数が使える
一文字のみ消化する
C.charを使えばいいのでほぼ使うこと無いのでは?
succeed
何も消費しない
必ず成功する
引数に取った文字列をそのまま返す
P.stringの内部で使われている
内部では一文字ごとparseするが、そのparser全体としては、一定量の文字列を返却したいときなどに有用
chainと最後で使う感じかなmrsekut.icon
instances
Alt
Alternative
Applicative
ChainRec
Functor
Monad
URI
URI (type alias)
getMonoid
getSemigroup
parser
model
Parser (interface)
utils
bind
bindTo
エラーの種類が複数あるっぽい
fatal error
cut系のcombinatorで返される
その場でエラーを返し、それ以降の文字列をparseしない
bindToとbind
code:ts
const statement = (cmd: string) =>
pipe(
whitespaceSurrounded(S.string(cmd)), // ①
P.bindTo('command'), // ②
P.bind('args', () => P.many(whitespaceSurrounded(argument))), // ③
);
bindToはpipeの一つ前の結果を、引数のkeyの値にする
上のコードなら①の結果を"command"の値にする
bindは、第1引数のkeyに、第2引数の結果を入れる
上のコードなら"args"に() => P.many(..)の結果を入れる
constructors
fail
succeed
Parserモナドのof
全角に対応させる
Monoidの嬉しさ
exampleのやつとか
ネストした括弧をparseしたい
Refinementとは
P.filterに出てきた
Predicateとは
P.filterに出てきた
ユーザー向けに用意されているものと、開発向けに用意されているものの判別が付きづらい
別にこういう分断はないのか?
テストがないものがたまにある
maybeとか
Stream
code:ts
export interface Stream<A> {
readonly buffer: Array<A>
readonly cursor: number
}
よく知らんが、型からあらかた推測できるmrsekut.icon
テストコードなどで使用する
ParseResult
success
value
next
start